未验证 提交 61953b90 编写于 作者: Z zhangkaihuo 提交者: GitHub

[cherry-pick]Fix english documents of sparse api (#47496)

Fix english documents of sparse api
上级 601626ac
...@@ -33,13 +33,13 @@ _int_dtype_ = [ ...@@ -33,13 +33,13 @@ _int_dtype_ = [
@dygraph_only @dygraph_only
def matmul(x, y, name=None): def matmul(x, y, name=None):
""" """
Note: Note:
This API is only supported from ``CUDA 11.0`` . This API is only supported from ``CUDA 11.0`` .
Applies matrix multiplication of two Tensors. Applies matrix multiplication of two Tensors.
The supported input/output Tensor layout are as follows: The supported input/output Tensor layout are as follows:
Note: Note:
x[SparseCsrTensor] @ y[SparseCsrTensor] -> out[SparseCsrTensor] x[SparseCsrTensor] @ y[SparseCsrTensor] -> out[SparseCsrTensor]
x[SparseCsrTensor] @ y[DenseTensor] -> out[DenseTensor] x[SparseCsrTensor] @ y[DenseTensor] -> out[DenseTensor]
...@@ -49,14 +49,14 @@ def matmul(x, y, name=None): ...@@ -49,14 +49,14 @@ def matmul(x, y, name=None):
It supports backward propagation. It supports backward propagation.
Dimensions `x` and `y` must be >= 2D. Automatic broadcasting of Tensor is not supported. Dimensions `x` and `y` must be >= 2D. Automatic broadcasting of Tensor is not supported.
the shape of `x` should be `[*, M, K]` , and the shape of `y` should be `[*, K, N]` , where `*` the shape of `x` should be `[*, M, K]` , and the shape of `y` should be `[*, K, N]` , where `*`
is zero or more batch dimensions. is zero or more batch dimensions.
Args: Args:
x (Tensor): The input tensor. It can be SparseCooTensor/SparseCsrTensor. The data type can be float32 or float64. x (Tensor): The input tensor. It can be SparseCooTensor/SparseCsrTensor. The data type can be float32 or float64.
y (Tensor): The input tensor. It can be SparseCooTensor/SparseCsrTensor/DenseTensor. The data type can be float32 or float64. y (Tensor): The input tensor. It can be SparseCooTensor/SparseCsrTensor/DenseTensor. The data type can be float32 or float64.
name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Returns: Returns:
Tensor: Its layout is determined by that of `x` and `y` . Tensor: Its layout is determined by that of `x` and `y` .
...@@ -72,9 +72,9 @@ def matmul(x, y, name=None): ...@@ -72,9 +72,9 @@ def matmul(x, y, name=None):
cols = [1, 2, 0] cols = [1, 2, 0]
values = [1., 2., 3.] values = [1., 2., 3.]
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, [3, 3]) csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, [3, 3])
# Tensor(shape=[3, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True, # Tensor(shape=[3, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# crows=[0, 1, 2, 3], # crows=[0, 1, 2, 3],
# cols=[1, 2, 0], # cols=[1, 2, 0],
# values=[1., 2., 3.]) # values=[1., 2., 3.])
dense = paddle.ones([3, 2]) dense = paddle.ones([3, 2])
out = paddle.sparse.matmul(csr, dense) out = paddle.sparse.matmul(csr, dense)
...@@ -87,9 +87,9 @@ def matmul(x, y, name=None): ...@@ -87,9 +87,9 @@ def matmul(x, y, name=None):
indices = [[0, 1, 2], [1, 2, 0]] indices = [[0, 1, 2], [1, 2, 0]]
values = [1., 2., 3.] values = [1., 2., 3.]
coo = paddle.sparse.sparse_coo_tensor(indices, values, [3, 3]) coo = paddle.sparse.sparse_coo_tensor(indices, values, [3, 3])
# Tensor(shape=[3, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True, # Tensor(shape=[3, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# indices=[[0, 1, 2], # indices=[[0, 1, 2],
# [1, 2, 0]], # [1, 2, 0]],
# values=[1., 2., 3.]) # values=[1., 2., 3.])
dense = paddle.ones([3, 2]) dense = paddle.ones([3, 2])
out = paddle.sparse.matmul(coo, dense) out = paddle.sparse.matmul(coo, dense)
...@@ -104,13 +104,13 @@ def matmul(x, y, name=None): ...@@ -104,13 +104,13 @@ def matmul(x, y, name=None):
@dygraph_only @dygraph_only
def masked_matmul(x, y, mask, name=None): def masked_matmul(x, y, mask, name=None):
""" """
Note: Note:
This API is only supported from ``CUDA 11.3`` . This API is only supported from ``CUDA 11.3`` .
Applies matrix multiplication of two Dense Tensors. Applies matrix multiplication of two Dense Tensors.
The supported input/output Tensor layout are as follows: The supported input/output Tensor layout are as follows:
Note: Note:
x[DenseTensor] @ y[DenseTensor] * mask[SparseCooTensor] -> out[SparseCooTensor] x[DenseTensor] @ y[DenseTensor] * mask[SparseCooTensor] -> out[SparseCooTensor]
x[DenseTensor] @ y[DenseTensor] * mask[SparseCsrTensor] -> out[SparseCsrTensor] x[DenseTensor] @ y[DenseTensor] * mask[SparseCsrTensor] -> out[SparseCsrTensor]
...@@ -153,9 +153,9 @@ def masked_matmul(x, y, mask, name=None): ...@@ -153,9 +153,9 @@ def masked_matmul(x, y, mask, name=None):
y = paddle.rand([5, 4]) y = paddle.rand([5, 4])
out = paddle.sparse.masked_matmul(x, y, mask) out = paddle.sparse.masked_matmul(x, y, mask)
# Tensor(shape=[3, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True, # Tensor(shape=[3, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# crows=[0, 2, 3, 5], # crows=[0, 2, 3, 5],
# cols=[1, 3, 2, 0, 1], # cols=[1, 3, 2, 0, 1],
# values=[0.98986477, 0.97800624, 1.14591956, 0.68561077, 0.94714981]) # values=[0.98986477, 0.97800624, 1.14591956, 0.68561077, 0.94714981])
""" """
...@@ -165,11 +165,11 @@ def masked_matmul(x, y, mask, name=None): ...@@ -165,11 +165,11 @@ def masked_matmul(x, y, mask, name=None):
@dygraph_only @dygraph_only
def mv(x, vec, name=None): def mv(x, vec, name=None):
""" """
Note: Note:
This API is only supported from ``CUDA 11.0`` . This API is only supported from ``CUDA 11.0`` .
Applies matrix-vector product of Sparse Matrix 'x' and Dense vector 'vec' . Applies matrix-vector product of Sparse Matrix 'x' and Dense vector 'vec' .
The supported input/output Tensor layout are as follows: The supported input/output Tensor layout are as follows:
Note: Note:
...@@ -178,39 +178,39 @@ def mv(x, vec, name=None): ...@@ -178,39 +178,39 @@ def mv(x, vec, name=None):
It supports backward propagation. It supports backward propagation.
The shape of `x` should be `[M, N]` , and the shape of `y` should be `[N]` , The shape of `x` should be `[M, N]` , and the shape of `y` should be `[N]` ,
and the shape of `out` will be `[M]` . and the shape of `out` will be `[M]` .
Args: Args:
x (Tensor): The input 2D tensor. It must be SparseCooTensor/SparseCsrTensor. The data type can be float32 or float64. x (Tensor): The input 2D tensor. It must be SparseCooTensor/SparseCsrTensor. The data type can be float32 or float64.
y (Tensor): The input 1D tensor. It must be DenseTensor vector. The data type can be float32 or float64. y (Tensor): The input 1D tensor. It must be DenseTensor vector. The data type can be float32 or float64.
name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Returns: Returns:
Tensor: 1D Tensor. Tensor: 1D Tensor.
Examples: Examples:
.. code-block:: python .. code-block:: python
# required: gpu # required: gpu
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard from paddle.fluid.framework import _test_eager_guard
paddle.seed(100) paddle.seed(100)
# csr @ dense -> dense # csr @ dense -> dense
with _test_eager_guard(): with _test_eager_guard():
crows = [0, 2, 3, 5] crows = [0, 2, 3, 5]
cols = [1, 3, 2, 0, 1] cols = [1, 3, 2, 0, 1]
values = [1., 2., 3., 4., 5.] values = [1., 2., 3., 4., 5.]
dense_shape = [3, 4] dense_shape = [3, 4]
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape) csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape)
# Tensor(shape=[3, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True, # Tensor(shape=[3, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# crows=[0, 2, 3, 5], # crows=[0, 2, 3, 5],
# cols=[1, 3, 2, 0, 1], # cols=[1, 3, 2, 0, 1],
# values=[1., 2., 3., 4., 5.]) # values=[1., 2., 3., 4., 5.])
vec = paddle.randn([4]) vec = paddle.randn([4])
out = paddle.sparse.mv(csr, vec) out = paddle.sparse.mv(csr, vec)
# Tensor(shape=[3], dtype=float32, place=Place(gpu:0), stop_gradient=True, # Tensor(shape=[3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
# [-3.85499096, -2.42975140, -1.75087738]) # [-3.85499096, -2.42975140, -1.75087738])
...@@ -241,17 +241,15 @@ def add(x, y, name=None): ...@@ -241,17 +241,15 @@ def add(x, y, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
paddle.device.set_device("cpu") paddle.device.set_device("cpu")
with _test_eager_guard(): x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32')
x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32') y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32')
y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32') sparse_x = x.to_sparse_csr()
sparse_x = x.to_sparse_csr() sparse_y = y.to_sparse_csr()
sparse_y = y.to_sparse_csr() sparse_z = paddle.sparse.add(sparse_x, sparse_y)
sparse_z = paddle.sparse.add(sparse_x, sparse_y) print(sparse_z.to_dense())
print(sparse_z.to_dense())
# [[ 0., -1., 0., 0.], # [[ 0., -1., 0., 0.],
# [ 0., 2., -6., 0.], # [ 0., 2., -6., 0.],
...@@ -268,10 +266,9 @@ def add(x, y, name=None): ...@@ -268,10 +266,9 @@ def add(x, y, name=None):
inputs = {'x': x, 'y': y} inputs = {'x': x, 'y': y}
helper = LayerHelper(op_type) helper = LayerHelper(op_type)
out = helper.create_sparse_variable_for_type_inference(x.dtype) out = helper.create_sparse_variable_for_type_inference(x.dtype)
helper.append_op(type=op_type, helper.append_op(
inputs=inputs, type=op_type, inputs=inputs, outputs={'out': out}, attrs={}
outputs={'out': out}, )
attrs={})
return out return out
...@@ -298,17 +295,15 @@ def subtract(x, y, name=None): ...@@ -298,17 +295,15 @@ def subtract(x, y, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
paddle.device.set_device("cpu") paddle.device.set_device("cpu")
with _test_eager_guard(): x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32')
x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32') y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32')
y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32') sparse_x = x.to_sparse_csr()
sparse_x = x.to_sparse_csr() sparse_y = y.to_sparse_csr()
sparse_y = y.to_sparse_csr() sparse_z = paddle.sparse.subtract(sparse_x, sparse_y)
sparse_z = paddle.sparse.subtract(sparse_x, sparse_y) print(sparse_z.to_dense())
print(sparse_z.to_dense())
# [[ 0., -1., 0., 4.], # [[ 0., -1., 0., 4.],
# [ 0., -2., 0., 0.], # [ 0., -2., 0., 0.],
...@@ -343,17 +338,15 @@ def multiply(x, y, name=None): ...@@ -343,17 +338,15 @@ def multiply(x, y, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
paddle.device.set_device("cpu") paddle.device.set_device("cpu")
with _test_eager_guard(): x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32')
x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32') y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32')
y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32') sparse_x = x.to_sparse_csr()
sparse_x = x.to_sparse_csr() sparse_y = y.to_sparse_csr()
sparse_y = y.to_sparse_csr() sparse_z = paddle.sparse.multiply(sparse_x, sparse_y)
sparse_z = paddle.sparse.multiply(sparse_x, sparse_y) print(sparse_z.to_dense())
print(sparse_z.to_dense())
# [[ 0., 0., 0., -4.], # [[ 0., 0., 0., -4.],
# [ 0., 0., 9., 0.], # [ 0., 0., 9., 0.],
...@@ -391,17 +384,15 @@ def divide(x, y, name=None): ...@@ -391,17 +384,15 @@ def divide(x, y, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
paddle.device.set_device("cpu") paddle.device.set_device("cpu")
with _test_eager_guard(): x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32')
x = paddle.to_tensor([[0, -1, 0, 2], [0, 0, -3, 0], [4, 5, 0, 0]], 'float32') y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32')
y = paddle.to_tensor([[0, 0, 0, -2], [0, 2, -3, 0], [2, 3, 4, 8]], 'float32') sparse_x = x.to_sparse_csr()
sparse_x = x.to_sparse_csr() sparse_y = y.to_sparse_csr()
sparse_y = y.to_sparse_csr() sparse_z = paddle.sparse.divide(sparse_x, sparse_y)
sparse_z = paddle.sparse.divide(sparse_x, sparse_y) print(sparse_z.to_dense())
print(sparse_z.to_dense())
# [[ nan , -inf. , nan , -1. ], # [[ nan , -inf. , nan , -1. ],
# [ nan , 0. , 1. , nan ], # [ nan , 0. , 1. , nan ],
......
...@@ -17,7 +17,12 @@ from paddle import _C_ops, _legacy_C_ops ...@@ -17,7 +17,12 @@ from paddle import _C_ops, _legacy_C_ops
from paddle.fluid.framework import core, dygraph_only from paddle.fluid.framework import core, dygraph_only
from paddle.fluid.framework import _current_expected_place, _get_paddle_place from paddle.fluid.framework import _current_expected_place, _get_paddle_place
from paddle.tensor import to_tensor, max from paddle.tensor import to_tensor, max
from paddle.fluid.data_feeder import check_variable_and_dtype, check_type, check_dtype, convert_dtype from paddle.fluid.data_feeder import (
check_variable_and_dtype,
check_type,
check_dtype,
convert_dtype,
)
from paddle import in_dynamic_mode from paddle import in_dynamic_mode
from paddle.fluid.layer_helper import LayerHelper from paddle.fluid.layer_helper import LayerHelper
...@@ -51,8 +56,8 @@ def _get_place(place): ...@@ -51,8 +56,8 @@ def _get_place(place):
if place is None: if place is None:
place = _current_expected_place() place = _current_expected_place()
elif not isinstance( elif not isinstance(
place, place, (core.Place, core.CPUPlace, core.CUDAPinnedPlace, core.CUDAPlace)
(core.Place, core.CPUPlace, core.CUDAPinnedPlace, core.CUDAPlace)): ):
raise ValueError( raise ValueError(
"'place' must be any of paddle.Place, paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace" "'place' must be any of paddle.Place, paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace"
) )
...@@ -66,14 +71,11 @@ def _check_indices_dtype(dtype): ...@@ -66,14 +71,11 @@ def _check_indices_dtype(dtype):
) )
def sparse_coo_tensor(indices, def sparse_coo_tensor(
values, indices, values, shape=None, dtype=None, place=None, stop_gradient=True
shape=None, ):
dtype=None,
place=None,
stop_gradient=True):
r""" r"""
Constructs a sparse ``paddle.Tensor`` in coordinate format according to the indices Constructs a sparse ``paddle.Tensor`` in coordinate format according to the indices
and values of the specified non-zero elements. and values of the specified non-zero elements.
Args: Args:
...@@ -82,15 +84,15 @@ def sparse_coo_tensor(indices, ...@@ -82,15 +84,15 @@ def sparse_coo_tensor(indices,
values(list|tuple|ndarray|Tensor): Initial values for the tensor. values(list|tuple|ndarray|Tensor): Initial values for the tensor.
Can be a scalar, list, tuple, numpy\.ndarray, paddle\.Tensor. Can be a scalar, list, tuple, numpy\.ndarray, paddle\.Tensor.
shape(list|tuple, optional): The shape of the sparse tensor also represents the shape of shape(list|tuple, optional): The shape of the sparse tensor also represents the shape of
original dense tensor. If not provided the smallest shape will be inferred to original dense tensor. If not provided the smallest shape will be inferred to
hold all elements. hold all elements.
dtype(str|np.dtype, optional): The desired data type of returned tensor. Can be 'bool' , 'float16' , dtype(str|np.dtype, optional): The desired data type of returned tensor. Can be 'bool' , 'float16' ,
'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8', 'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8',
'complex64' , 'complex128'. Default: None, infers dtype from ``data`` 'complex64' , 'complex128'. Default: None, infers dtype from ``data``
except for python float number which gets dtype from ``get_default_type`` . except for python float number which gets dtype from ``get_default_type`` .
place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str, optional): The place to allocate Tensor. Can be place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str, optional): The place to allocate Tensor. Can be
CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is
string, It can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where ``x`` is the index of the GPUs. string, It can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where ``x`` is the index of the GPUs.
stop_gradient(bool, optional): Whether to block the gradient propagation of Autograd. Default: True. stop_gradient(bool, optional): Whether to block the gradient propagation of Autograd. Default: True.
Returns: Returns:
...@@ -98,37 +100,34 @@ def sparse_coo_tensor(indices, ...@@ -98,37 +100,34 @@ def sparse_coo_tensor(indices,
Raises: Raises:
TypeError: If the data type of ``values`` is not list, tuple, numpy.ndarray, paddle.Tensor TypeError: If the data type of ``values`` is not list, tuple, numpy.ndarray, paddle.Tensor
ValueError: If ``values`` is tuple|list, it can't contain nested tuple|list with different lengths , such as: [[1, 2], [3, 4, 5]]. If the ``indices`` is not a 2-D. ValueError: If ``values`` is tuple|list, it can't contain nested tuple|list with different lengths , such as: [[1, 2], [3, 4, 5]]. If the ``indices`` is not a 2-D.
TypeError: If ``dtype`` is not bool, float16, float32, float64, int8, int16, int32, int64, uint8, complex64, complex128 TypeError: If ``dtype`` is not bool, float16, float32, float64, int8, int16, int32, int64, uint8, complex64, complex128
ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace or specified pattern string. ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace or specified pattern string.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
indices = [[0, 1, 2], [1, 2, 0]]
with _test_eager_guard(): values = [1.0, 2.0, 3.0]
indices = [[0, 1, 2], [1, 2, 0]] dense_shape = [3, 3]
values = [1.0, 2.0, 3.0] coo = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape)
dense_shape = [3, 3] # print(coo)
coo = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape) # Tensor(shape=[2, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# print(coo) # indices=[[0, 1, 2],
# Tensor(shape=[2, 3], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True, # [1, 2, 0]],
# indices=[[0, 1, 2], # values=[1., 2., 3.])
# [1, 2, 0]],
# values=[1., 2., 3.])
""" """
if in_dynamic_mode(): if in_dynamic_mode():
place = _get_place(place) place = _get_place(place)
if not isinstance(indices, core.eager.Tensor): if not isinstance(indices, core.eager.Tensor):
indices = to_tensor(indices, indices = to_tensor(
dtype=None, indices, dtype=None, place=place, stop_gradient=True
place=place, )
stop_gradient=True)
if not isinstance(values, core.eager.Tensor): if not isinstance(values, core.eager.Tensor):
values = to_tensor(values, dtype, place, stop_gradient) values = to_tensor(values, dtype, place, stop_gradient)
if len(indices.shape) != 2: if len(indices.shape) != 2:
...@@ -141,8 +140,10 @@ def sparse_coo_tensor(indices, ...@@ -141,8 +140,10 @@ def sparse_coo_tensor(indices,
if nnz != values.shape[0]: if nnz != values.shape[0]:
raise ValueError( raise ValueError(
"the indices and values must have same number of non-zero, but get {} and {}" "the indices and values must have same number of non-zero, but get {} and {}".format(
.format(nnz, values.shape[0])) nnz, values.shape[0]
)
)
dense_dim = len(values.shape) - 1 dense_dim = len(values.shape) - 1
...@@ -162,11 +163,15 @@ def sparse_coo_tensor(indices, ...@@ -162,11 +163,15 @@ def sparse_coo_tensor(indices,
if shape < min_shape: if shape < min_shape:
raise ValueError( raise ValueError(
"the minimun shape required is {}, but get {}".format( "the minimun shape required is {}, but get {}".format(
min_shape, shape)) min_shape, shape
)
)
if len(shape) != sparse_dim + dense_dim: if len(shape) != sparse_dim + dense_dim:
raise ValueError( raise ValueError(
"the number of dimensions(len(shape) must be sparse_dim({}) + dense_dim({}), but get {}" "the number of dimensions(len(shape) must be sparse_dim({}) + dense_dim({}), but get {}".format(
.format(sparse_dim, dense_dim, len(shape))) sparse_dim, dense_dim, len(shape)
)
)
return _C_ops.sparse_sparse_coo_tensor(values, indices, shape) return _C_ops.sparse_sparse_coo_tensor(values, indices, shape)
...@@ -178,45 +183,40 @@ def sparse_coo_tensor(indices, ...@@ -178,45 +183,40 @@ def sparse_coo_tensor(indices,
attrs = {'dense_shape': shape} attrs = {'dense_shape': shape}
helper = LayerHelper(op_type) helper = LayerHelper(op_type)
out = helper.create_sparse_variable_for_type_inference(dtype) out = helper.create_sparse_variable_for_type_inference(dtype)
helper.append_op(type=op_type, helper.append_op(
inputs=inputs, type=op_type, inputs=inputs, outputs={'out': out}, attrs=attrs
outputs={'out': out}, )
attrs=attrs)
return out return out
#TODO: need to support shape is None # TODO: need to support shape is None
@dygraph_only @dygraph_only
def sparse_csr_tensor(crows, def sparse_csr_tensor(
cols, crows, cols, values, shape, dtype=None, place=None, stop_gradient=True
values, ):
shape,
dtype=None,
place=None,
stop_gradient=True):
r""" r"""
Constructs a sparse ``paddle.Tensor`` in CSR(Compressed Sparse Row) format according to the Constructs a sparse ``paddle.Tensor`` in CSR(Compressed Sparse Row) format according to the
``crows``, ``cols`` and ``values``. ``crows``, ``cols`` and ``values``.
Currently, the crows and cols of each batch must be incrementd. Currently, the crows and cols of each batch must be incrementd.
Args: Args:
crows(list|tuple|ndarray|Tensor): 1-D array, each element in the rows represents the crows(list|tuple|ndarray|Tensor): 1-D array, each element in the rows represents the
starting position of the first non-zero element of each row in values. starting position of the first non-zero element of each row in values.
Can be a list, tuple, numpy\.ndarray, paddle\.Tensor. Can be a list, tuple, numpy\.ndarray, paddle\.Tensor.
cols(list|tuple|ndarray|Tensor): 1-D array, the column of non-zero elements. cols(list|tuple|ndarray|Tensor): 1-D array, the column of non-zero elements.
Can be a list, tuple, numpy\.ndarray, paddle\.Tensor. Can be a list, tuple, numpy\.ndarray, paddle\.Tensor.
values(list|tuple|ndarray|Tensor): 1-D array, the non-zero elements. values(list|tuple|ndarray|Tensor): 1-D array, the non-zero elements.
Can be a scalar, list, tuple, numpy\.ndarray, paddle\.Tensor. Can be a scalar, list, tuple, numpy\.ndarray, paddle\.Tensor.
shape(list|tuple, optional): The shape of the sparse tensor also represents the shape of shape(list|tuple, optional): The shape of the sparse tensor also represents the shape of
original dense tensor. original dense tensor.
hold all elements. hold all elements.
dtype(str|np.dtype, optional): The desired data type of returned tensor. Can be 'bool' , 'float16' , dtype(str|np.dtype, optional): The desired data type of returned tensor. Can be 'bool' , 'float16' ,
'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8', 'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8',
'complex64' , 'complex128'. Default: None, infers dtype from ``data`` 'complex64' , 'complex128'. Default: None, infers dtype from ``data``
except for python float number which gets dtype from ``get_default_type`` . except for python float number which gets dtype from ``get_default_type`` .
place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str, optional): The place to allocate Tensor. Can be place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str, optional): The place to allocate Tensor. Can be
CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is
string, It can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where ``x`` is the index of the GPUs. string, It can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where ``x`` is the index of the GPUs.
stop_gradient(bool, optional): Whether to block the gradient propagation of Autograd. Default: True. stop_gradient(bool, optional): Whether to block the gradient propagation of Autograd. Default: True.
Returns: Returns:
...@@ -224,28 +224,26 @@ def sparse_csr_tensor(crows, ...@@ -224,28 +224,26 @@ def sparse_csr_tensor(crows,
Raises: Raises:
TypeError: If the data type of ``values`` is not list, tuple, numpy.ndarray, paddle.Tensor TypeError: If the data type of ``values`` is not list, tuple, numpy.ndarray, paddle.Tensor
ValueError: If ``values`` is tuple|list, it can't contain nested tuple|list with different lengths , such as: [[1, 2], [3, 4, 5]]. If the ``crow``, ``cols`` and ``values`` is not a 2-D. ValueError: If ``values`` is tuple|list, it can't contain nested tuple|list with different lengths , such as: [[1, 2], [3, 4, 5]]. If the ``crow``, ``cols`` and ``values`` is not a 2-D.
TypeError: If ``dtype`` is not bool, float16, float32, float64, int8, int16, int32, int64, uint8, complex64, complex128 TypeError: If ``dtype`` is not bool, float16, float32, float64, int8, int16, int32, int64, uint8, complex64, complex128
ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace or specified pattern string. ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace or specified pattern string.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
crows = [0, 2, 3, 5]
with _test_eager_guard(): cols = [1, 3, 2, 0, 1]
crows = [0, 2, 3, 5] values = [1, 2, 3, 4, 5]
cols = [1, 3, 2, 0, 1] dense_shape = [3, 4]
values = [1, 2, 3, 4, 5] csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape)
dense_shape = [3, 4] # print(csr)
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape) # Tensor(shape=[3, 4], dtype=paddle.int64, place=Place(gpu:0), stop_gradient=True,
# print(csr) # crows=[0, 2, 3, 5],
# Tensor(shape=[3, 4], dtype=paddle.int64, place=Place(gpu:0), stop_gradient=True, # cols=[1, 3, 2, 0, 1],
# crows=[0, 2, 3, 5], # values=[1, 2, 3, 4, 5])
# cols=[1, 3, 2, 0, 1],
# values=[1, 2, 3, 4, 5])
""" """
place = _get_place(place) place = _get_place(place)
...@@ -262,8 +260,10 @@ def sparse_csr_tensor(crows, ...@@ -262,8 +260,10 @@ def sparse_csr_tensor(crows,
if len(shape) != 2 and len(shape) != 3: if len(shape) != 2 and len(shape) != 3:
raise ValueError( raise ValueError(
"SparseCsrTensor only support 2-D or 3-D matrix. but get shape {}". "SparseCsrTensor only support 2-D or 3-D matrix. but get shape {}".format(
format(shape)) shape
)
)
rows = shape[len(shape) - 2] rows = shape[len(shape) - 2]
if not crows.place._equals(place): if not crows.place._equals(place):
...@@ -280,26 +280,32 @@ def sparse_csr_tensor(crows, ...@@ -280,26 +280,32 @@ def sparse_csr_tensor(crows,
if len(crows.shape) != 1 or len(cols.shape) != 1 or len(values.shape) != 1: if len(crows.shape) != 1 or len(cols.shape) != 1 or len(values.shape) != 1:
raise ValueError("The 'crows', 'cols' and 'values' must be 1-D.") raise ValueError("The 'crows', 'cols' and 'values' must be 1-D.")
if (len(cols) != len(values)): if len(cols) != len(values):
raise ValueError("the length of cols must be same as length of values") raise ValueError("the length of cols must be same as length of values")
if len(shape) == 2: if len(shape) == 2:
if crows.shape[0] != rows + 1: if crows.shape[0] != rows + 1:
raise ValueError( raise ValueError(
"The length({}) of crows must be equal to the rows({})+1 of matrix." "The length({}) of crows must be equal to the rows({})+1 of matrix.".format(
.format(crows.shape[0], rows)) crows.shape[0], rows
)
)
if crows[0] != 0: if crows[0] != 0:
raise ValueError("the 0th value of crows must be 0") raise ValueError("the 0th value of crows must be 0")
if crows[-1] != values.shape[0]: if crows[-1] != values.shape[0]:
raise ValueError( raise ValueError(
"the last value of crows must be equal the number of non-zero") "the last value of crows must be equal the number of non-zero"
)
else: else:
if crows.shape[0] % (rows + 1) != 0: if crows.shape[0] % (rows + 1) != 0:
raise ValueError( raise ValueError(
"The length({}) of crows must be divisible the rows({})+1 of matrix." "The length({}) of crows must be divisible the rows({})+1 of matrix.".format(
.format(crows.shape[0], rows)) crows.shape[0], rows
)
)
# TODO(zkh2016): check whether the value in crows and cols is legal # TODO(zkh2016): check whether the value in crows and cols is legal
return core.eager.sparse_csr_tensor(crows, cols, values, shape, return core.eager.sparse_csr_tensor(
stop_gradient) crows, cols, values, shape, stop_gradient
)
...@@ -23,50 +23,66 @@ from paddle.nn.functional.conv import _update_padding_nd ...@@ -23,50 +23,66 @@ from paddle.nn.functional.conv import _update_padding_nd
from paddle.fluid.layer_helper import LayerHelper from paddle.fluid.layer_helper import LayerHelper
def _conv3d(x, def _conv3d(
weight, x,
bias=None, weight,
stride=1, bias=None,
padding=0, stride=1,
dilation=1, padding=0,
groups=1, dilation=1,
subm=False, groups=1,
key=None, subm=False,
data_format="NDHWC", key=None,
name=None): data_format="NDHWC",
name=None,
):
assert groups == 1, "Currently, only support groups=1" assert groups == 1, "Currently, only support groups=1"
dims = 3 dims = 3
# Currently, only support 'NDHWC' # Currently, only support 'NDHWC'
if data_format not in ["NDHWC"]: if data_format not in ["NDHWC"]:
raise ValueError("Attr(data_format) should be 'NDHWC'. Received " raise ValueError(
"Attr(data_format): {}.".format(data_format)) "Attr(data_format) should be 'NDHWC'. Received "
"Attr(data_format): {}.".format(data_format)
)
if len(x.shape) != 5: if len(x.shape) != 5:
raise ValueError( raise ValueError(
"Input x should be 5D tensor, but received x with the shape of {}". "Input x should be 5D tensor, but received x with the shape of {}".format(
format(x.shape)) x.shape
)
)
channel_last = (data_format == "NDHWC") channel_last = data_format == "NDHWC"
channel_dim = -1 if channel_last else 1 channel_dim = -1 if channel_last else 1
if len(x.shape) != 5: if len(x.shape) != 5:
raise ValueError( raise ValueError(
"Input x should be 5D tensor, but received x with the shape of {}". "Input x should be 5D tensor, but received x with the shape of {}".format(
format(x.shape)) x.shape
)
)
num_channels = x.shape[channel_dim] num_channels = x.shape[channel_dim]
if num_channels < 0: if num_channels < 0:
raise ValueError( raise ValueError(
"The channel dimension of the input({}) should be defined. " "The channel dimension of the input({}) should be defined. "
"Received: {}.".format(x.shape, num_channels)) "Received: {}.".format(x.shape, num_channels)
)
padding, padding_algorithm = _update_padding_nd(padding, channel_last, dims) padding, padding_algorithm = _update_padding_nd(padding, channel_last, dims)
stride = convert_to_list(stride, dims, 'stride') stride = convert_to_list(stride, dims, 'stride')
dilation = convert_to_list(dilation, dims, 'dilation') dilation = convert_to_list(dilation, dims, 'dilation')
if in_dynamic_mode(): if in_dynamic_mode():
pre_bias = _C_ops.sparse_conv3d(x, weight, padding, dilation, stride, pre_bias = _C_ops.sparse_conv3d(
groups, subm, x,
key if key is not None else "") weight,
padding,
dilation,
stride,
groups,
subm,
key if key is not None else "",
)
if bias is not None: if bias is not None:
return add(pre_bias, bias) return add(pre_bias, bias)
else: else:
...@@ -79,44 +95,47 @@ def _conv3d(x, ...@@ -79,44 +95,47 @@ def _conv3d(x,
'strides': stride, 'strides': stride,
'groups': groups, 'groups': groups,
'subm': subm, 'subm': subm,
'key': key 'key': key,
} }
op_type = 'sparse_conv3d' op_type = 'sparse_conv3d'
helper = LayerHelper(op_type, **locals()) helper = LayerHelper(op_type, **locals())
rulebook = helper.create_variable_for_type_inference(dtype='int32', rulebook = helper.create_variable_for_type_inference(
stop_gradient=True) dtype='int32', stop_gradient=True
counter = helper.create_variable_for_type_inference(dtype='int32', )
stop_gradient=True) counter = helper.create_variable_for_type_inference(
dtype='int32', stop_gradient=True
)
pre_bias = helper.create_sparse_variable_for_type_inference(x.dtype) pre_bias = helper.create_sparse_variable_for_type_inference(x.dtype)
outputs = {"out": pre_bias, "rulebook": rulebook, "counter": counter} outputs = {"out": pre_bias, "rulebook": rulebook, "counter": counter}
helper.append_op(type=op_type, helper.append_op(
inputs=inputs, type=op_type, inputs=inputs, outputs=outputs, attrs=attrs
outputs=outputs, )
attrs=attrs)
if bias is not None: if bias is not None:
return add(pre_bias, bias) return add(pre_bias, bias)
else: else:
return pre_bias return pre_bias
def conv3d(x, def conv3d(
weight, x,
bias=None, weight,
stride=1, bias=None,
padding=0, stride=1,
dilation=1, padding=0,
groups=1, dilation=1,
data_format="NDHWC", groups=1,
name=None): data_format="NDHWC",
name=None,
):
r""" r"""
The sparse convolution3d functional calculates the output based on the input, filter The sparse convolution3d functional calculates the output based on the input, filter
and strides, paddings, dilations, groups parameters. Input(Input) and and strides, paddings, dilations, groups parameters. Input(Input) and
Output(Output) are multidimensional SparseCooTensors with a shape of Output(Output) are multidimensional SparseCooTensors with a shape of
:math:`[N, D, H, W, C]` . Where N is batch size, C is the number of :math:`[N, D, H, W, C]` . Where N is batch size, C is the number of
channels, D is the depth of the feature, H is the height of the feature, channels, D is the depth of the feature, H is the height of the feature,
and W is the width of the feature. If bias attribution is provided, and W is the width of the feature. If bias attribution is provided,
bias is added to the output of the convolution. bias is added to the output of the convolution.
For each input :math:`X`, the equation is: For each input :math:`X`, the equation is:
...@@ -132,36 +151,17 @@ def conv3d(x, ...@@ -132,36 +151,17 @@ def conv3d(x,
* :math:`b`: Bias value, a 1-D tensor with shape [M]. * :math:`b`: Bias value, a 1-D tensor with shape [M].
* :math:`Out`: Output value, the shape of :math:`Out` and :math:`X` may be different. * :math:`Out`: Output value, the shape of :math:`Out` and :math:`X` may be different.
Example:
- Input:
Input shape: :math:`(N, D_{in}, H_{in}, W_{in}, C_{in})`
Filter shape: :math:`(D_f, H_f, W_f, C_{in}, C_{out})`
- Output:
Output shape: :math:`(N, D_{out}, H_{out}, W_{out}, C_{out})`
Where
.. math::
D_{out}&= \\frac{(D_{in} + 2 * paddings[0] - (dilations[0] * (D_f - 1) + 1))}{strides[0]} + 1 \\\\
H_{out}&= \\frac{(H_{in} + 2 * paddings[1] - (dilations[1] * (H_f - 1) + 1))}{strides[1]} + 1 \\\\
W_{out}&= \\frac{(W_{in} + 2 * paddings[2] - (dilations[2] * (W_f - 1) + 1))}{strides[2]} + 1
Args: Args:
x (Tensor): The input is 5-D SparseCooTensor with shape [N, D, H, W, C], the data x (Tensor): The input is 5-D SparseCooTensor with shape [N, D, H, W, C], the data
type of input is float16 or float32 or float64. type of input is float16 or float32 or float64.
weight (Tensor): The convolution kernel, a Tensor with shape [kD, kH, kW, C/g, M], weight (Tensor): The convolution kernel, a Tensor with shape [kD, kH, kW, C/g, M],
where M is the number of filters(output channels), g is the number of groups, where M is the number of filters(output channels), g is the number of groups,
kD, kH, kW are the filter's depth, height and width respectively. kD, kH, kW are the filter's depth, height and width respectively.
bias (Tensor, optional): The bias, a Tensor of shape [M, ], currently, only support bias is None. bias (Tensor, optional): The bias, a Tensor of shape [M].
stride (int|list|tuple): The stride size. It means the stride in convolution. If stride is a stride (int|list|tuple, optional): The stride size. It means the stride in convolution. If stride is a
list/tuple, it must contain three integers, (stride_depth, stride_height, stride_width). list/tuple, it must contain three integers, (stride_depth, stride_height, stride_width).
Otherwise, stride_depth = stride_height = stride_width = stride. Default: stride = 1. Otherwise, stride_depth = stride_height = stride_width = stride. Default: stride = 1.
padding (string|int|list|tuple): The padding size. It means the number of zero-paddings padding (string|int|list|tuple, optional): The padding size. It means the number of zero-paddings
on both sides for each dimension. If `padding` is a string, either 'VALID' or on both sides for each dimension. If `padding` is a string, either 'VALID' or
'SAME' which is the padding algorithm. If padding size is a tuple or list, 'SAME' which is the padding algorithm. If padding size is a tuple or list,
it could be in three forms: `[pad_depth, pad_height, pad_width]` or it could be in three forms: `[pad_depth, pad_height, pad_width]` or
...@@ -171,67 +171,78 @@ def conv3d(x, ...@@ -171,67 +171,78 @@ def conv3d(x,
when `data_format` is `"NDHWC"`, `padding` can be in the form when `data_format` is `"NDHWC"`, `padding` can be in the form
`[[0,0], [pad_depth_front, pad_depth_back], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right], [0,0]]`. `[[0,0], [pad_depth_front, pad_depth_back], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right], [0,0]]`.
Default: padding = 0. Default: padding = 0.
dilation (int|list|tuple): The dilation size. It means the spacing between the kernel points. dilation (int|list|tuple, optional): The dilation size. It means the spacing between the kernel points.
If dilation is a list/tuple, it must contain three integers, (dilation_depth, dilation_height, If dilation is a list/tuple, it must contain three integers, (dilation_depth, dilation_height,
dilation_width). Otherwise, dilation_depth = dilation_height = dilation_width = dilation. dilation_width). Otherwise, dilation_depth = dilation_height = dilation_width = dilation.
Default: dilation = 1. Default: dilation = 1.
groups (int): The groups number of the Conv3D Layer. According to grouped groups (int, optional): The groups number of the Conv3D Layer. According to grouped
convolution in Alex Krizhevsky's Deep CNN paper: when group=2, convolution in Alex Krizhevsky's Deep CNN paper: when group=2,
the first half of the filters is only connected to the first half the first half of the filters is only connected to the first half
of the input channels, while the second half of the filters is only of the input channels, while the second half of the filters is only
connected to the second half of the input channels. Default: groups=1. Currently, only support groups=1. connected to the second half of the input channels. Default: groups=1. Currently, only support groups=1.
data_format (str, optional): Specify the data format of the input, and the data format of the output data_format (str, optional): Specify the data format of the input, and the data format of the output
will be consistent with that of the input. An optional string from: `"NCDHW"`, `"NDHWC"`. will be consistent with that of the input. An optional string from: `"NCDHW"`, `"NDHWC"`.
The default is `"NDHWC"`. When it is `"NDHWC"`, the data is stored in the order of: The default is `"NDHWC"`. When it is `"NDHWC"`, the data is stored in the order of:
`[batch_size, input_depth, input_height, input_width, input_channels]`. `[batch_size, input_depth, input_height, input_width, input_channels]`.
name(str|None): For detailed information, please refer name(str, optional): For detailed information, please refer
to :ref:`api_guide_Name`. Usually name is no need to set and to :ref:`api_guide_Name`. Usually name is no need to set and
None by default. None by default.
Returns: Returns:
A SparseCooTensor representing the conv3d, whose data type is the same with input. A SparseCooTensor representing the conv3d, whose data type is the same with input.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]]
with _test_eager_guard(): values = [[1], [2], [3], [4]]
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]] indices = paddle.to_tensor(indices, dtype='int32')
values = [[1], [2], [3], [4]] values = paddle.to_tensor(values, dtype='float32')
indices = paddle.to_tensor(indices, dtype='int32') dense_shape = [1, 1, 3, 4, 1]
values = paddle.to_tensor(values, dtype='float32') sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True)
dense_shape = [1, 1, 3, 4, 1] weight = paddle.randn((1, 3, 3, 1, 1), dtype='float32')
sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True) y = paddle.sparse.nn.functional.conv3d(sparse_x, weight)
weight = paddle.randn((1, 3, 3, 1, 1), dtype='float32') print(y.shape)
y = paddle.sparse.nn.functional.conv3d(sparse_x, weight) # (1, 1, 1, 2, 1)
print(y.shape)
# (1, 1, 1, 2, 1)
""" """
return _conv3d(x, weight, bias, stride, padding, dilation, groups, False, return _conv3d(
None, data_format, name) x,
weight,
bias,
def subm_conv3d(x, stride,
weight, padding,
bias=None, dilation,
stride=1, groups,
padding=0, False,
dilation=1, None,
groups=1, data_format,
data_format="NDHWC", name,
key=None, )
name=None):
def subm_conv3d(
x,
weight,
bias=None,
stride=1,
padding=0,
dilation=1,
groups=1,
data_format="NDHWC",
key=None,
name=None,
):
r""" r"""
The sparse submanifold convolution3d functional calculates the output based on the input, filter The sparse submanifold convolution3d functional calculates the output based on the input, filter
and strides, paddings, dilations, groups parameters. Input(Input) and and strides, paddings, dilations, groups parameters. Input(Input) and
Output(Output) are multidimensional SparseCooTensors with a shape of Output(Output) are multidimensional SparseCooTensors with a shape of
:math:`[N, D, H, W, C]` . Where N is batch size, C is the number of :math:`[N, D, H, W, C]` . Where N is batch size, C is the number of
channels, D is the depth of the feature, H is the height of the feature, channels, D is the depth of the feature, H is the height of the feature,
and W is the width of the feature. If bias attribution is provided, and W is the width of the feature. If bias attribution is provided,
bias is added to the output of the convolution. bias is added to the output of the convolution.
For each input :math:`X`, the equation is: For each input :math:`X`, the equation is:
...@@ -247,36 +258,17 @@ def subm_conv3d(x, ...@@ -247,36 +258,17 @@ def subm_conv3d(x,
* :math:`b`: Bias value, a 1-D tensor with shape [M]. * :math:`b`: Bias value, a 1-D tensor with shape [M].
* :math:`Out`: Output value, the shape of :math:`Out` and :math:`X` may be different. * :math:`Out`: Output value, the shape of :math:`Out` and :math:`X` may be different.
Example:
- Input:
Input shape: :math:`(N, D_{in}, H_{in}, W_{in}, C_{in})`
Filter shape: :math:`(D_f, H_f, W_f, C_{in}, C_{out})`
- Output:
Output shape: :math:`(N, D_{out}, H_{out}, W_{out}, C_{out})`
Where
.. math::
D_{out}&= \\frac{(D_{in} + 2 * paddings[0] - (dilations[0] * (D_f - 1) + 1))}{strides[0]} + 1 \\\\
H_{out}&= \\frac{(H_{in} + 2 * paddings[1] - (dilations[1] * (H_f - 1) + 1))}{strides[1]} + 1 \\\\
W_{out}&= \\frac{(W_{in} + 2 * paddings[2] - (dilations[2] * (W_f - 1) + 1))}{strides[2]} + 1
Args: Args:
x (Tensor): The input is 5-D SparseCooTensor with shape [N, D, H, W, C], the data x (Tensor): The input is 5-D SparseCooTensor with shape [N, D, H, W, C], the data
type of input is float16 or float32 or float64. type of input is float16 or float32 or float64.
weight (Tensor): The convolution kernel, a Tensor with shape [kD, kH, kW, C/g, M], weight (Tensor): The convolution kernel, a Tensor with shape [kD, kH, kW, C/g, M],
where M is the number of filters(output channels), g is the number of groups, where M is the number of filters(output channels), g is the number of groups,
kD, kH, kW are the filter's depth, height and width respectively. kD, kH, kW are the filter's depth, height and width respectively.
bias (Tensor, optional): The bias, a Tensor of shape [M, ], currently, only support bias is None. bias (Tensor, optional): The bias, a Tensor of shape [M].
stride (int|list|tuple): The stride size. It means the stride in convolution. If stride is a stride (int|list|tuple, optional): The stride size. It means the stride in convolution. If stride is a
list/tuple, it must contain three integers, (stride_depth, stride_height, stride_width). list/tuple, it must contain three integers, (stride_depth, stride_height, stride_width).
Otherwise, stride_depth = stride_height = stride_width = stride. Default: stride = 1. Otherwise, stride_depth = stride_height = stride_width = stride. Default: stride = 1.
padding (string|int|list|tuple): The padding size. It means the number of zero-paddings padding (string|int|list|tuple): The padding size. It means the number of zero-paddings
on both sides for each dimension. If `padding` is a string, either 'VALID' or on both sides for each dimension. If `padding` is a string, either 'VALID' or
'SAME' which is the padding algorithm. If padding size is a tuple or list, 'SAME' which is the padding algorithm. If padding size is a tuple or list,
it could be in three forms: `[pad_depth, pad_height, pad_width]` or it could be in three forms: `[pad_depth, pad_height, pad_width]` or
...@@ -286,48 +278,57 @@ def subm_conv3d(x, ...@@ -286,48 +278,57 @@ def subm_conv3d(x,
when `data_format` is `"NHWC"`, `padding` can be in the form when `data_format` is `"NHWC"`, `padding` can be in the form
`[[0,0], [pad_depth_front, pad_depth_back], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right], [0,0]]`. `[[0,0], [pad_depth_front, pad_depth_back], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right], [0,0]]`.
Default: padding = 0. Default: padding = 0.
dilation (int|list|tuple): The dilation size. It means the spacing between the kernel points. dilation (int|list|tuple, optional): The dilation size. It means the spacing between the kernel points.
If dilation is a list/tuple, it must contain three integers, (dilation_depth, dilation_height, If dilation is a list/tuple, it must contain three integers, (dilation_depth, dilation_height,
dilation_width). Otherwise, dilation_depth = dilation_height = dilation_width = dilation. dilation_width). Otherwise, dilation_depth = dilation_height = dilation_width = dilation.
Default: dilation = 1. Default: dilation = 1.
groups (int): The groups number of the Conv3D Layer. According to grouped groups (int, optional): The groups number of the Conv3D Layer. According to grouped
convolution in Alex Krizhevsky's Deep CNN paper: when group=2, convolution in Alex Krizhevsky's Deep CNN paper: when group=2,
the first half of the filters is only connected to the first half the first half of the filters is only connected to the first half
of the input channels, while the second half of the filters is only of the input channels, while the second half of the filters is only
connected to the second half of the input channels. Currently, only support groups=1. connected to the second half of the input channels. Currently, only support groups=1.
data_format (str, optional): Specify the data format of the input, and the data format of the output data_format (str, optional): Specify the data format of the input, and the data format of the output
will be consistent with that of the input. An optional string from: `"NCDHW"`, `"NDHWC"`. will be consistent with that of the input. An optional string from: `"NCDHW"`, `"NDHWC"`.
The default is `"NDHWC"`. When it is `"NDHWC"`, the data is stored in the order of: The default is `"NDHWC"`. When it is `"NDHWC"`, the data is stored in the order of:
`[batch_size, input_depth, input_height, input_width, input_channels]`. `[batch_size, input_depth, input_height, input_width, input_channels]`.
key(str, optional): the key is used to save or use the same rulebook, key(str, optional): the key is used to save or use the same rulebook,
the definition and role of rulebook refers to the definition and role of rulebook refers to
https://pdfs.semanticscholar.org/5125/a16039cabc6320c908a4764f32596e018ad3.pdf. The https://pdfs.semanticscholar.org/5125/a16039cabc6320c908a4764f32596e018ad3.pdf. The
default value is None. default value is None.
name(str|None): For detailed information, please refer name(str, optional): For detailed information, please refer
to :ref:`api_guide_Name`. Usually name is no need to set and to :ref:`api_guide_Name`. Usually name is no need to set and
None by default. None by default.
Returns: Returns:
A SparseCooTensor representing the conv3d, whose data type is A SparseCooTensor representing the conv3d, whose data type is
the same with input. the same with input.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]]
with _test_eager_guard(): values = [[1], [2], [3], [4]]
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]] indices = paddle.to_tensor(indices, dtype='int32')
values = [[1], [2], [3], [4]] values = paddle.to_tensor(values, dtype='float32')
indices = paddle.to_tensor(indices, dtype='int32') dense_shape = [1, 1, 3, 4, 1]
values = paddle.to_tensor(values, dtype='float32') sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True)
dense_shape = [1, 1, 3, 4, 1] weight = paddle.randn((1, 3, 3, 1, 1), dtype='float32')
sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True) y = paddle.sparse.nn.functional.subm_conv3d(sparse_x, weight)
weight = paddle.randn((1, 3, 3, 1, 1), dtype='float32') print(y.shape)
y = paddle.sparse.nn.functional.subm_conv3d(sparse_x, weight) #(1, 1, 3, 4, 1)
print(y.shape)
#(1, 1, 3, 4, 1)
""" """
return _conv3d(x, weight, bias, stride, padding, dilation, groups, True, return _conv3d(
key, data_format, name) x,
weight,
bias,
stride,
padding,
dilation,
groups,
True,
key,
data_format,
name,
)
...@@ -19,13 +19,15 @@ from paddle.nn.functional.pooling import _update_padding_nd ...@@ -19,13 +19,15 @@ from paddle.nn.functional.pooling import _update_padding_nd
__all__ = [] __all__ = []
def max_pool3d(x, def max_pool3d(
kernel_size, x,
stride=None, kernel_size,
padding=0, stride=None,
ceil_mode=False, padding=0,
data_format="NDHWC", ceil_mode=False,
name=None): data_format="NDHWC",
name=None,
):
""" """
Implements sparse max pooling 3d operation. Implements sparse max pooling 3d operation.
See more details in :ref:`api_sparse_pooling_MaxPool3d` . See more details in :ref:`api_sparse_pooling_MaxPool3d` .
...@@ -37,47 +39,48 @@ def max_pool3d(x, ...@@ -37,47 +39,48 @@ def max_pool3d(x,
is a tuple or list, it must contain three integers, is a tuple or list, it must contain three integers,
(kernel_size_Depth, kernel_size_Height, kernel_size_Width). (kernel_size_Depth, kernel_size_Height, kernel_size_Width).
Otherwise, the pool kernel size will be the cube of an int. Otherwise, the pool kernel size will be the cube of an int.
stride (int|list|tuple): The pool stride size. If pool stride size is a tuple or list, stride (int|list|tuple, optional): The pool stride size. If pool stride size is a tuple or list,
it must contain three integers, [stride_Depth, stride_Height, stride_Width). it must contain three integers, [stride_Depth, stride_Height, stride_Width).
Otherwise, the pool stride size will be a cube of an int. Otherwise, the pool stride size will be a cube of an int.
padding (string|int|list|tuple): The padding size. Padding could be in one of the following forms. padding (string|int|list|tuple, optional): The padding size. Padding could be in one of the following forms.
1. A string in ['valid', 'same']. 1. A string in ['valid', 'same'].
2. An int, which means the feature map is zero padded by size of `padding` on every sides. 2. An int, which means the feature map is zero padded by size of `padding` on every sides.
3. A list[int] or tuple(int) whose length is 3, [pad_depth, pad_height, pad_weight] whose value means the padding size of each dimension. 3. A list[int] or tuple(int) whose length is 3, [pad_depth, pad_height, pad_weight] whose value means the padding size of each dimension.
4. A list[int] or tuple(int) whose length is 6. [pad_depth_front, pad_depth_back, pad_height_top, pad_height_bottom, pad_width_left, pad_width_right] whose value means the padding size of each side. 4. A list[int] or tuple(int) whose length is 6. [pad_depth_front, pad_depth_back, pad_height_top, pad_height_bottom, pad_width_left, pad_width_right] whose value means the padding size of each side.
5. A list or tuple of pairs of integers. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension should be [0,0] or (0,0). 5. A list or tuple of pairs of integers. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension should be [0,0] or (0,0).
The default value is 0. The default value is 0.
ceil_mode (bool): ${ceil_mode_comment} ceil_mode (bool, optional): ${ceil_mode_comment}
data_format (string): The data format of the input and output data. An optional string from: `"NCDHW"`, `"NDHWC"`. data_format (string, optional): The data format of the input and output data. An optional string from: `"NCDHW"`, `"NDHWC"`.
The default is `"NCDHW"`. When it is `"NCDHW"`, the data is stored in the order of: The default is `"NCDHW"`. When it is `"NCDHW"`, the data is stored in the order of:
`[batch_size, input_channels, input_depth, input_height, input_width]`. Currently only support `"NDHWC"` . `[batch_size, input_channels, input_depth, input_height, input_width]`. Currently only support `"NDHWC"` .
name(str, optional): For detailed information, please refer name(str, optional): For detailed information, please refer
to :ref:`api_guide_Name`. Usually name is no need to set and to :ref:`api_guide_Name`. Usually name is no need to set and
None by default. None by default.
Returns: Returns:
Tensor: The output tensor of pooling result. The data type is same as input tensor. Tensor: The output tensor of pooling result. The data type is same as input tensor.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
with _test_eager_guard(): dense_x = paddle.randn((1, 4, 4, 4, 3))
dense_x = paddle.randn((1, 4, 4, 4, 3)) sparse_x = dense_x.to_sparse_coo(4)
sparse_x = dense_x.to_sparse_coo(4) kernel_sizes = [3, 3, 3]
kernel_sizes = [3, 3, 3] paddings = [0, 0, 0]
paddings = [0, 0, 0] strides = [1, 1, 1]
strides = [1, 1, 1] out = paddle.sparse.nn.functional.max_pool3d(sparse_x, kernel_sizes, stride=strides, padding=paddings)
out = paddle.sparse.nn.functional.max_pool3d(sparse_x, kernel_sizes, stride=strides, padding=paddings) #[1, 2, 2, 2, 3]
#[1, 2, 2, 2, 3]
""" """
assert in_dynamic_mode(), "Currently, Sparse API only support dynamic mode" assert in_dynamic_mode(), "Currently, Sparse API only support dynamic mode"
assert x.is_sparse_coo( assert (
x.is_sparse_coo()
), "Currently, sparse.relu only support the input of SparseCooTensor" ), "Currently, sparse.relu only support the input of SparseCooTensor"
assert data_format == 'NDHWC', "Currently, sparse.max_pool3d only support data format of 'NDHWC'" assert (
data_format == 'NDHWC'
), "Currently, sparse.max_pool3d only support data format of 'NDHWC'"
kernel_size = utils.convert_to_list(kernel_size, 3, 'pool_size') kernel_size = utils.convert_to_list(kernel_size, 3, 'pool_size')
if stride is None: if stride is None:
...@@ -87,12 +90,11 @@ def max_pool3d(x, ...@@ -87,12 +90,11 @@ def max_pool3d(x,
channel_last = True channel_last = True
padding, padding_algorithm = _update_padding_nd(padding, padding, padding_algorithm = _update_padding_nd(
3, padding, 3, channel_last=channel_last, ceil_mode=ceil_mode
channel_last=channel_last, )
ceil_mode=ceil_mode)
#TODO(zkh2016): remove the dependency on dilation from the backend # TODO(zkh2016): remove the dependency on dilation from the backend
dilation = [1, 1, 1] dilation = [1, 1, 1]
return _C_ops.sparse_maxpool(x, kernel_size, padding, dilation, stride) return _C_ops.sparse_maxpool(x, kernel_size, padding, dilation, stride)
...@@ -23,23 +23,26 @@ __all__ = [] ...@@ -23,23 +23,26 @@ __all__ = []
class _Conv3D(Layer): class _Conv3D(Layer):
def __init__(
def __init__(self, self,
in_channels, in_channels,
out_channels, out_channels,
kernel_size, kernel_size,
stride=1, stride=1,
padding=0, padding=0,
dilation=1, dilation=1,
groups=1, groups=1,
subm=False, subm=False,
key=None, key=None,
padding_mode='zeros', padding_mode='zeros',
weight_attr=None, weight_attr=None,
bias_attr=None, bias_attr=None,
data_format="NDHWC"): data_format="NDHWC",
):
super(_Conv3D, self).__init__() super(_Conv3D, self).__init__()
assert weight_attr is not False, "weight_attr should not be False in Conv." assert (
weight_attr is not False
), "weight_attr should not be False in Conv."
self._param_attr = weight_attr self._param_attr = weight_attr
self._bias_attr = bias_attr self._bias_attr = bias_attr
self._groups = groups self._groups = groups
...@@ -49,56 +52,66 @@ class _Conv3D(Layer): ...@@ -49,56 +52,66 @@ class _Conv3D(Layer):
self._subm = subm self._subm = subm
self._key = key self._key = key
assert padding_mode == 'zeros', "Currently, only support padding_mode='zeros'" assert (
padding_mode == 'zeros'
), "Currently, only support padding_mode='zeros'"
assert groups == 1, "Currently, only support groups=1" assert groups == 1, "Currently, only support groups=1"
valid_format = {'NDHWC'} valid_format = {'NDHWC'}
if data_format not in valid_format: if data_format not in valid_format:
raise ValueError( raise ValueError(
"data_format must be one of {}, but got data_format='{}'". "data_format must be one of {}, but got data_format='{}'".format(
format(valid_format, data_format)) valid_format, data_format
)
)
channel_last = data_format == "NDHWC" channel_last = data_format == "NDHWC"
dims = 3 dims = 3
self._stride = utils.convert_to_list(stride, dims, 'stride') self._stride = utils.convert_to_list(stride, dims, 'stride')
self._dilation = utils.convert_to_list(dilation, dims, 'dilation') self._dilation = utils.convert_to_list(dilation, dims, 'dilation')
self._kernel_size = utils.convert_to_list(kernel_size, dims, self._kernel_size = utils.convert_to_list(
'kernel_size') kernel_size, dims, 'kernel_size'
)
self._padding = padding self._padding = padding
self._padding_mode = padding_mode self._padding_mode = padding_mode
self._updated_padding, self._padding_algorithm = _update_padding_nd( self._updated_padding, self._padding_algorithm = _update_padding_nd(
padding, channel_last, dims) padding, channel_last, dims
)
# the sparse conv restricts the shape is [D, H, W, in_channels, out_channels] # the sparse conv restricts the shape is [D, H, W, in_channels, out_channels]
filter_shape = self._kernel_size + [ filter_shape = self._kernel_size + [
self._in_channels, self._out_channels self._in_channels,
self._out_channels,
] ]
def _get_default_param_initializer(): def _get_default_param_initializer():
filter_elem_num = np.prod(self._kernel_size) * self._in_channels filter_elem_num = np.prod(self._kernel_size) * self._in_channels
std = (2.0 / filter_elem_num)**0.5 std = (2.0 / filter_elem_num) ** 0.5
return Normal(0.0, std) return Normal(0.0, std)
self.weight = self.create_parameter( self.weight = self.create_parameter(
shape=filter_shape, shape=filter_shape,
attr=self._param_attr, attr=self._param_attr,
default_initializer=_get_default_param_initializer()) default_initializer=_get_default_param_initializer(),
self.bias = self.create_parameter(attr=self._bias_attr, )
shape=[self._out_channels], self.bias = self.create_parameter(
is_bias=True) attr=self._bias_attr, shape=[self._out_channels], is_bias=True
)
def forward(self, x): def forward(self, x):
out = F.conv._conv3d(x, out = F.conv._conv3d(
self.weight, x,
bias=self.bias, self.weight,
stride=self._stride, bias=self.bias,
padding=self._updated_padding, stride=self._stride,
dilation=self._dilation, padding=self._updated_padding,
groups=self._groups, dilation=self._dilation,
subm=self._subm, groups=self._groups,
key=self._key, subm=self._subm,
data_format=self._data_format) key=self._key,
data_format=self._data_format,
)
return out return out
def extra_repr(self): def extra_repr(self):
...@@ -122,11 +135,11 @@ class Conv3D(_Conv3D): ...@@ -122,11 +135,11 @@ class Conv3D(_Conv3D):
**Sparse Convlution3d Layer** **Sparse Convlution3d Layer**
The Sparse convolution3d layer calculates the output based on the input, filter The Sparse convolution3d layer calculates the output based on the input, filter
and strides, paddings, dilations, groups parameters. Input(Input) and and strides, paddings, dilations, groups parameters. Input(Input) and
Output(Output) are multidimensional SparseCooTensors with a shape of Output(Output) are multidimensional SparseCooTensors with a shape of
:math:`[N, D, H, W, C]` . Where N is batch size, C is the number of :math:`[N, D, H, W, C]` . Where N is batch size, C is the number of
channels, D is the depth of the feature, H is the height of the feature, channels, D is the depth of the feature, H is the height of the feature,
and W is the width of the feature. If bias attribution is provided, and W is the width of the feature. If bias attribution is provided,
bias is added to the output of the convolution. bias is added to the output of the convolution.
For each input :math:`X`, the equation is: For each input :math:`X`, the equation is:
.. math:: .. math::
...@@ -150,7 +163,7 @@ class Conv3D(_Conv3D): ...@@ -150,7 +163,7 @@ class Conv3D(_Conv3D):
stride_D = stride_H = stride_W = stride. The default value is 1. stride_D = stride_H = stride_W = stride. The default value is 1.
padding(int|str|tuple|list, optional): The padding size. Padding coule be in one of the following forms. padding(int|str|tuple|list, optional): The padding size. Padding coule be in one of the following forms.
1. a string in ['valid', 'same']. 1. a string in ['valid', 'same'].
2. an int, which means each spartial dimension(depth, height, width) is zero paded by size of `padding` 2. an int, which means each spartial dimension(depth, height, width) is zero paded by size of `padding`
3. a list[int] or tuple[int] whose length is the number of spartial dimensions, which contains the amount of padding on each side for each spartial dimension. It has the form [pad_d1, pad_d2, ...]. 3. a list[int] or tuple[int] whose length is the number of spartial dimensions, which contains the amount of padding on each side for each spartial dimension. It has the form [pad_d1, pad_d2, ...].
4. a list[int] or tuple[int] whose length is 2 * number of spartial dimensions. It has the form [pad_before, pad_after, pad_before, pad_after, ...] for all spartial dimensions. 4. a list[int] or tuple[int] whose length is 2 * number of spartial dimensions. It has the form [pad_before, pad_after, pad_before, pad_after, ...] for all spartial dimensions.
5. a list or tuple of pairs of ints. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension are also included. Each pair of integers correspond to the amount of padding for a dimension of the input. Padding in batch dimension and channel dimension should be [0, 0] or (0, 0). 5. a list or tuple of pairs of ints. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension are also included. Each pair of integers correspond to the amount of padding for a dimension of the input. Padding in batch dimension and channel dimension should be [0, 0] or (0, 0).
...@@ -208,63 +221,65 @@ class Conv3D(_Conv3D): ...@@ -208,63 +221,65 @@ class Conv3D(_Conv3D):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]]
with _test_eager_guard(): values = [[1], [2], [3], [4]]
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]] indices = paddle.to_tensor(indices, dtype='int32')
values = [[1], [2], [3], [4]] values = paddle.to_tensor(values, dtype='float32')
indices = paddle.to_tensor(indices, dtype='int32') dense_shape = [1, 1, 3, 4, 1]
values = paddle.to_tensor(values, dtype='float32') sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True)
dense_shape = [1, 1, 3, 4, 1] conv = paddle.sparse.nn.Conv3D(1, 1, (1, 3, 3))
sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True) y = conv(sparse_x)
conv = paddle.sparse.nn.Conv3D(1, 1, (1, 3, 3)) print(y.shape)
y = conv(sparse_x) # (1, 1, 1, 2, 1)
print(y.shape)
# (1, 1, 1, 2, 1)
""" """
def __init__(self, def __init__(
in_channels, self,
out_channels, in_channels,
kernel_size, out_channels,
stride=1, kernel_size,
padding=0, stride=1,
dilation=1, padding=0,
groups=1, dilation=1,
padding_mode='zeros', groups=1,
weight_attr=None, padding_mode='zeros',
bias_attr=None, weight_attr=None,
data_format="NDHWC"): bias_attr=None,
super(Conv3D, self).__init__(in_channels, data_format="NDHWC",
out_channels, ):
kernel_size, super(Conv3D, self).__init__(
stride=stride, in_channels,
padding=padding, out_channels,
dilation=dilation, kernel_size,
groups=groups, stride=stride,
subm=False, padding=padding,
key=None, dilation=dilation,
padding_mode=padding_mode, groups=groups,
weight_attr=weight_attr, subm=False,
bias_attr=bias_attr, key=None,
data_format=data_format) padding_mode=padding_mode,
weight_attr=weight_attr,
bias_attr=bias_attr,
data_format=data_format,
)
class SubmConv3D(_Conv3D): class SubmConv3D(_Conv3D):
r""" r"""
**Sparse Submanifold Convlution3d Layer** **Submanifold Sparse Convlution3d Layer**
The Sparse submanifold convolution3d layer calculates the output based on the input, filter The submanifold sparse convolution3d layer calculates the output based on the input, filter
and strides, paddings, dilations, groups parameters. Input(Input) and and strides, paddings, dilations, groups parameters. Input(Input) and
Output(Output) are multidimensional SparseCooTensors with a shape of Output(Output) are multidimensional SparseCooTensors with a shape of
:math:`[N, D, H, W, C]` . Where N is batch size, C is the number of :math:`[N, D, H, W, C]` . Where N is batch size, C is the number of
channels, D is the depth of the feature, H is the height of the feature, channels, D is the depth of the feature, H is the height of the feature,
and W is the width of the feature. If bias attribution is provided, and W is the width of the feature. If bias attribution is provided,
bias is added to the output of the convolution. bias is added to the output of the convolution.
For each input :math:`X`, the equation is: For each input :math:`X`, the equation is:
.. math:: .. math::
Out =(W \ast X + b Out = W \ast X + b
In the above equation: In the above equation:
...@@ -283,7 +298,7 @@ class SubmConv3D(_Conv3D): ...@@ -283,7 +298,7 @@ class SubmConv3D(_Conv3D):
stride_D = stride_H = stride_W = stride. The default value is 1. stride_D = stride_H = stride_W = stride. The default value is 1.
padding(int|str|tuple|list, optional): The padding size. Padding coule be in one of the following forms. padding(int|str|tuple|list, optional): The padding size. Padding coule be in one of the following forms.
1. a string in ['valid', 'same']. 1. a string in ['valid', 'same'].
2. an int, which means each spartial dimension(depth, height, width) is zero paded by size of `padding` 2. an int, which means each spartial dimension(depth, height, width) is zero paded by size of `padding`
3. a list[int] or tuple[int] whose length is the number of spartial dimensions, which contains the amount of padding on each side for each spartial dimension. It has the form [pad_d1, pad_d2, ...]. 3. a list[int] or tuple[int] whose length is the number of spartial dimensions, which contains the amount of padding on each side for each spartial dimension. It has the form [pad_d1, pad_d2, ...].
4. a list[int] or tuple[int] whose length is 2 * number of spartial dimensions. It has the form [pad_before, pad_after, pad_before, pad_after, ...] for all spartial dimensions. 4. a list[int] or tuple[int] whose length is 2 * number of spartial dimensions. It has the form [pad_before, pad_after, pad_before, pad_after, ...] for all spartial dimensions.
5. a list or tuple of pairs of ints. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension are also included. Each pair of integers correspond to the amount of padding for a dimension of the input. Padding in batch dimension and channel dimension should be [0, 0] or (0, 0). 5. a list or tuple of pairs of ints. It has the form [[pad_before, pad_after], [pad_before, pad_after], ...]. Note that, the batch dimension and channel dimension are also included. Each pair of integers correspond to the amount of padding for a dimension of the input. Padding in batch dimension and channel dimension should be [0, 0] or (0, 0).
...@@ -297,7 +312,7 @@ class SubmConv3D(_Conv3D): ...@@ -297,7 +312,7 @@ class SubmConv3D(_Conv3D):
of the input channels, while the second half of the filters is only of the input channels, while the second half of the filters is only
connected to the second half of the input channels. The default value is 1. connected to the second half of the input channels. The default value is 1.
padding_mode(str, optional): ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Currently only support ``'zeros'``. padding_mode(str, optional): ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Currently only support ``'zeros'``.
key(str, optional): the key is used to save or use the same rulebook, key(str, optional): the key is used to save or use the same rulebook,
the definition and role of rulebook refers to the definition and role of rulebook refers to
https://pdfs.semanticscholar.org/5125/a16039cabc6320c908a4764f32596e018ad3.pdf. The https://pdfs.semanticscholar.org/5125/a16039cabc6320c908a4764f32596e018ad3.pdf. The
default value is None. default value is None.
...@@ -345,44 +360,46 @@ class SubmConv3D(_Conv3D): ...@@ -345,44 +360,46 @@ class SubmConv3D(_Conv3D):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]]
with _test_eager_guard(): values = [[1], [2], [3], [4]]
indices = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 2], [1, 3, 2, 3]] dense_shape = [1, 1, 3, 4, 1]
values = [[1], [2], [3], [4]] indices = paddle.to_tensor(indices, dtype='int32')
dense_shape = [1, 1, 3, 4, 1] values = paddle.to_tensor(values, dtype='float32')
indices = paddle.to_tensor(indices, dtype='int32') sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True)
values = paddle.to_tensor(values, dtype='float32') subm_conv = paddle.sparse.nn.SubmConv3D(1, 1, (1, 3, 3))
sparse_x = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape, stop_gradient=True) y = subm_conv(sparse_x)
subm_conv = paddle.sparse.nn.SubmConv3D(1, 1, (1, 3, 3)) print(y.shape)
y = subm_conv(sparse_x) # (1, 1, 3, 4, 1)
print(y.shape)
# (1, 1, 3, 4, 1)
""" """
def __init__(self, def __init__(
in_channels, self,
out_channels, in_channels,
kernel_size, out_channels,
stride=1, kernel_size,
padding=0, stride=1,
dilation=1, padding=0,
groups=1, dilation=1,
padding_mode='zeros', groups=1,
key=None, padding_mode='zeros',
weight_attr=None, key=None,
bias_attr=None, weight_attr=None,
data_format="NDHWC"): bias_attr=None,
super(SubmConv3D, self).__init__(in_channels, data_format="NDHWC",
out_channels, ):
kernel_size, super(SubmConv3D, self).__init__(
stride=stride, in_channels,
padding=padding, out_channels,
dilation=dilation, kernel_size,
groups=groups, stride=stride,
subm=True, padding=padding,
key=key, dilation=dilation,
padding_mode=padding_mode, groups=groups,
weight_attr=weight_attr, subm=True,
bias_attr=bias_attr, key=key,
data_format=data_format) padding_mode=padding_mode,
weight_attr=weight_attr,
bias_attr=bias_attr,
data_format=data_format,
)
...@@ -83,18 +83,16 @@ class BatchNorm(paddle.nn.BatchNorm1D): ...@@ -83,18 +83,16 @@ class BatchNorm(paddle.nn.BatchNorm1D):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
paddle.seed(123)
with _test_eager_guard(): channels = 3
paddle.seed(123) x_data = paddle.randn((1, 6, 6, 6, channels)).astype('float32')
channels = 3 dense_x = paddle.to_tensor(x_data)
x_data = paddle.randn((1, 6, 6, 6, channels)).astype('float32') sparse_x = dense_x.to_sparse_coo(4)
dense_x = paddle.to_tensor(x_data) batch_norm = paddle.sparse.nn.BatchNorm(channels)
sparse_x = dense_x.to_sparse_coo(4) batch_norm_out = batch_norm(sparse_x)
batch_norm = paddle.sparse.nn.BatchNorm(channels) print(batch_norm_out.shape)
batch_norm_out = batch_norm(sparse_x) # [1, 6, 6, 6, 3]
print(batch_norm_out.shape)
# [1, 6, 6, 6, 3]
""" """
def __init__( def __init__(
...@@ -271,6 +269,8 @@ class SyncBatchNorm(paddle.nn.SyncBatchNorm): ...@@ -271,6 +269,8 @@ class SyncBatchNorm(paddle.nn.SyncBatchNorm):
will create ParamAttr as bias_attr. If the Initializer of the bias_attr will create ParamAttr as bias_attr. If the Initializer of the bias_attr
is not set, the bias is initialized zero. If it is set to False, this layer will not is not set, the bias is initialized zero. If it is set to False, this layer will not
have trainable bias parameter. Default: None. have trainable bias parameter. Default: None.
data_format(str, optional): Specify the input data format, may be "NCHW". Default "NCHW".
name(str, optional): Name for the BatchNorm, default is None. For more information, please refer to :ref:`api_guide_Name`..
Shapes: Shapes:
input: Tensor that the dimension from 2 to 5. input: Tensor that the dimension from 2 to 5.
...@@ -283,10 +283,8 @@ class SyncBatchNorm(paddle.nn.SyncBatchNorm): ...@@ -283,10 +283,8 @@ class SyncBatchNorm(paddle.nn.SyncBatchNorm):
# required: gpu # required: gpu
import paddle import paddle
import paddle.sparse.nn as nn import paddle.sparse.nn as nn
import numpy as np
x = np.array([[[[0.3, 0.4], [0.3, 0.07]], [[0.83, 0.37], [0.18, 0.93]]]]).astype('float32') x = paddle.to_tensor([[[[0.3, 0.4], [0.3, 0.07]], [[0.83, 0.37], [0.18, 0.93]]]], dtype='float32')
x = paddle.to_tensor(x)
x = x.to_sparse_coo(len(x.shape)-1) x = x.to_sparse_coo(len(x.shape)-1)
if paddle.is_compiled_with_cuda(): if paddle.is_compiled_with_cuda():
......
...@@ -61,26 +61,26 @@ class MaxPool3D(Layer): ...@@ -61,26 +61,26 @@ class MaxPool3D(Layer):
.. code-block:: python .. code-block:: python
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
with _test_eager_guard(): dense_x = paddle.randn((2, 3, 6, 6, 3))
dense_x = paddle.randn((2, 3, 6, 6, 3)) sparse_x = dense_x.to_sparse_coo(4)
sparse_x = dense_x.to_sparse_coo(4) max_pool3d = paddle.sparse.nn.MaxPool3D(
max_pool3d = paddle.sparse.nn.MaxPool3D( kernel_size=3, data_format='NDHWC')
kernel_size=3, data_format='NDHWC') out = max_pool3d(sparse_x)
out = max_pool3d(sparse_x) #shape=[2, 1, 2, 2, 3]
#shape=[2, 1, 2, 2, 3]
""" """
def __init__(self, def __init__(
kernel_size, self,
stride=None, kernel_size,
padding=0, stride=None,
return_mask=False, padding=0,
ceil_mode=False, return_mask=False,
data_format="NDHWC", ceil_mode=False,
name=None): data_format="NDHWC",
name=None,
):
super(MaxPool3D, self).__init__() super(MaxPool3D, self).__init__()
self.ksize = kernel_size self.ksize = kernel_size
self.stride = stride self.stride = stride
...@@ -91,14 +91,17 @@ class MaxPool3D(Layer): ...@@ -91,14 +91,17 @@ class MaxPool3D(Layer):
self.name = name self.name = name
def forward(self, x): def forward(self, x):
return F.max_pool3d(x, return F.max_pool3d(
kernel_size=self.ksize, x,
stride=self.stride, kernel_size=self.ksize,
padding=self.padding, stride=self.stride,
ceil_mode=self.ceil_mode, padding=self.padding,
data_format=self.data_format, ceil_mode=self.ceil_mode,
name=self.name) data_format=self.data_format,
name=self.name,
)
def extra_repr(self): def extra_repr(self):
return 'kernel_size={ksize}, stride={stride}, padding={padding}'.format( return 'kernel_size={ksize}, stride={stride}, padding={padding}'.format(
**self.__dict__) **self.__dict__
)
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
import numpy as np import numpy as np
from paddle import _C_ops, _legacy_C_ops from paddle import _C_ops, _legacy_C_ops
from paddle.fluid.framework import dygraph_only, core, convert_np_dtype_to_dtype_ from paddle.fluid.framework import (
dygraph_only,
core,
convert_np_dtype_to_dtype_,
)
__all__ = [] __all__ = []
...@@ -33,7 +37,7 @@ _int_dtype_ = [ ...@@ -33,7 +37,7 @@ _int_dtype_ = [
def sin(x, name=None): def sin(x, name=None):
""" """
Calculate elementwise sin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise sin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = sin(x) out = sin(x)
...@@ -54,7 +58,7 @@ def sin(x, name=None): ...@@ -54,7 +58,7 @@ def sin(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.sin(sparse_x) out = paddle.sparse.sin(sparse_x)
""" """
return _C_ops.sparse_sin(x) return _C_ops.sparse_sin(x)
...@@ -63,7 +67,7 @@ def sin(x, name=None): ...@@ -63,7 +67,7 @@ def sin(x, name=None):
def tan(x, name=None): def tan(x, name=None):
""" """
Calculate elementwise tan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise tan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = tan(x) out = tan(x)
...@@ -84,7 +88,7 @@ def tan(x, name=None): ...@@ -84,7 +88,7 @@ def tan(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.tan(sparse_x) out = paddle.sparse.tan(sparse_x)
""" """
return _C_ops.sparse_tan(x) return _C_ops.sparse_tan(x)
...@@ -93,7 +97,7 @@ def tan(x, name=None): ...@@ -93,7 +97,7 @@ def tan(x, name=None):
def asin(x, name=None): def asin(x, name=None):
""" """
Calculate elementwise asin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise asin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = asin(x) out = asin(x)
...@@ -114,7 +118,7 @@ def asin(x, name=None): ...@@ -114,7 +118,7 @@ def asin(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.asin(sparse_x) out = paddle.sparse.asin(sparse_x)
""" """
return _C_ops.sparse_asin(x) return _C_ops.sparse_asin(x)
...@@ -154,7 +158,7 @@ def transpose(x, perm, name=None): ...@@ -154,7 +158,7 @@ def transpose(x, perm, name=None):
def atan(x, name=None): def atan(x, name=None):
""" """
Calculate elementwise atan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise atan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = atan(x) out = atan(x)
...@@ -175,7 +179,7 @@ def atan(x, name=None): ...@@ -175,7 +179,7 @@ def atan(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.atan(sparse_x) out = paddle.sparse.atan(sparse_x)
""" """
return _C_ops.sparse_atan(x) return _C_ops.sparse_atan(x)
...@@ -184,7 +188,7 @@ def atan(x, name=None): ...@@ -184,7 +188,7 @@ def atan(x, name=None):
def sinh(x, name=None): def sinh(x, name=None):
""" """
Calculate elementwise sinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise sinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = sinh(x) out = sinh(x)
...@@ -205,7 +209,7 @@ def sinh(x, name=None): ...@@ -205,7 +209,7 @@ def sinh(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.sinh(sparse_x) out = paddle.sparse.sinh(sparse_x)
""" """
return _C_ops.sparse_sinh(x) return _C_ops.sparse_sinh(x)
...@@ -214,7 +218,7 @@ def sinh(x, name=None): ...@@ -214,7 +218,7 @@ def sinh(x, name=None):
def asinh(x, name=None): def asinh(x, name=None):
""" """
Calculate elementwise asinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise asinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = asinh(x) out = asinh(x)
...@@ -235,7 +239,7 @@ def asinh(x, name=None): ...@@ -235,7 +239,7 @@ def asinh(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.asinh(sparse_x) out = paddle.sparse.asinh(sparse_x)
""" """
return _C_ops.sparse_asinh(x) return _C_ops.sparse_asinh(x)
...@@ -244,7 +248,7 @@ def asinh(x, name=None): ...@@ -244,7 +248,7 @@ def asinh(x, name=None):
def atanh(x, name=None): def atanh(x, name=None):
""" """
Calculate elementwise atanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise atanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = atanh(x) out = atanh(x)
...@@ -265,7 +269,7 @@ def atanh(x, name=None): ...@@ -265,7 +269,7 @@ def atanh(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.atanh(sparse_x) out = paddle.sparse.atanh(sparse_x)
""" """
return _C_ops.sparse_atanh(x) return _C_ops.sparse_atanh(x)
...@@ -274,7 +278,7 @@ def atanh(x, name=None): ...@@ -274,7 +278,7 @@ def atanh(x, name=None):
def tanh(x, name=None): def tanh(x, name=None):
""" """
Calculate elementwise tanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise tanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = tanh(x) out = tanh(x)
...@@ -291,11 +295,11 @@ def tanh(x, name=None): ...@@ -291,11 +295,11 @@ def tanh(x, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.tanh(sparse_x) out = paddle.sparse.tanh(sparse_x)
""" """
return _C_ops.sparse_tanh(x) return _C_ops.sparse_tanh(x)
...@@ -304,7 +308,7 @@ def tanh(x, name=None): ...@@ -304,7 +308,7 @@ def tanh(x, name=None):
def square(x, name=None): def square(x, name=None):
""" """
Calculate elementwise square of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise square of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = square(x) out = square(x)
...@@ -321,11 +325,11 @@ def square(x, name=None): ...@@ -321,11 +325,11 @@ def square(x, name=None):
.. code-block:: python .. code-block:: python
import paddle import paddle
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.square(sparse_x) out = paddle.sparse.square(sparse_x)
""" """
return _C_ops.sparse_square(x) return _C_ops.sparse_square(x)
...@@ -334,7 +338,7 @@ def square(x, name=None): ...@@ -334,7 +338,7 @@ def square(x, name=None):
def sqrt(x, name=None): def sqrt(x, name=None):
""" """
Calculate elementwise sqrt of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor. Calculate elementwise sqrt of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
out = sqrt(x) out = sqrt(x)
...@@ -355,7 +359,7 @@ def sqrt(x, name=None): ...@@ -355,7 +359,7 @@ def sqrt(x, name=None):
dense_x = paddle.to_tensor([-2., 0., 1.]) dense_x = paddle.to_tensor([-2., 0., 1.])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.sqrt(sparse_x) out = paddle.sparse.sqrt(sparse_x)
""" """
return _C_ops.sparse_sqrt(x) return _C_ops.sparse_sqrt(x)
...@@ -385,7 +389,7 @@ def log1p(x, name=None): ...@@ -385,7 +389,7 @@ def log1p(x, name=None):
dense_x = paddle.to_tensor([-2, 0, 1], dtype='float32') dense_x = paddle.to_tensor([-2, 0, 1], dtype='float32')
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.log1p(sparse_x) out = paddle.sparse.log1p(sparse_x)
""" """
return _C_ops.sparse_log1p(x) return _C_ops.sparse_log1p(x)
...@@ -398,7 +402,7 @@ def cast(x, index_dtype=None, value_dtype=None, name=None): ...@@ -398,7 +402,7 @@ def cast(x, index_dtype=None, value_dtype=None, name=None):
Parameters: Parameters:
x (Tensor): The input Sparse Tensor with data type float32, float64. x (Tensor): The input Sparse Tensor with data type float32, float64.
index_dtype (np.dtype|str, optional): Data type of the index of SparseCooTensor, index_dtype (np.dtype|str, optional): Data type of the index of SparseCooTensor,
or crows/cols of SparseCsrTensor. Can be uint8, int8, int16, int32, int64. or crows/cols of SparseCsrTensor. Can be uint8, int8, int16, int32, int64.
value_dtype (np.dtype|str, optional): Data type of the value of SparseCooTensor, value_dtype (np.dtype|str, optional): Data type of the value of SparseCooTensor,
SparseCsrTensor. Can be bool, float16, float32, float64, int8, int32, int64, uint8. SparseCsrTensor. Can be bool, float16, float32, float64, int8, int32, int64, uint8.
...@@ -416,7 +420,7 @@ def cast(x, index_dtype=None, value_dtype=None, name=None): ...@@ -416,7 +420,7 @@ def cast(x, index_dtype=None, value_dtype=None, name=None):
dense_x = paddle.to_tensor([-2, 0, 1]) dense_x = paddle.to_tensor([-2, 0, 1])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.cast(sparse_x, 'int32', 'float64') out = paddle.sparse.cast(sparse_x, 'int32', 'float64')
""" """
if index_dtype and not isinstance(index_dtype, core.VarDesc.VarType): if index_dtype and not isinstance(index_dtype, core.VarDesc.VarType):
index_dtype = convert_np_dtype_to_dtype_(index_dtype) index_dtype = convert_np_dtype_to_dtype_(index_dtype)
...@@ -451,7 +455,7 @@ def pow(x, factor, name=None): ...@@ -451,7 +455,7 @@ def pow(x, factor, name=None):
dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32') dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.pow(sparse_x, 2) out = paddle.sparse.pow(sparse_x, 2)
""" """
return _C_ops.sparse_pow(x, float(factor)) return _C_ops.sparse_pow(x, float(factor))
...@@ -481,7 +485,7 @@ def neg(x, name=None): ...@@ -481,7 +485,7 @@ def neg(x, name=None):
dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32') dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.neg(sparse_x) out = paddle.sparse.neg(sparse_x)
""" """
return _C_ops.sparse_scale(x, -1.0, 0.0, True) return _C_ops.sparse_scale(x, -1.0, 0.0, True)
...@@ -511,18 +515,20 @@ def abs(x, name=None): ...@@ -511,18 +515,20 @@ def abs(x, name=None):
dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32') dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.abs(sparse_x) out = paddle.sparse.abs(sparse_x)
""" """
return _C_ops.sparse_abs(x) return _C_ops.sparse_abs(x)
@dygraph_only @dygraph_only
def coalesce(x): def coalesce(x, name=None):
r""" r"""
the coalesced operator include sorted and merge, after coalesced, the indices of x is sorted and unique. the coalesced operator include sorted and merge, after coalesced, the indices of x is sorted and unique.
Parameters: Parameters:
x (Tensor): the input SparseCooTensor. x (Tensor): the input SparseCooTensor.
name (str, optional): Name for the operation (optional, default is None).
For more information, please refer to :ref:`api_guide_Name`.
Returns: Returns:
Tensor: return the SparseCooTensor after coalesced. Tensor: return the SparseCooTensor after coalesced.
...@@ -540,7 +546,7 @@ def coalesce(x): ...@@ -540,7 +546,7 @@ def coalesce(x):
#[[0, 1], [1, 2]] #[[0, 1], [1, 2]]
print(sp_x.values()) print(sp_x.values())
#[3.0, 3.0] #[3.0, 3.0]
""" """
return _C_ops.sparse_coalesce(x) return _C_ops.sparse_coalesce(x)
...@@ -570,7 +576,7 @@ def rad2deg(x, name=None): ...@@ -570,7 +576,7 @@ def rad2deg(x, name=None):
dense_x = paddle.to_tensor([3.142, 0., -3.142]) dense_x = paddle.to_tensor([3.142, 0., -3.142])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.rad2deg(sparse_x) out = paddle.sparse.rad2deg(sparse_x)
""" """
if x.dtype in _int_dtype_: if x.dtype in _int_dtype_:
x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32) x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32)
...@@ -582,7 +588,7 @@ def deg2rad(x, name=None): ...@@ -582,7 +588,7 @@ def deg2rad(x, name=None):
""" """
Convert each of the elements of input x from degrees to angles in radians, Convert each of the elements of input x from degrees to angles in radians,
requiring x to be a SparseCooTensor or SparseCsrTensor. requiring x to be a SparseCooTensor or SparseCsrTensor.
.. math:: .. math::
deg2rad(x) = \pi * x / 180 deg2rad(x) = \pi * x / 180
...@@ -603,7 +609,7 @@ def deg2rad(x, name=None): ...@@ -603,7 +609,7 @@ def deg2rad(x, name=None):
dense_x = paddle.to_tensor([-180, 0, 180]) dense_x = paddle.to_tensor([-180, 0, 180])
sparse_x = dense_x.to_sparse_coo(1) sparse_x = dense_x.to_sparse_coo(1)
out = paddle.sparse.deg2rad(sparse_x) out = paddle.sparse.deg2rad(sparse_x)
""" """
if x.dtype in _int_dtype_: if x.dtype in _int_dtype_:
x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32) x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册