NVIDIA / MinkowskiEngine

Minkowski Engine is an auto-diff neural network library for high-dimensional sparse tensors
https://nvidia.github.io/MinkowskiEngine
Other
2.43k stars 360 forks source link

insert_and_map not working as intented #451

Open aniqueakhtar opened 2 years ago

aniqueakhtar commented 2 years ago

Code # 1:

coordinates = torch.IntTensor([[0, 0], [0, 0], [0, 1], [0, 2]])
coordinates = coordinates.to(device)
manager = ME.CoordinateManager(D=1)
key, (unique_map, inverse_map) = manager.insert_and_map(coordinates, [1])
print(key)
print(unique_map)
print(inverse_map)
torch.all(coordinates[unique_map] == manager.get_coordinates(key))
torch.all(coordinates == coordinates[unique_map][inverse_map])

Output:

coordinate map key:[1]
tensor([0, 2, 3], device='cuda:0')
tensor([0, 0, 1, 2], device='cuda:0')
tensor(True, device='cuda:0')
tensor(True, device='cuda:0')

Code # 2:

coordinates = torch.IntTensor([[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3]])
coordinates = coordinates.to(device)
manager = ME.CoordinateManager(D=1)
key, (unique_map, inverse_map) = manager.insert_and_map(coordinates, [1])
print(key)
print(unique_map)
print(inverse_map)
torch.all(coordinates[unique_map] == manager.get_coordinates(key))
torch.all(coordinates == coordinates[unique_map][inverse_map])

Output:

coordinate map key:[1]
tensor([0, 1, 2, 3, 4, 5, 6, 7], device='cuda:0')
tensor([], device='cuda:0', dtype=torch.int64)
tensor(True, device='cuda:0')
RuntimeError: The size of tensor a (8) must match the size of tensor b (0) at non-singleton dimension 0

For some reason, insert_and_map does not seem to work for the second case. I have also tried it on three-dimensional data. insert_and_map never seems to give the right answer.

@chrischoy Is there a bug in the code or has it been removed from the library?

--

I have one further question. My goal is to obtain the unique_map and inverse_map of passing a 16x16x16 kernel with stride 16 over the input 3D tensor. For the same input, I want to pass a 16x16x16 kernel with stride 16 with an offset of 8 over the same input. Basically wanting to divide the input into patches of 16x16x16, and also in patched of 16x16x16 with an offset of 8. What would be the best way to achieve this?

My current code looks something like this:

x = ME.SparseTensor(feats, coordinates=coords + offset, device=device)
conv = ME.MinkowskiConvolution(1, 1, kernel_size=16, stride=16, bias=False, dimension=D).to(device)
output = conv(x)

iC = x.C.cpu().numpy()
oC = output.C.cpu().numpy()
print("Input Coordinates")
print(iC)
print("Output Coordinates")
print(oC)

print("Testing Kernel Map")
kernel_maps = output.coordinate_manager.kernel_map(
            1,
            2,
            stride=16,
            kernel_size=16)

for kernel_index, in_out_map in kernel_maps.items():
    for i, o in zip(in_out_map[0], in_out_map[1]):
        print(kernel_index, iC[i], "->", oC[o])

First, I fail to understand how 1 and 2 are the CoordinateMapKey. How can I obtain these CoordinateMapKey?

Further, In this method, I have to manually add an offset. And in this method, I also have to have conv. Also, it seems difficult if I try to do this with a KernelGenerator (Maybe custom kernels no longer works in the newer version).

That is why I wanted to do it with insert_and_map but that doesn't seem to work either.

What would be the best method of achieving this?

Thank you for your time.