Exemplo n.º 1
0
    def __init__(self,
                 kernel_size,
                 stride=1,
                 dilation=1,
                 kernel_generator=None,
                 out_coords_key=None,
                 is_transpose=False,
                 average=True,
                 dimension=-1):
        super(MinkowskiPoolingBase, self).__init__()
        if out_coords_key is not None:
            assert isinstance(out_coords_key, CoordsKey)
        assert dimension > 0, f"dimension must be a positive integer, {dimension}"

        stride = convert_to_int_tensor(stride, dimension)
        kernel_size = convert_to_int_tensor(kernel_size, dimension)
        dilation = convert_to_int_tensor(dilation, dimension)
        if torch.prod(kernel_size) == 1 and torch.prod(stride) == 1:
            raise ValueError('Trivial input output mapping')

        if kernel_generator is None:
            kernel_generator = KernelGenerator(kernel_size=kernel_size,
                                               stride=stride,
                                               dilation=dilation,
                                               dimension=dimension)

        self.is_transpose = is_transpose
        self.average = average
        self.kernel_size = kernel_size
        self.stride = stride
        self.dilation = dilation
        self.kernel_generator = kernel_generator
        self.out_coords_key = out_coords_key
        self.dimension = dimension
    def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size=-1,
                 stride=1,
                 dilation=1,
                 has_bias=False,
                 kernel_generator=None,
                 out_coords_key=None,
                 is_transpose=False,
                 dimension=-1):
        super(MinkowskiConvolutionBase, self).__init__()
        assert dimension > 0, f"dimension must be a positive integer, {dimension}"
        if out_coords_key is not None:
            assert isinstance(out_coords_key, CoordsKey)

        if kernel_generator is None:
            kernel_generator = KernelGenerator(
                kernel_size=kernel_size,
                stride=stride,
                dilation=dilation,
                dimension=dimension)
        else:
            kernel_size = kernel_generator.kernel_size

        stride = convert_to_int_tensor(stride, dimension)
        kernel_size = convert_to_int_tensor(kernel_size, dimension)
        dilation = convert_to_int_tensor(dilation, dimension)

        kernel_volume = kernel_generator.kernel_volume

        self.is_transpose = is_transpose
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.kernel_volume = kernel_volume
        self.stride = stride
        self.dilation = dilation
        self.kernel_generator = kernel_generator
        self.out_coords_key = out_coords_key
        self.dimension = dimension
        self.use_mm = False  # use matrix multiplication when kernel is 1

        Tensor = torch.FloatTensor
        if torch.prod(kernel_size) == 1 and torch.prod(stride) == 1:
            self.kernel_shape = (self.in_channels, self.out_channels)
            self.use_mm = True
        else:
            self.kernel_shape = (self.kernel_volume, self.in_channels,
                                 self.out_channels)

        self.kernel = Parameter(Tensor(*self.kernel_shape))
        self.bias = Parameter(Tensor(1, out_channels)) if has_bias else None
        self.has_bias = has_bias
Exemplo n.º 3
0
    def get_kernel_map(self,
                       in_key_or_tensor_strides,
                       out_key_or_tensor_strides,
                       stride=1,
                       kernel_size=3,
                       dilation=1,
                       region_type=0,
                       region_offset=None,
                       is_transpose=False,
                       is_pool=False,
                       on_gpu=False):
        r"""Get kernel in-out maps for the specified coords keys or tensor strides.

        """
        # region type 1 iteration with kernel_size 1 is invalid
        assert kernel_size > 0, "Invalid kernel size."
        if kernel_size == 1:
            region_type = 0

        if isinstance(in_key_or_tensor_strides, CoordsKey):
            in_tensor_strides = in_key_or_tensor_strides.getTensorStride()
        else:
            in_tensor_strides = in_key_or_tensor_strides
        if region_offset is None:
            region_offset = torch.IntTensor()

        in_coords_key = self._get_coords_key(in_key_or_tensor_strides)
        out_coords_key = self._get_coords_key(out_key_or_tensor_strides)

        tensor_strides = convert_to_int_tensor(in_tensor_strides, self.D)
        strides = convert_to_int_tensor(stride, self.D)
        kernel_sizes = convert_to_int_tensor(kernel_size, self.D)
        dilations = convert_to_int_tensor(dilation, self.D)
        D = in_coords_key.D
        tensor_strides, strides, kernel_sizes, dilations, region_type = prep_args(
            tensor_strides, strides, kernel_sizes, dilations, region_type, D)
        kernel_map_fn = self.CPPCoordsManager.getKernelMapGPU \
            if on_gpu else self.CPPCoordsManager.getKernelMapGPU
        kernel_map = kernel_map_fn(
            convert_to_int_list(tensor_strides, D),  #
            convert_to_int_list(strides, D),  #
            convert_to_int_list(kernel_sizes, D),  #
            convert_to_int_list(dilations, D),  #
            region_type,
            region_offset,
            in_coords_key.CPPCoordsKey,
            out_coords_key.CPPCoordsKey,
            is_transpose,
            is_pool)

        return kernel_map
Exemplo n.º 4
0
    def get_kernel_map(self,
                       in_key_or_tensor_strides,
                       out_key_or_tensor_strides,
                       stride=1,
                       kernel_size=3,
                       dilation=1,
                       region_type=0,
                       is_transpose=False,
                       is_pool=False):
        r"""Get kernel in-out maps for the specified coords keys or tensor strides.

        """

        if isinstance(in_key_or_tensor_strides, CoordsKey):
            in_tensor_strides = in_key_or_tensor_strides.getTensorStride()
        else:
            in_tensor_strides = in_key_or_tensor_strides

        in_coords_key = self._get_coords_key(in_key_or_tensor_strides)
        out_coords_key = self._get_coords_key(out_key_or_tensor_strides)

        tensor_strides = convert_to_int_tensor(in_tensor_strides, self.D)
        strides = convert_to_int_tensor(stride, self.D)
        kernel_sizes = convert_to_int_tensor(kernel_size, self.D)
        dilations = convert_to_int_tensor(dilation, self.D)
        D = in_coords_key.D
        tensor_strides, strides, kernel_sizes, dilations, region_type = prep_args(
            tensor_strides, strides, kernel_sizes, dilations, region_type, D)

        kernel_map = self.CPPCoordsManager.getKernelMap(
            convert_to_int_list(tensor_strides, D),  #
            convert_to_int_list(strides, D),  #
            convert_to_int_list(kernel_sizes, D),  #
            convert_to_int_list(dilations, D),  #
            region_type,
            in_coords_key.CPPCoordsKey,
            out_coords_key.CPPCoordsKey,
            is_transpose,
            is_pool)

        return kernel_map
    def permute_feature(self, feat, tensor_stride, dtype=np.float32):
        tensor_stride = convert_to_int_tensor(tensor_stride, self.D)
        permutation = self.get_permutation(tensor_stride, 1)
        nrows = self.get_nrows(tensor_stride)

        feat_np = feat.contiguous().numpy()
        warped_feat = np.zeros((nrows, feat.size(1)), dtype=dtype)
        counter = np.zeros((nrows, 1), dtype='int32')
        for j in range(feat.size(1)):
            np.add.at(warped_feat, (permutation, j), feat_np[:, j])
        np.add.at(counter, permutation, 1)
        warped_feat = warped_feat / counter
        return torch.from_numpy(warped_feat)
    def permute_label(self, label, max_label, tensor_stride):
        if tensor_stride == 1 or np.prod(tensor_stride) == 1:
            return label

        tensor_stride = convert_to_int_tensor(tensor_stride, self.D)
        permutation = self.get_permutation(tensor_stride, 1)
        nrows = self.get_nrows(tensor_stride)

        label = label.contiguous().numpy()
        permutation = permutation.numpy()

        counter = np.zeros((nrows, max_label), dtype='int32')
        np.add.at(counter, (permutation, label), 1)
        return torch.from_numpy(np.argmax(counter, 1))
    def get_index_map(self, coords, tensor_stride):
        """
        Get the current coords (with duplicates) index map.

        If tensor_stride > 1, use
        coords = torch.cat(((coords[:, :D] / tensor_stride) * tensor_stride,
                            coords[:, D:]), dim=1)
        """
        assert isinstance(coords, torch.IntTensor), "Coord must be IntTensor"
        index_map = torch.IntTensor()
        tensor_stride = convert_to_int_tensor(tensor_stride, self.D)
        success = MEB.get_index_map(coords.contiguous(), index_map,
                                    tensor_stride, self.D,
                                    self.net_metadata.ffi)
        if success < 0:
            raise ValueError('get_index_map failed')
        return index_map
Exemplo n.º 8
0
    def get_kernel_map(self,
                       in_key_or_tensor_strides,
                       out_key_or_tensor_strides,
                       stride=1,
                       kernel_size=3,
                       dilation=1,
                       region_type=0,
                       region_offset=None,
                       is_transpose=False,
                       is_pool=False,
                       on_gpu=False):
        r"""Get kernel in-out maps for the specified coords keys or tensor strides.

        """
        # region type 1 iteration with kernel_size 1 is invalid
        if isinstance(kernel_size, torch.Tensor):
            assert (kernel_size >
                    0).all(), f"Invalid kernel size: {kernel_size}"
            if (kernel_size == 1).all() == 1:
                region_type = 0
        elif isinstance(kernel_size, int):
            assert kernel_size > 0, f"Invalid kernel size: {kernel_size}"
            if kernel_size == 1:
                region_type = 0

        if isinstance(in_key_or_tensor_strides, CoordsKey):
            in_tensor_strides = in_key_or_tensor_strides.getTensorStride()
        else:
            in_tensor_strides = in_key_or_tensor_strides
        if region_offset is None:
            region_offset = torch.IntTensor()

        in_coords_key = self._get_coords_key(in_key_or_tensor_strides)
        out_coords_key = self._get_coords_key(out_key_or_tensor_strides)

        tensor_strides = convert_to_int_tensor(in_tensor_strides, self.D)
        strides = convert_to_int_tensor(stride, self.D)
        kernel_sizes = convert_to_int_tensor(kernel_size, self.D)
        dilations = convert_to_int_tensor(dilation, self.D)
        D = in_coords_key.D
        tensor_strides, strides, kernel_sizes, dilations, region_type = prep_args(
            tensor_strides, strides, kernel_sizes, dilations, region_type, D)
        if on_gpu:
            assert hasattr(
                self.CPPCoordsManager, 'getKernelMapGPU'
            ), f"Function getKernelMapGPU not available. Please compile MinkowskiEngine where `torch.cuda.is_available()` is `True`."
            kernel_map_fn = getattr(self.CPPCoordsManager, 'getKernelMapGPU')
        else:
            kernel_map_fn = self.CPPCoordsManager.getKernelMap
        kernel_map = kernel_map_fn(
            convert_to_int_list(tensor_strides, D),  #
            convert_to_int_list(strides, D),  #
            convert_to_int_list(kernel_sizes, D),  #
            convert_to_int_list(dilations, D),  #
            region_type,
            region_offset,
            in_coords_key.CPPCoordsKey,
            out_coords_key.CPPCoordsKey,
            is_transpose,
            is_pool)

        return kernel_map
    def __init__(self,
                 in_channels,
                 kernel_size=-1,
                 stride=1,
                 dilation=1,
                 has_bias=False,
                 kernel_generator=None,
                 dimension=-1):
        r"""convolution on a sparse tensor

        Args:
            :attr:`in_channels` (int): the number of input channels in the
            input tensor.

            :attr:`kernel_size` (int, optional): the size of the kernel in the
            output tensor. If not provided, :attr:`region_offset` should be
            :attr:`RegionType.CUSTOM` and :attr:`region_offset` should be a 2D
            matrix with size :math:`N\times D` such that it lists all :math:`N`
            offsets in D-dimension.

            :attr:`stride` (int, or list, optional): stride size of the
            convolution layer. If non-identity is used, the output coordinates
            will be at least :attr:`stride` :math:`\times` :attr:`tensor_stride`
            away. When a list is given, the length must be D; each element will
            be used for stride size for the specific axis.

            :attr:`dilation` (int, or list, optional): dilation size for the
            convolution kernel. When a list is given, the length must be D and
            each element is an axis specific dilation. All elements must be > 0.

            :attr:`has_bias` (bool, optional): if True, the convolution layer
            has a bias.

            :attr:`kernel_generator` (:attr:`MinkowskiEngine.KernelGenerator`,
            optional): defines the custom kernel shape.

            :attr:`dimension` (int): the spatial dimension of the space where
            all the inputs and the network are defined. For example, images are
            in a 2D space, meshes and 3D shapes are in a 3D space.

        """

        super(MinkowskiChannelwiseConvolution, self).__init__()
        assert dimension > 0, f"dimension must be a positive integer, {dimension}"

        if kernel_generator is None:
            kernel_generator = KernelGenerator(kernel_size=kernel_size,
                                               stride=stride,
                                               dilation=dilation,
                                               dimension=dimension)
        else:
            kernel_size = kernel_generator.kernel_size

        stride = convert_to_int_tensor(stride, dimension)
        kernel_size = convert_to_int_tensor(kernel_size, dimension)
        dilation = convert_to_int_tensor(dilation, dimension)

        kernel_volume = kernel_generator.kernel_volume

        self.in_channels = in_channels
        self.kernel_size = kernel_size
        self.kernel_volume = kernel_volume
        self.stride = stride
        self.dilation = dilation
        self.kernel_generator = kernel_generator
        self.dimension = dimension
        self.use_mm = False  # use matrix multiplication when kernel is 1

        Tensor = torch.FloatTensor
        self.kernel_shape = (self.kernel_volume, self.in_channels)

        self.kernel = Parameter(Tensor(*self.kernel_shape))
        self.bias = Parameter(Tensor(1, in_channels)) if has_bias else None
        self.has_bias = has_bias
        self.reset_parameters()