コード例 #1
0
    def test_coords_manager(self):
        key = CoordsKey(D=1)
        key.setTensorStride(1)

        cm = CoordsManager(D=1)
        coords = (torch.rand(5, 1) * 100).int()
        cm.initialize(coords, key)

        print(key)
        print(cm)
コード例 #2
0
    def forward(ctx,
                input_features,
                average=True,
                mode=GlobalPoolingMode.AUTO,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert isinstance(mode, GlobalPoolingMode), \
            f"Mode must be an instance of GlobalPoolingMode, {mode}"

        ctx.in_coords_key = in_coords_key
        ctx.out_coords_key = out_coords_key

        ctx.in_feat = input_features
        ctx.average = average
        ctx.coords_manager = coords_manager
        ctx.mode = mode.value

        fw_fn = getattr(MEB,
                        'GlobalPoolingForward' + get_postfix(input_features))
        out_feat, num_nonzero = fw_fn(ctx.in_feat,
                                      ctx.in_coords_key.CPPCoordsKey,
                                      ctx.out_coords_key.CPPCoordsKey,
                                      ctx.coords_manager.CPPCoordsManager,
                                      ctx.average, ctx.mode)

        ctx.num_nonzero = num_nonzero

        return out_feat
コード例 #3
0
    def forward(self, input):
        assert isinstance(input, SparseTensor)
        assert input.D == self.dimension

        # Create a region_offset
        self.region_type_, self.region_offset_, _ = \
            self.kernel_generator.get_kernel(input.tensor_stride, self.is_transpose)

        if self.out_coords_key is None:
            out_coords_key = CoordsKey(input.coords_key.D)
        else:
            out_coords_key = self.out_coords_key
        # If the kernel_size == 1, the convolution is simply a matrix
        # multiplication
        if self.use_mm:
            outfeat = input.F.mm(self.kernel)
            out_coords_key = input.coords_key
        else:
            outfeat = self.conv.apply(
                input.F, self.kernel, input.tensor_stride, self.stride,
                self.kernel_size, self.dilation, self.region_type_,
                self.region_offset_, self.generate_new_coords,
                input.coords_key, out_coords_key, input.coords_man)
        if self.has_bias:
            outfeat += self.bias

        return SparseTensor(outfeat,
                            coords_key=out_coords_key,
                            coords_manager=input.coords_man)
コード例 #4
0
    def __truediv__(self, other):
        r"""
        Divide its feature by the corresponding feature of the other
        :attr:`MinkowskiEngine.SparseTensor` or a :attr:`torch.Tensor`
        element-wise. For coordinates that exist on one sparse tensor but not
        on the other, features of the counterpart that do not exist will be set
        to 0.
        """
        assert isinstance(other, (SparseTensor, torch.Tensor))
        if isinstance(other, SparseTensor):
            assert self.coords_man == other.coords_man, COORDS_MAN_DIFFERENT_ERROR

            if self.coords_key == other.coords_key:
                return SparseTensor(self._F / other.F,
                                    coords_key=self.coords_key,
                                    coords_manager=self.coords_man)
            else:
                # Generate union maps
                out_key = CoordsKey(self.coords_man.D)
                ins, outs = self.coords_man.get_union_map(
                    (self.coords_key, other.coords_key), out_key)
                N_out = self.coords_man.get_coords_size_by_coords_key(out_key)
                out_F = torch.zeros((N_out, self._F.size(1)),
                                    dtype=self.dtype,
                                    device=self.device)
                out_F[outs[0]] = self._F[ins[0]]
                out_F[outs[1]] /= other._F[ins[1]]
                return SparseTensor(out_F,
                                    coords_key=out_key,
                                    coords_manager=self.coords_man)
        else:  # when it is a torch.Tensor
            return SparseTensor(self._F / other,
                                coords_key=self.coords_key,
                                coords_manager=self.coords_man)
コード例 #5
0
    def forward(ctx,
                input_features,
                batch_size=0,
                average=True,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        ctx.in_coords_key = in_coords_key
        ctx.out_coords_key = out_coords_key

        ctx.in_feat = input_features
        out_feat = input_features.new()
        ctx.average = average
        ctx.num_nonzero = input_features.new()
        ctx.coords_manager = coords_manager

        D = in_coords_key.D
        fw_fn = getattr(MEB,
                        'GlobalPoolingForward' + get_postfix(input_features))
        fw_fn(D, ctx.in_feat, out_feat, ctx.num_nonzero,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_manager.CPPCoordsManager, batch_size, ctx.average)
        return out_feat
コード例 #6
0
    def forward(self, input, mask):
        r"""
        Args:
            :attr:`input` (:attr:`MinkowskiEnigne.SparseTensor`): a sparse tensor
            to remove coordinates from.

            :attr:`mask` (:attr:`torch.BoolTensor`): mask vector that specifies
            which one to keep. Coordinates with False will be removed.

        Returns:
            A :attr:`MinkowskiEngine.SparseTensor` with C = coordinates
            corresponding to `mask == True` F = copy of the features from `mask ==
            True`.

        Example::

            >>> # Define inputs
            >>> input = SparseTensor(feats, coords=coords)
            >>> # Any boolean tensor can be used as the filter
            >>> mask = torch.rand(feats.size(0)) < 0.5
            >>> pruning = MinkowskiPruning()
            >>> output = pruning(input, mask)

        """
        assert isinstance(input, SparseTensor)

        out_coords_key = CoordsKey(input.coords_key.D)
        output = self.pruning.apply(input.F, mask, input.coords_key,
                                    out_coords_key, input.coords_man)
        return SparseTensor(output,
                            coords_key=out_coords_key,
                            coords_manager=input.coords_man)
コード例 #7
0
    def forward(self, input):
        assert isinstance(input, SparseTensor)

        out_coords_key = CoordsKey(input.coords_key.D)
        output = self.pooling.apply(input.F, input.coords_key, out_coords_key,
                                    input.coords_man)

        return SparseTensor(output,
                            coords_key=out_coords_key,
                            coords_manager=input.coords_man)
コード例 #8
0
ファイル: MinkowskiPruning.py プロジェクト: GaoQiyu/Minkowski
    def forward(self, input, use_feat):
        assert isinstance(input, SparseTensor)
        assert input.D == self.dimension

        out_coords_key = CoordsKey(input.coords_key.D)
        output = self.pruning.apply(input.F, use_feat, input.coords_key,
                                    out_coords_key, input.coords_man)
        return SparseTensor(output,
                            coords_key=out_coords_key,
                            coords_manager=input.coords_man)
コード例 #9
0
    def forward(ctx,
                input_features,
                kernel,
                tensor_stride=1,
                stride=1,
                kernel_size=-1,
                dilation=1,
                region_type=0,
                region_offset=None,
                generate_new_coords=False,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        """
        region_type=0 HyperCube
        """
        # Prep arguments
        # Kernel shape (n_spatial_kernels, in_nfeat, out_nfeat)
        assert input_features.shape[1] == kernel.shape[1], \
            "The input shape " + str(list(input_features.shape)) + \
            " does not match the kernel shape " + str(list(kernel.shape))
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert in_coords_key.D == out_coords_key.D
        assert input_features.type() == kernel.type(), \
            f"Type mismatch input: {input_features.type()} != kernel: {kernel.type()}"
        if not input_features.is_contiguous():
            input_features = input_features.contiguous()

        tensor_stride, stride, kernel_size, dilation, region_type = prep_args(
            tensor_stride, stride, kernel_size, dilation, region_type,
            in_coords_key.D)

        if region_offset is None:
            region_offset = torch.IntTensor()

        ctx.in_feat = input_features
        ctx.kernel = kernel
        ctx = save_ctx(ctx, tensor_stride, stride, kernel_size, dilation,
                       region_type, in_coords_key, out_coords_key,
                       coords_manager)

        D = in_coords_key.D
        out_feat = input_features.new()

        fw_fn = getattr(
            MEB, 'ConvolutionTransposeForward' + get_postfix(input_features))
        fw_fn(ctx.in_feat, out_feat, kernel,
              convert_to_int_list(ctx.tensor_stride, D),
              convert_to_int_list(ctx.stride, D),
              convert_to_int_list(ctx.kernel_size, D),
              convert_to_int_list(ctx.dilation, D), region_type, region_offset,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_man.CPPCoordsManager, generate_new_coords)
        return out_feat
コード例 #10
0
    def forward(self, input):
        assert isinstance(input, SparseTensor)
        assert input.D == self.dimension

        out_coords_key = CoordsKey(input.coords_key.D)
        output = self.pooling.apply(input.F, self.batch_size, self.average,
                                    input.coords_key, out_coords_key,
                                    input.coords_man)

        return SparseTensor(
            output, coords_key=out_coords_key, coords_manager=input.coords_man)
コード例 #11
0
    def forward(ctx,
                in_feat,
                mode=GlobalPoolingMode.AUTO,
                in_coords_key=None,
                glob_coords_key=None,
                coords_manager=None):
        assert isinstance(mode, GlobalPoolingMode), \
            f"Mode must be an instance of GlobalPoolingMode, {mode}"
        if glob_coords_key is None:
            glob_coords_key = CoordsKey(in_coords_key.D)

        gpool_forward = getattr(MEB,
                                'GlobalPoolingForward' + get_postfix(in_feat))
        broadcast_forward = getattr(MEB,
                                    'BroadcastForward' + get_postfix(in_feat))
        add = operation_type_to_int(OperationType.ADDITION)
        multiply = operation_type_to_int(OperationType.MULTIPLICATION)

        mean = in_feat.new()
        num_nonzero = in_feat.new()

        cpp_in_coords_key = in_coords_key.CPPCoordsKey
        cpp_glob_coords_key = glob_coords_key.CPPCoordsKey
        cpp_coords_manager = coords_manager.CPPCoordsManager

        mean, num_nonzero = gpool_forward(in_feat, cpp_in_coords_key,
                                          cpp_glob_coords_key,
                                          cpp_coords_manager, True, mode.value)
        # X - \mu
        centered_feat = broadcast_forward(in_feat, -mean, add,
                                          cpp_in_coords_key,
                                          cpp_glob_coords_key,
                                          cpp_coords_manager)

        # Variance = 1/N \sum (X - \mu) ** 2
        variance, num_nonzero = gpool_forward(centered_feat**2,
                                              cpp_in_coords_key,
                                              cpp_glob_coords_key,
                                              cpp_coords_manager, True,
                                              mode.value)

        # norm_feat = (X - \mu) / \sigma
        inv_std = 1 / (variance + 1e-8).sqrt()
        norm_feat = broadcast_forward(centered_feat, inv_std, multiply,
                                      cpp_in_coords_key, cpp_glob_coords_key,
                                      cpp_coords_manager)

        ctx.mode = mode
        ctx.in_coords_key, ctx.glob_coords_key = in_coords_key, glob_coords_key
        ctx.coords_manager = coords_manager
        # For GPU tensors, must use save_for_backward.
        ctx.save_for_backward(inv_std, norm_feat)
        return norm_feat
コード例 #12
0
    def forward(ctx,
                in_feat,
                batch_size=0,
                in_coords_key=None,
                glob_coords_key=None,
                coords_manager=None):
        if glob_coords_key is None:
            glob_coords_key = CoordsKey(in_coords_key.D)

        gpool_forward = getattr(MEB,
                                'GlobalPoolingForward' + get_postfix(in_feat))
        broadcast_forward = getattr(MEB,
                                    'BroadcastForward' + get_postfix(in_feat))
        add = operation_type_to_int(OperationType.ADDITION)
        multiply = operation_type_to_int(OperationType.MULTIPLICATION)

        mean = in_feat.new()
        num_nonzero = in_feat.new()
        D = in_coords_key.D

        cpp_in_coords_key = in_coords_key.CPPCoordsKey
        cpp_glob_coords_key = glob_coords_key.CPPCoordsKey
        cpp_coords_manager = coords_manager.CPPCoordsManager

        gpool_forward(D, in_feat, mean, num_nonzero, cpp_in_coords_key,
                      cpp_glob_coords_key, cpp_coords_manager, batch_size,
                      True)
        # X - \mu
        centered_feat = in_feat.new()
        broadcast_forward(D, in_feat, -mean, centered_feat, add,
                          cpp_in_coords_key, cpp_glob_coords_key,
                          cpp_coords_manager)

        # Variance = 1/N \sum (X - \mu) ** 2
        variance = in_feat.new()
        gpool_forward(D, centered_feat**2, variance, num_nonzero,
                      cpp_in_coords_key, cpp_glob_coords_key,
                      cpp_coords_manager, batch_size, True)

        # norm_feat = (X - \mu) / \sigma
        inv_std = 1 / (variance + 1e-8).sqrt()
        norm_feat = in_feat.new()
        broadcast_forward(D, centered_feat, inv_std, norm_feat, multiply,
                          cpp_in_coords_key, cpp_glob_coords_key,
                          cpp_coords_manager)

        ctx.batch_size = batch_size
        ctx.in_coords_key, ctx.glob_coords_key = in_coords_key, glob_coords_key
        ctx.coords_manager = coords_manager
        # For GPU tensors, must use save_for_backward.
        ctx.save_for_backward(inv_std, norm_feat)
        return norm_feat
コード例 #13
0
    def test_hash(self):
        try:
            import numpy as np
        except:
            return

        N, M = 1000, 1000
        I, J = np.meshgrid(np.arange(N), np.arange(M))
        I = I.reshape(-1, 1) - 100
        J = J.reshape(-1, 1) - 100
        K = np.zeros_like(I)
        C = np.hstack((I, J, K))
        coords_manager = CoordsManager(D=2)
        coords_key = CoordsKey(2)
        coords_manager.initialize(torch.from_numpy(C).int(), coords_key)
コード例 #14
0
    def forward(ctx,
                input_features,
                kernel,
                tensor_stride=1,
                stride=1,
                kernel_size=-1,
                dilation=1,
                region_type=0,
                region_offset=None,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        """
        region_type=0 HyperCube
        """
        # Prep arguments
        # Kernel shape (n_spatial_kernels, in_nfeat, out_nfeat)
        assert input_features.shape[1] == kernel.shape[1]
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert in_coords_key.D == out_coords_key.D
        assert input_features.type() == kernel.type()
        tensor_stride, stride, kernel_size, dilation, region_type = prep_args(
            tensor_stride, stride, kernel_size, dilation, region_type,
            in_coords_key.D)

        if region_offset is None:
            region_offset = torch.IntTensor()

        ctx.in_feat = input_features
        ctx.kernel = kernel
        ctx = save_ctx(ctx, tensor_stride, stride, kernel_size, dilation,
                       region_type, in_coords_key, out_coords_key,
                       coords_manager)

        D = in_coords_key.D
        out_feat = input_features.new()

        fw_fn = getattr(MEB,
                        'ConvolutionForward' + get_postfix(input_features))
        fw_fn(D, ctx.in_feat, out_feat, kernel,
              convert_to_int_list(ctx.tensor_stride, D),
              convert_to_int_list(ctx.stride, D),
              convert_to_int_list(ctx.kernel_size, D),
              convert_to_int_list(ctx.dilation, D), region_type, region_offset,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_man.CPPCoordsManager)
        return out_feat
コード例 #15
0
    def forward(ctx,
                input_features,
                tensor_stride=1,
                stride=1,
                kernel_size=-1,
                dilation=1,
                region_type=0,
                region_offset=None,
                average=True,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        assert isinstance(region_type, RegionType)
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert in_coords_key.D == out_coords_key.D
        if not input_features.is_contiguous():
            input_features = input_features.contiguous()

        tensor_stride, stride, kernel_size, dilation, region_type = prep_args(
            tensor_stride, stride, kernel_size, dilation, region_type,
            in_coords_key.D)

        if region_offset is None:
            region_offset = torch.IntTensor()

        ctx.in_feat = input_features
        ctx = save_ctx(ctx, tensor_stride, stride, kernel_size, dilation,
                       region_type, in_coords_key, out_coords_key,
                       coords_manager)
        ctx.use_avg = average

        D = in_coords_key.D
        out_feat = input_features.new()
        ctx.num_nonzero = input_features.new()

        fw_fn = get_minkowski_function('AvgPoolingForward', input_features)
        fw_fn(ctx.in_feat, out_feat, ctx.num_nonzero,
              convert_to_int_list(ctx.tensor_stride, D),
              convert_to_int_list(ctx.stride, D),
              convert_to_int_list(ctx.kernel_size, D),
              convert_to_int_list(ctx.dilation, D), region_type, region_offset,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_man.CPPCoordsManager, ctx.use_avg)
        return out_feat
コード例 #16
0
    def forward(ctx,
                input_features,
                tensor_stride=1,
                stride=1,
                kernel_size=-1,
                dilation=1,
                region_type=0,
                region_offset=None,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        assert isinstance(region_type, RegionType)
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert in_coords_key.D == out_coords_key.D
        if not input_features.is_contiguous():
            input_features = input_features.contiguous()

        tensor_stride, stride, kernel_size, dilation, region_type = prep_args(
            tensor_stride, stride, kernel_size, dilation, region_type,
            in_coords_key.D)

        if region_offset is None:
            region_offset = torch.IntTensor()

        ctx.in_feat = input_features
        ctx = save_ctx(ctx, tensor_stride, stride, kernel_size, dilation,
                       region_type, in_coords_key, out_coords_key,
                       coords_manager)

        D = in_coords_key.D
        out_feat = input_features.new()
        max_index = input_features.new().int()

        ctx.max_index = max_index

        fw_fn = getattr(MEB, 'MaxPoolingForward' + get_postfix(input_features))
        fw_fn(input_features, out_feat, max_index,
              convert_to_int_list(ctx.tensor_stride, D),
              convert_to_int_list(ctx.stride, D),
              convert_to_int_list(ctx.kernel_size, D),
              convert_to_int_list(ctx.dilation, D), region_type, region_offset,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_man.CPPCoordsManager)
        return out_feat
コード例 #17
0
    def forward(self, input):
        assert isinstance(input, SparseTensor)
        assert input.D == self.dimension

        # Create a region_offset
        self.region_type_, self.region_offset_, _ = \
            self.kernel_generator.get_kernel(input.tensor_stride, self.is_transpose)

        if self.out_coords_key is None:
            out_coords_key = CoordsKey(input.coords_key.D)
        else:
            out_coords_key = self.out_coords_key

        output = self.pooling.apply(input.F, input.tensor_stride, self.stride,
                                    self.kernel_size, self.dilation,
                                    self.region_type_, self.region_offset_,
                                    input.coords_key, out_coords_key,
                                    input.coords_man)
        return SparseTensor(
            output, coords_key=out_coords_key, coords_manager=input.coords_man)
コード例 #18
0
    def forward(ctx,
                input_features,
                tensor_stride=1,
                stride=1,
                kernel_size=-1,
                dilation=1,
                region_type=-1,
                region_offset=None,
                average=False,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        assert isinstance(region_type, RegionType)
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        assert in_coords_key.D == out_coords_key.D
        tensor_stride, stride, kernel_size, dilation, region_type = prep_args(
            tensor_stride, stride, kernel_size, dilation, region_type,
            in_coords_key.D)

        if region_offset is None:
            region_offset = torch.IntTensor()

        ctx.in_feat = input_features
        out_feat = input_features.new()
        ctx.num_nonzero = input_features.new()
        ctx = save_ctx(ctx, tensor_stride, stride, kernel_size, dilation,
                       region_type, in_coords_key, out_coords_key,
                       coords_manager)
        D = in_coords_key.D
        fw_fn = getattr(
            MEB, 'PoolingTransposeForward' + get_postfix(input_features))
        fw_fn(ctx.in_feat, out_feat, ctx.num_nonzero,
              convert_to_int_list(ctx.tensor_stride, D),
              convert_to_int_list(ctx.stride, D),
              convert_to_int_list(ctx.kernel_size, D),
              convert_to_int_list(ctx.dilation, D), region_type, region_offset,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_man.CPPCoordsManager)
        return out_feat
コード例 #19
0
    def forward(self, *inputs):
        r"""
        Args:
            A variable number of :attr:`MinkowskiEngine.SparseTensor`'s.

        Returns:
            A :attr:`MinkowskiEngine.SparseTensor` with coordinates = union of all
            input coordinates, and features = sum of all features corresponding to the
            coordinate.

        Example::

            >>> # Define inputs
            >>> input1 = SparseTensor(
            >>>     torch.rand(N, in_channels, dtype=torch.double), coords=coords)
            >>> # All inputs must share the same coordinate manager
            >>> input2 = SparseTensor(
            >>>     torch.rand(N, in_channels, dtype=torch.double),
            >>>     coords=coords + 1,
            >>>     coords_manager=input1.coords_man,  # Must use same coords manager
            >>>     force_creation=True  # The tensor stride [1, 1] already exists.
            >>> )
            >>> union = MinkowskiUnion()
            >>> output = union(input1, iput2)

        """
        for s in inputs:
            assert isinstance(s,
                              SparseTensor), "Inputs must be sparse tensors."
        assert len(inputs) > 1, \
            "input must be a set with at least 2 SparseTensors"

        out_coords_key = CoordsKey(inputs[0].coords_key.D)
        output = self.union.apply([input.coords_key for input in inputs],
                                  out_coords_key, inputs[0].coords_man,
                                  *[input.F for input in inputs])
        return SparseTensor(output,
                            coords_key=out_coords_key,
                            coords_manager=inputs[0].coords_man)
コード例 #20
0
def _get_coords_key(input: SparseTensor,
                    coords: Union[torch.IntTensor, CoordsKey,
                                  SparseTensor] = None,
                    tensor_stride: Union[Sequence, np.ndarray,
                                         torch.IntTensor] = 1):
    r"""Process coords according to its type.
    """
    if coords is not None:
        assert isinstance(coords, (CoordsKey, torch.IntTensor, SparseTensor))
        if isinstance(coords, torch.IntTensor):
            coords_key = input.coords_man.create_coords_key(
                coords,
                tensor_stride=tensor_stride,
                force_creation=True,
                force_remap=True,
                allow_duplicate_coords=True)
        elif isinstance(coords, SparseTensor):
            coords_key = coords.coords_key
        else:  # CoordsKey type due to the previous assertion
            coords_key = coords
    else:
        coords_key = CoordsKey(input.D)
    return coords_key
コード例 #21
0
    def forward(ctx,
                input_features,
                in_coords_key=None,
                out_coords_key=None,
                coords_manager=None):
        if out_coords_key is None:
            out_coords_key = CoordsKey(in_coords_key.D)
        ctx.in_coords_key = in_coords_key
        ctx.out_coords_key = out_coords_key

        ctx.in_feat = input_features
        out_feat = input_features.new()

        max_index = input_features.new().int()

        ctx.max_index = max_index
        ctx.coords_manager = coords_manager

        fw_fn = getattr(
            MEB, 'GlobalMaxPoolingForward' + get_postfix(input_features))
        fw_fn(ctx.in_feat, out_feat, ctx.max_index,
              ctx.in_coords_key.CPPCoordsKey, ctx.out_coords_key.CPPCoordsKey,
              ctx.coords_manager.CPPCoordsManager)
        return out_feat
コード例 #22
0
    def __init__(self,
                 feats,
                 coords=None,
                 coords_key=None,
                 coords_manager=None,
                 tensor_stride=1):
        r"""

        Args:
            :attr:`feats` (:attr:`torch.FloatTensor`,
            :attr:`torch.DoubleTensor`, :attr:`torch.cuda.FloatTensor`, or
            :attr:`torch.cuda.DoubleTensor`): The features of the sparse
            tensor.

            :attr:`coords` (:attr:`torch.IntTensor`): The coordinates
            associated to the features. If not provided, :attr:`coords_key`
            must be provided.

            :attr:`coords_key` (:attr:`MinkowskiEngine.CoordsKey`): When the
            coordinates are already cached in the MinkowskiEngine, we could
            reuse the same coordinates by simply providing the coordinate hash
            key. In most case, this process is done automatically. If you
            provide one, make sure you understand what you are doing.

            :attr:`coords_manager` (:attr:`MinkowskiEngine.CoordsManager`): The
            MinkowskiEngine creates a dynamic computation graph using an input
            coordinates. If not provided, the MinkowskiEngine will create a new
            computation graph, so make sure to provide the same
            :attr:`CoordsManager` when you want to use the same computation
            graph. To use a sparse tensor within the same computation graph
            that you are using before, feed the :attr:`CoordsManager` of the
            sparse tensor that you want to use by
            :attr:`sparse_tensor.coords_man`. In most cases, this process is
            handled automatically. When you use it, make sure you understand
            what you are doing.

            :attr:`tensor_stride` (:attr:`int`, :attr:`list`,
            :attr:`numpy.array`, or :attr:`tensor.Tensor`): The tensor stride
            of the current sparse tensor. By default, it is 1.

        """
        assert isinstance(feats,
                          torch.Tensor), "Features must be a torch.Tensor"

        if coords is None and coords_key is None:
            raise ValueError('Either coords or coords_key must be provided')

        if coords_key is None:
            assert coords_manager is not None or coords is not None
            D = -1
            if coords_manager is None:
                D = coords.size(1) - 1
            else:
                D = coords_manager.D
            coords_key = CoordsKey(D)
            coords_key.setTensorStride(convert_to_int_list(tensor_stride, D))
        else:
            assert isinstance(coords_key, CoordsKey)

        if coords is not None:
            assert isinstance(coords, torch.Tensor), \
                "Coordinate must be of type torch.Tensor"

            if not isinstance(coords, torch.IntTensor):
                warnings.warn(
                    'Coords implicitly converted to torch.IntTensor. ' +
                    'To remove this warning, use `.int()` to convert the ' +
                    'coords into an torch.IntTensor')
                coords = coords.int()

            assert feats.shape[0] == coords.shape[0], \
                "Number of rows in features and coordinates do not match."

            coords = coords.contiguous()

        if coords_manager is None:
            assert coords is not None, "Initial coordinates must be given"
            D = coords.size(1) - 1
            coords_manager = CoordsManager(D=D)
            coords_manager.initialize(coords, coords_key)
        else:
            assert isinstance(coords_manager, CoordsManager)

        self._F = feats.contiguous()
        self._C = coords
        self.coords_key = coords_key
        self.coords_man = coords_manager
コード例 #23
0
 def test_coords_key(self):
     key = CoordsKey(D=1)
     key.setKey(1)
     self.assertTrue(key.getKey() == 1)
     key.setTensorStride([1])
     print(key)
コード例 #24
0
    def __init__(self,
                 feats,
                 coords=None,
                 coords_key=None,
                 coords_manager=None,
                 force_creation=False,
                 allow_duplicate_coords=False,
                 tensor_stride=1):
        r"""

        Args:
            :attr:`feats` (:attr:`torch.FloatTensor`,
            :attr:`torch.DoubleTensor`, :attr:`torch.cuda.FloatTensor`, or
            :attr:`torch.cuda.DoubleTensor`): The features of the sparse
            tensor.

            :attr:`coords` (:attr:`torch.IntTensor`): The coordinates
            associated to the features. If not provided, :attr:`coords_key`
            must be provided.

            :attr:`coords_key` (:attr:`MinkowskiEngine.CoordsKey`): When the
            coordinates are already cached in the MinkowskiEngine, we could
            reuse the same coordinates by simply providing the coordinate hash
            key. In most case, this process is done automatically. If you
            provide one, make sure you understand what you are doing.

            :attr:`coords_manager` (:attr:`MinkowskiEngine.CoordsManager`): The
            MinkowskiEngine creates a dynamic computation graph and all
            coordinates inside the same computation graph are managed by a
            CoordsManager object. If not provided, the MinkowskiEngine will
            create a new computation graph. In most cases, this process is
            handled automatically and you do not need to use this. When you use
            it, make sure you understand what you are doing.

            :attr:`force_creation` (:attr:`bool`): Force creation of the
            coordinates. This allows generating a new set of coordinates even
            when there exists another set of coordinates with the same
            tensor stride. This could happen when you manually feed the same
            :attr:`coords_manager`.

            :attr:`allow_duplicate_coords` (:attr:`bool`): Allow duplicate
            coordinates when creating the sparse tensor. Internally, it will
            generate a new unique set of coordinates and use features of at the
            corresponding unique coordinates. In general, setting
            `allow_duplicate_coords=True` is not recommended as it could hide
            obvious errors in your data loading and preprocessing steps. Please
            refer to the quantization and data loading tutorial on `here
            <https://stanfordvl.github.io/MinkowskiEngine/demo/training.html>`_
            for more details.

            :attr:`tensor_stride` (:attr:`int`, :attr:`list`,
            :attr:`numpy.array`, or :attr:`tensor.Tensor`): The tensor stride
            of the current sparse tensor. By default, it is 1.

        """
        assert isinstance(feats,
                          torch.Tensor), "Features must be a torch.Tensor"

        if coords is None and coords_key is None:
            raise ValueError('Either coords or coords_key must be provided')

        if coords_key is None:
            assert coords_manager is not None or coords is not None
            D = -1
            if coords_manager is None:
                D = coords.size(1) - 1
            else:
                D = coords_manager.D
            coords_key = CoordsKey(D)
            coords_key.setTensorStride(convert_to_int_list(tensor_stride, D))
        else:
            assert isinstance(coords_key, CoordsKey)

        if coords is not None:
            assert isinstance(coords, torch.Tensor), \
                "Coordinate must be of type torch.Tensor"

            if not isinstance(coords, torch.IntTensor):
                warnings.warn(
                    'Coords implicitly converted to torch.IntTensor. ' +
                    'To remove this warning, use `.int()` to convert the ' +
                    'coords into an torch.IntTensor')
                coords = coords.int()

            if coords.device.type != 'cpu':
                warnings.warn(
                    'Coords implicitly converted to CPU type. ' +
                    'To remove this warning, use `.cpu()` to convert the ' +
                    'coords into a CPU type')
                coords = coords.cpu()

            assert feats.shape[0] == coords.shape[0], \
                "Number of rows in features and coordinates do not match."

            coords = coords.contiguous()

        if coords_manager is None:
            # If set to share the coords man, use the global coords man
            global _sparse_tensor_operation_mode, _global_coords_man
            if _sparse_tensor_operation_mode == SparseTensorOperationMode.SHARE_COORDS_MANAGER:
                if _global_coords_man is None:
                    _global_coords_man = CoordsManager(D=coords.size(1) - 1)
                coords_manager = _global_coords_man
            else:
                assert coords is not None, "Initial coordinates must be given"
                coords_manager = CoordsManager(D=coords.size(1) - 1)

            if not coords_key.isKeySet():
                self.mapping = coords_manager.initialize(
                    coords,
                    coords_key,
                    force_creation=force_creation,
                    force_remap=allow_duplicate_coords,
                    allow_duplicate_coords=allow_duplicate_coords)
                if len(self.mapping) > 0:
                    coords = coords[self.mapping]
                    feats = feats[self.mapping]
        else:
            assert isinstance(coords_manager, CoordsManager)

            if not coords_key.isKeySet():
                assert coords is not None
                self.mapping = coords_manager.initialize(
                    coords,
                    coords_key,
                    force_creation=force_creation,
                    force_remap=allow_duplicate_coords,
                    allow_duplicate_coords=allow_duplicate_coords)
                if len(self.mapping) > 0:
                    coords = coords[self.mapping]
                    feats = feats[self.mapping]

        self._F = feats.contiguous()
        self._C = coords
        self.coords_key = coords_key
        self.coords_man = coords_manager
コード例 #25
0
    def __init__(
            self,
            feats,
            coords=None,
            coords_key=None,
            coords_manager=None,
            force_creation=False,
            allow_duplicate_coords=False,
            quantization_mode=SparseTensorQuantizationMode.RANDOM_SUBSAMPLE,
            tensor_stride=1):
        r"""

        Args:
            :attr:`feats` (:attr:`torch.FloatTensor`,
            :attr:`torch.DoubleTensor`, :attr:`torch.cuda.FloatTensor`, or
            :attr:`torch.cuda.DoubleTensor`): The features of the sparse
            tensor.

            :attr:`coords` (:attr:`torch.IntTensor`): The coordinates
            associated to the features. If not provided, :attr:`coords_key`
            must be provided.

            :attr:`coords_key` (:attr:`MinkowskiEngine.CoordsKey`): When the
            coordinates are already cached in the MinkowskiEngine, we could
            reuse the same coordinates by simply providing the coordinate hash
            key. In most case, this process is done automatically. When you
            provide a `coords_key`, all other arguments will be be ignored.

            :attr:`coords_manager` (:attr:`MinkowskiEngine.CoordsManager`): The
            MinkowskiEngine creates a dynamic computation graph and all
            coordinates inside the same computation graph are managed by a
            CoordsManager object. If not provided, the MinkowskiEngine will
            create a new computation graph. In most cases, this process is
            handled automatically and you do not need to use this. When you use
            it, make sure you understand what you are doing.

            :attr:`force_creation` (:attr:`bool`): Force creation of the
            coordinates. This allows generating a new set of coordinates even
            when there exists another set of coordinates with the same
            tensor stride. This could happen when you manually feed the same
            :attr:`coords_manager`.

            :attr:`allow_duplicate_coords` (:attr:`bool`): Allow duplicate
            coordinates when creating the sparse tensor. Internally, it will
            generate a new unique set of coordinates and use features of at the
            corresponding unique coordinates. In general, setting
            `allow_duplicate_coords=True` is not recommended as it could hide
            obvious errors in your data loading and preprocessing steps. Please
            refer to the quantization and data loading tutorial on `here
            <https://stanfordvl.github.io/MinkowskiEngine/demo/training.html>`_
            for more details.

            :attr:`quantizatino_mode`
            (:attr:`MinkowskiEngine.SparseTensorQuantizationMode`): Defines the
            quantization method and how to define features of a sparse tensor.
            Please refer to :attr:`SparseTensorQuantizationMode` for details.

            :attr:`tensor_stride` (:attr:`int`, :attr:`list`,
            :attr:`numpy.array`, or :attr:`tensor.Tensor`): The tensor stride
            of the current sparse tensor. By default, it is 1.

        """
        assert isinstance(feats,
                          torch.Tensor), "Features must be a torch.Tensor"
        assert feats.ndim == 2, f"The feature should be a matrix, The input feature is an order-{feats.ndim} tensor."
        assert isinstance(quantization_mode, SparseTensorQuantizationMode)
        self.quantization_mode = quantization_mode

        if coords is None and coords_key is None:
            raise ValueError('Either coords or coords_key must be provided')

        if coords_key is None:
            assert coords_manager is not None or coords is not None
            D = -1
            if coords_manager is None:
                D = coords.size(1) - 1
            else:
                D = coords_manager.D
            coords_key = CoordsKey(D)
            coords_key.setTensorStride(convert_to_int_list(tensor_stride, D))
        else:
            assert isinstance(coords_key, CoordsKey)

        if coords is not None:
            assert isinstance(coords, torch.Tensor), \
                "Coordinate must be of type torch.Tensor"

            if not isinstance(coords, torch.IntTensor):
                warnings.warn(
                    'Coords implicitly converted to torch.IntTensor. ' +
                    'To remove this warning, use `.int()` to convert the ' +
                    'coords into an torch.IntTensor')
                coords = torch.floor(coords).int()

            if coords.device.type != 'cpu':
                warnings.warn(
                    'Coords implicitly converted to CPU type. ' +
                    'To remove this warning, use `.cpu()` to convert the ' +
                    'coords into a CPU type')
                coords = coords.cpu()

            assert feats.shape[0] == coords.shape[0], \
                "The number of rows in features and coordinates do not match."

            coords = coords.contiguous()

        ##########################
        # Setup CoordsManager
        ##########################
        if coords_manager is None:
            # If set to share the coords man, use the global coords man
            global _sparse_tensor_operation_mode, _global_coords_man
            if _sparse_tensor_operation_mode == SparseTensorOperationMode.SHARE_COORDS_MANAGER:
                if _global_coords_man is None:
                    _global_coords_man = CoordsManager(D=coords.size(1) - 1)
                coords_manager = _global_coords_man
            else:
                assert coords is not None, "Initial coordinates must be given"
                coords_manager = CoordsManager(D=coords.size(1) - 1)

        else:
            assert isinstance(coords_manager, CoordsManager)

        ##########################
        # Initialize coords
        ##########################
        if not coords_key.isKeySet() and coords is not None and len(
                coords) > 0:
            if quantization_mode == SparseTensorQuantizationMode.RANDOM_SUBSAMPLE:
                force_remap = True
                return_inverse = False
            elif quantization_mode == SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE:
                force_remap = True
                return_inverse = True

            self.unique_index, self.inverse_mapping = coords_manager.initialize(
                coords,
                coords_key,
                force_creation=force_creation,
                force_remap=force_remap,
                allow_duplicate_coords=allow_duplicate_coords,
                return_inverse=return_inverse)

            if quantization_mode == SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE:
                self._CF = feats
                self._CC = coords
                feats = MEB.quantization_average_features(
                    feats, torch.arange(len(feats)), self.inverse_mapping,
                    len(self.unique_index), 0)
                coords = coords[self.unique_index]
            elif force_remap:
                assert len(self.unique_index) > 0
                self._CC = coords
                self._CF = feats
                coords = coords[self.unique_index]
                feats = feats[self.unique_index]

        elif coords is not None:  # empty / invalid coords
            assert isinstance(coords, torch.IntTensor)
            assert coords.ndim == 2
            coords_manager.initialize(coords,
                                      coords_key,
                                      force_creation=force_creation,
                                      force_remap=False,
                                      allow_duplicate_coords=False,
                                      return_inverse=False)
        elif coords_key is not None:
            assert coords_key.isKeySet()

        self._F = feats.contiguous()
        self._C = coords
        self.coords_key = coords_key
        self.coords_man = coords_manager