Yeqing0814's picture
Upload folder using huggingface_hub
a6dd040 verified
# Copyright (c) 2020 NVIDIA CORPORATION.
# Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
# Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
# of the code.
import unittest
import numpy as np
import torch
from MinkowskiEngine import (
SparseTensor,
SparseTensorOperationMode,
SparseTensorQuantizationMode,
set_sparse_tensor_operation_mode,
clear_global_coordinate_manager,
is_cuda_available,
)
from MinkowskiEngine.utils import batched_coordinates, sparse_quantize, sparse_collate
from tests.python.common import data_loader, load_file
class SparseTensorTestCase(unittest.TestCase):
def test(self):
print(f"{self.__class__.__name__}: test SparseTensor")
coords, feats, labels = data_loader(nchannel=2)
input = SparseTensor(feats, coordinates=coords)
print(input)
def test_empty(self):
print(f"{self.__class__.__name__}: test_empty SparseTensor")
feats = torch.FloatTensor(0, 16)
coords = torch.IntTensor(0, 4)
input = SparseTensor(feats, coordinates=coords)
print(input)
def test_tensor_stride(self):
print(f"{self.__class__.__name__}: test_tensor_stride SparseTensor")
feats = torch.FloatTensor(4, 16)
coords = torch.IntTensor(
[[0, 4, 2, 1], [0, 4, 0, 0], [0, 4, 4, 4], [0, 4, 4, 7]]
)
print(coords)
input = SparseTensor(feats, coordinates=coords, tensor_stride=4)
self.assertEqual(input.tensor_stride, [4, 4, 4])
print(input)
def test_force_creation(self):
print(f"{self.__class__.__name__}: test_force_creation")
coords, feats, labels = data_loader(nchannel=2)
input1 = SparseTensor(feats, coordinates=coords)
input2 = SparseTensor(
feats, coordinates=coords, coordinate_manager=input1.coordinate_manager
)
print(input1.coordinate_map_key, input2.coordinate_map_key)
def test_device(self):
print(f"{self.__class__.__name__}: test_device SparseTensor")
if not is_cuda_available():
return
coords = torch.IntTensor(
[[0, 1], [0, 1], [0, 2], [0, 2], [1, 0], [1, 0], [1, 1]]
)
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T
SparseTensor(feats.to(0), coords.to(0))
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T.to(0)
st = SparseTensor(feats, coords, device=feats.device)
print(st)
def test_device_unique(self):
print(f"{self.__class__.__name__}: test_device_unique SparseTensor")
if not is_cuda_available():
return
coords = torch.IntTensor(
[[0, 1], [0, 2], [0, 3], [0, 4], [1, 0], [1, 1], [1, 2]]
)
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T
SparseTensor(feats.to(0), coords.to(0))
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T.to(0)
st = SparseTensor(feats, coords, device=feats.device)
print(st)
def test_device2(self):
print(f"{self.__class__.__name__}: test_device2 SparseTensor")
if not is_cuda_available():
return
coordinates = np.random.rand(8192,3) * 200
quant_coordinates, quant_features = sparse_quantize(coordinates, coordinates)
bcoords, bfeats = sparse_collate([quant_coordinates], [quant_features])
bcoords, bfeats = bcoords.cuda(), bfeats.cuda()
print(bcoords, bfeats)
SparseTensor(bfeats, bcoords)
def test_quantization(self):
print(f"{self.__class__.__name__}: test_quantization")
coords, feats, labels = data_loader(nchannel=2)
# create duplicate coords
coords[0] = coords[1]
coords[2] = coords[3]
input = SparseTensor(feats, coordinates=coords)
self.assertTrue(len(input) == len(coords) - 2)
input = SparseTensor(
feats,
coordinates=coords,
quantization_mode=SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE,
)
self.assertTrue(len(coords) == 16)
self.assertTrue(len(input) == 14)
# 1D
coords = torch.IntTensor(
[[0, 1], [0, 1], [0, 2], [0, 2], [1, 0], [1, 0], [1, 1]]
)
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T
# 0.5, 2.5, 5.5, 7
sinput = SparseTensor(
coordinates=coords,
features=feats,
quantization_mode=SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE,
)
self.assertTrue(len(sinput) == 4)
self.assertTrue(0.5 in sinput.features)
self.assertTrue(2.5 in sinput.features)
self.assertTrue(5.5 in sinput.features)
self.assertTrue(7 in sinput.features)
self.assertTrue(len(sinput.slice(sinput)) == len(coords))
def test_quantization_gpu(self):
print(f"{self.__class__.__name__}: test_quantization_gpu")
coords, feats, labels = data_loader(nchannel=2)
# create duplicate coords
coords[0] = coords[1]
coords[2] = coords[3]
input = SparseTensor(feats, coordinates=coords)
self.assertTrue(len(input) == len(coords) - 2)
input = SparseTensor(
feats,
coordinates=coords,
quantization_mode=SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE,
device="cuda",
)
self.assertTrue(len(coords) == 16)
self.assertTrue(len(input) == 14)
print(input)
# 1D
coords = torch.IntTensor(
[[0, 1], [0, 1], [0, 2], [0, 2], [1, 0], [1, 0], [1, 1]]
)
feats = torch.FloatTensor([[0, 1, 2, 3, 5, 6, 7]]).T
# 0.5, 2.5, 5.5, 7
sinput = SparseTensor(
coordinates=coords,
features=feats,
quantization_mode=SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE,
device="cuda",
)
print(sinput)
self.assertTrue(len(sinput) == 4)
self.assertTrue(0.5 in sinput.features)
self.assertTrue(2.5 in sinput.features)
self.assertTrue(5.5 in sinput.features)
self.assertTrue(7 in sinput.features)
self.assertTrue(len(sinput.slice(sinput)) == len(coords))
def test_extraction(self):
print(f"{self.__class__.__name__}: test_extraction")
coords = torch.IntTensor([[0, 0], [0, 1], [0, 2], [2, 0], [2, 2]])
feats = torch.FloatTensor([[1.1, 2.1, 3.1, 4.1, 5.1]]).t()
X = SparseTensor(feats, coords)
C0 = X.coordinates_at(0)
F0 = X.features_at(0)
self.assertTrue(0 in C0)
self.assertTrue(1 in C0)
self.assertTrue(2 in C0)
self.assertTrue(1.1 in F0)
self.assertTrue(2.1 in F0)
self.assertTrue(3.1 in F0)
CC0, FC0 = X.coordinates_and_features_at(0)
self.assertTrue((C0 == CC0).all())
self.assertTrue((F0 == FC0).all())
coords, feats = X.decomposed_coordinates_and_features
for c, f in zip(coords, feats):
self.assertEqual(c.numel(), f.numel())
print(c, f)
self.assertEqual(len(coords[0]), 3)
self.assertEqual(len(coords[1]), 0)
self.assertEqual(len(coords[2]), 2)
if not is_cuda_available():
return
coords = torch.IntTensor([[0, 0], [0, 1], [0, 2], [2, 0], [2, 2]])
feats = torch.FloatTensor([[1.1, 2.1, 3.1, 4.1, 5.1]]).t()
X = SparseTensor(feats, coords, device=0)
coords, feats = X.decomposed_coordinates_and_features
for c, f in zip(coords, feats):
self.assertEqual(c.numel(), f.numel())
print(c, f)
self.assertEqual(len(coords[0]), 3)
self.assertEqual(len(coords[1]), 0)
self.assertEqual(len(coords[2]), 2)
def test_features_at_coordinates(self):
print(f"{self.__class__.__name__}: test_features_at_coordinates")
coords = torch.IntTensor([[0, 0], [0, 1], [0, 2], [2, 0], [2, 2]])
feats = torch.FloatTensor([[1.1, 2.1, 3.1, 4.1, 5.1]]).t()
X = SparseTensor(features=feats, coordinates=coords)
feats = X.features_at_coordinates(
torch.FloatTensor([[0, 0], [0, 1], [0, 2], [2, 2], [0, 0], [0, 0.5]])
).flatten()
self.assertTrue(feats[0] == 1.1)
self.assertTrue(feats[3] == 5.1)
self.assertTrue(feats[4] == 1.1)
def test_decomposition(self):
print(f"{self.__class__.__name__}: test_decomposition")
coords, colors, pcd = load_file("1.ply")
colors = torch.from_numpy(colors)
for batch_size in [1, 5, 10, 20, 40]:
for voxel_size in [0.02]:
dcoords = torch.from_numpy(np.floor(coords / voxel_size)).int()
bcoords = batched_coordinates([dcoords for i in range(batch_size)])
feats = torch.cat([colors for b in range(batch_size)], 0)
sinput = SparseTensor(feats, bcoords)
(
decomposed_coords,
decomposed_feats,
) = sinput.decomposed_coordinates_and_features
print([len(c) for c in decomposed_coords])
print([len(f) for f in decomposed_feats])
self.assertEqual(len(decomposed_coords), batch_size)
self.assertEqual(len(decomposed_feats), batch_size)
def test_decomposition_gpu(self):
print(f"{self.__class__.__name__}: test_decomposition_gpu")
if not torch.cuda.is_available():
return
coords, colors, pcd = load_file("1.ply")
colors = torch.from_numpy(colors)
for batch_size in [5, 10, 20, 40]:
for voxel_size in [0.02]:
dcoords = torch.from_numpy(np.floor(coords / voxel_size)).int()
bcoords = batched_coordinates([dcoords for i in range(batch_size)])
feats = torch.cat([colors for b in range(batch_size)], 0)
sinput = SparseTensor(feats.to(0), bcoords.to(0))
(
decomposed_coords,
decomposed_feats,
) = sinput.decomposed_coordinates_and_features
print([len(c) for c in decomposed_coords])
print([len(f) for f in decomposed_feats])
self.assertEqual(len(decomposed_coords), batch_size)
self.assertEqual(len(decomposed_feats), batch_size)
def test_operation_mode(self):
print(f"{self.__class__.__name__}: test_operation_mode")
# Set to use the global sparse tensor coords manager by default
set_sparse_tensor_operation_mode(
SparseTensorOperationMode.SHARE_COORDINATE_MANAGER
)
coords, feats, labels = data_loader(nchannel=2)
# Create a sparse tensor on two different coordinates.
A = SparseTensor(torch.rand(feats.shape), coordinates=coords)
B = SparseTensor(
torch.rand(4, 2),
coordinates=torch.IntTensor([[0, 0, 0], [1, 1, 1], [0, 1, 0], [1, 0, 1]]),
)
self.assertTrue(A.coordinate_manager == B.coordinate_manager)
A.requires_grad_(True)
B.requires_grad_(True)
C = A + B
C.F.sum().backward()
self.assertTrue(torch.all(A.F.grad == 1).item())
self.assertTrue(torch.all(B.F.grad == 1).item())
C = A - B
C = A * B
C = A / B
# Inplace
A.requires_grad_(False)
D = SparseTensor(
torch.rand(feats.shape),
coordinate_map_key=A.coordinate_map_key,
coordinate_manager=A.coordinate_manager,
)
A -= D
A *= D
A /= D
clear_global_coordinate_manager()
set_sparse_tensor_operation_mode(
SparseTensorOperationMode.SEPARATE_COORDINATE_MANAGER
)