r"""Converts a (differentiable) dense tensor or a :attr:`MinkowskiEngine.TensorField` to a :attr:`MinkowskiEngine.SparseTensor`. For dense tensor, the input must have the BxCxD1xD2x....xDN format. :attr:`remove_zeros` (bool): if True, removes zero valued coordinates. If False, use all
| 349 | |
| 350 | |
| 351 | class MinkowskiToSparseTensor(MinkowskiModuleBase): |
| 352 | r"""Converts a (differentiable) dense tensor or a :attr:`MinkowskiEngine.TensorField` to a :attr:`MinkowskiEngine.SparseTensor`. |
| 353 | |
| 354 | For dense tensor, the input must have the BxCxD1xD2x....xDN format. |
| 355 | |
| 356 | :attr:`remove_zeros` (bool): if True, removes zero valued coordinates. If |
| 357 | False, use all coordinates to populate a sparse tensor. True by default. |
| 358 | |
| 359 | If the shape of the tensor do not change, use `dense_coordinates` to cache the coordinates. |
| 360 | Please refer to tests/python/dense.py for usage. |
| 361 | |
| 362 | Example:: |
| 363 | |
| 364 | >>> # Differentiable dense torch.Tensor to sparse tensor. |
| 365 | >>> dense_tensor = torch.rand(3, 4, 11, 11, 11, 11) # BxCxD1xD2x....xDN |
| 366 | >>> dense_tensor.requires_grad = True |
| 367 | |
| 368 | >>> # Since the shape is fixed, cache the coordinates for faster inference |
| 369 | >>> coordinates = dense_coordinates(dense_tensor.shape) |
| 370 | |
| 371 | >>> network = nn.Sequential( |
| 372 | >>> # Add layers that can be applied on a regular pytorch tensor |
| 373 | >>> nn.ReLU(), |
| 374 | >>> MinkowskiToSparseTensor(remove_zeros=False, coordinates=coordinates), |
| 375 | >>> MinkowskiConvolution(4, 5, kernel_size=3, dimension=4), |
| 376 | >>> MinkowskiBatchNorm(5), |
| 377 | >>> MinkowskiReLU(), |
| 378 | >>> ) |
| 379 | |
| 380 | >>> for i in range(5): |
| 381 | >>> print(f"Iteration: {i}") |
| 382 | >>> soutput = network(dense_tensor) |
| 383 | >>> soutput.F.sum().backward() |
| 384 | >>> soutput.dense(shape=dense_tensor.shape) |
| 385 | |
| 386 | """ |
| 387 | |
| 388 | def __init__(self, remove_zeros=True, coordinates: torch.Tensor = None): |
| 389 | MinkowskiModuleBase.__init__(self) |
| 390 | assert ( |
| 391 | remove_zeros and coordinates is None |
| 392 | ), "The coordinates argument cannot be used with remove_zeros=True. If you want to use the coordinates argument, provide remove_zeros=False." |
| 393 | self.remove_zeros = remove_zeros |
| 394 | self.coordinates = coordinates |
| 395 | |
| 396 | def forward(self, input: Union[TensorField, torch.Tensor]): |
| 397 | if isinstance(input, TensorField): |
| 398 | return input.sparse() |
| 399 | elif isinstance(input, torch.Tensor): |
| 400 | # dense tensor to sparse tensor conversion |
| 401 | if self.remove_zeros: |
| 402 | return to_sparse(input) |
| 403 | else: |
| 404 | return to_sparse_all(input, self.coordinates) |
| 405 | else: |
| 406 | raise ValueError( |
| 407 | "Unsupported type. Only TensorField and torch.Tensor are supported" |
| 408 | ) |
no outgoing calls