Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【不兼容升级】移除paddle.nn.functional.diag_embed,添加paddle.diag_embed并支持作为类方法 #58223

Merged
3 changes: 2 additions & 1 deletion python/paddle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
Tensor.__qualname__ = 'Tensor'

import paddle.distributed.fleet # noqa: F401

from paddle import ( # noqa: F401
distributed,
sysconfig,
Expand Down Expand Up @@ -113,6 +112,7 @@
create_parameter,
to_tensor,
diag,
diag_embed,
diagflat,
eye,
linspace,
Expand Down Expand Up @@ -566,6 +566,7 @@
'subtract',
'diag',
'diagflat',
'diag_embed',
'isnan',
'scatter_nd_add',
'unstack',
Expand Down
42 changes: 0 additions & 42 deletions python/paddle/nn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,48 +164,6 @@
from . import initializer # noqa: F401
from . import quant # noqa: F401

# TODO: remove 'diag_embed', 'remove_weight_norm', 'weight_norm' months later.
from paddle.utils import deprecated


@deprecated(
since="2.0.0",
update_to="paddle.nn.functional.diag_embed",
level=1,
reason="diag_embed in paddle.nn will be removed in future",
)
def diag_embed(*args):
'''
alias name of paddle.nn.functional.diag_embed
'''
return functional.diag_embed(*args)


@deprecated(
since="2.0.0",
update_to="paddle.nn.utils.remove_weight_norm",
level=1,
reason="remove_weight_norm in paddle.nn will be removed in future",
)
def remove_weight_norm(*args):
'''
alias name of paddle.nn.utils.remove_weight_norm
'''
return utils.remove_weight_norm(*args)


@deprecated(
since="2.0.0",
update_to="paddle.nn.utils.weight_norm",
level=1,
reason="weight_norm in paddle.nn will be removed in future",
)
def weight_norm(*args):
'''
alias name of paddle.nn.utils.weight_norm
'''
return utils.weight_norm(*args)


__all__ = [
'BatchNorm',
Expand Down
1 change: 0 additions & 1 deletion python/paddle/nn/functional/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@
'log_softmax',
'glu',
'gumbel_softmax',
'diag_embed',
'sequence_mask',
'dropout',
'dropout2d',
Expand Down
135 changes: 10 additions & 125 deletions python/paddle/nn/functional/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,141 +14,26 @@

# TODO: define the extention functions

import numpy as np

from paddle import _C_ops, _legacy_C_ops, in_dynamic_mode
from paddle import _C_ops, _legacy_C_ops, in_dynamic_mode, tensor
from paddle.utils import deprecated

from ...base.data_feeder import (
check_dtype,
check_type,
check_variable_and_dtype,
)
from ...base.data_feeder import check_type, check_variable_and_dtype
from ...base.layer_helper import LayerHelper
from ...common_ops_import import Variable
from ...framework import convert_np_dtype_to_dtype_, core
from ...tensor.creation import assign

__all__ = []


@deprecated(
since="2.5.2",
update_to="paddle.diag_embed",
level=1,
reason="diag_embed in paddle.nn.functional will be removed in future",
)
def diag_embed(input, offset=0, dim1=-2, dim2=-1):
"""
Creates a tensor whose diagonals of certain 2D planes (specified by dim1 and dim2)
are filled by ``input``. By default, a 2D plane formed by the last two dimensions
of the returned tensor will be selected.

The argument ``offset`` determines which diagonal is generated:

- If offset = 0, it is the main diagonal.
- If offset > 0, it is above the main diagonal.
- If offset < 0, it is below the main diagonal.

Args:
input(Tensor|numpy.ndarray): The input tensor. Must be at least 1-dimensional. The input data type should be float32, float64, int32, int64.
offset(int, optional): Which diagonal to consider. Default: 0 (main diagonal).
dim1(int, optional): The first dimension with respect to which to take diagonal. Default: -2.
dim2(int, optional): The second dimension with respect to which to take diagonal. Default: -1.

Returns:
Tensor, the output data type is the same as input data type.

Examples:
.. code-block:: python

>>> import paddle
>>> import paddle.nn.functional as F

>>> diag_embed_input = paddle.arange(6)

>>> diag_embed_output1 = F.diag_embed(diag_embed_input)
>>> print(diag_embed_output1)
Tensor(shape=[6, 6], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0],
[0, 0, 0, 3, 0, 0],
[0, 0, 0, 0, 4, 0],
[0, 0, 0, 0, 0, 5]])

>>> diag_embed_output2 = F.diag_embed(diag_embed_input, offset=-1, dim1=0,dim2=1 )
>>> print(diag_embed_output2)
Tensor(shape=[7, 7], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 0],
[0, 0, 0, 0, 4, 0, 0],
[0, 0, 0, 0, 0, 5, 0]])

>>> diag_embed_input_2dim = paddle.reshape(diag_embed_input,[2,3])
>>> print(diag_embed_input_2dim)
Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 1, 2],
[3, 4, 5]])
>>> diag_embed_output3 = F.diag_embed(diag_embed_input_2dim,offset= 0, dim1=0, dim2=2 )
>>> print(diag_embed_output3)
Tensor(shape=[3, 2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
[[[0, 0, 0],
[3, 0, 0]],
[[0, 1, 0],
[0, 4, 0]],
[[0, 0, 2],
[0, 0, 5]]])
"""
if not isinstance(input, Variable):
input = assign(input)

if in_dynamic_mode():
return _C_ops.diag_embed(input, offset, dim1, dim2)

inputs = {'Input': [input]}
attrs = {'offset': offset, 'dim1': dim1, 'dim2': dim2}

def __check_input(input, offset, dim1, dim2):
check_dtype(
input.dtype,
'Input',
['int32', 'int64', 'float16', 'float32', 'float64'],
'diag_embed',
)

input_shape = list(input.shape)
assert len(input_shape) >= 1, (
"Input must be at least 1-dimensional, "
"But received Input's dimensional: %s.\n" % len(input_shape)
)

assert np.abs(dim1) <= len(input_shape), (
"Dim1 is out of range (expected to be in range of [%d, %d], but got %d).\n"
% (-(len(input_shape) + 1), len(input_shape), dim1)
)

assert np.abs(dim2) <= len(input_shape), (
"Dim2 is out of range (expected to be in range of [%d, %d], but got %d).\n"
% (-(len(input_shape) + 1), len(input_shape), dim2)
)

dim1_ = dim1 if dim1 >= 0 else len(input_shape) + dim1 + 1
dim2_ = dim2 if dim2 >= 0 else len(input_shape) + dim2 + 1
assert dim1_ != dim2_, (
"dim1 and dim2 cannot be the same dimension."
"But received dim1 = %d, dim2 = %d\n" % (dim1, dim2)
)

__check_input(input, offset, dim1, dim2)
helper = LayerHelper("diag_embed", **locals())

out = helper.create_variable_for_type_inference(dtype=input.dtype)

helper.append_op(
type='diag_embed',
inputs={'Input': [input]},
attrs={'offset': offset, 'dim1': dim1, 'dim2': dim2},
outputs={'Out': [out]},
)
out.stop_gradient = True
return out
return tensor.diag_embed(input, offset, dim1, dim2)


def sequence_mask(x, maxlen=None, dtype='int64', name=None):
Expand Down
2 changes: 2 additions & 0 deletions python/paddle/tensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from .creation import to_tensor # noqa: F401
from .creation import diag # noqa: F401
from .creation import diagflat # noqa: F401
from .creation import diag_embed # noqa: F401
from .creation import eye # noqa: F401
from .creation import linspace # noqa: F401
from .creation import fill_constant # noqa: F401
Expand Down Expand Up @@ -690,6 +691,7 @@
'i1e',
'polygamma',
'polygamma_',
'diag_embed',
'atan2',
'diagflat',
'multinomial',
Expand Down
119 changes: 119 additions & 0 deletions python/paddle/tensor/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,125 @@ def meshgrid(*args, **kwargs):
return out


def diag_embed(input, offset=0, dim1=-2, dim2=-1):
"""
Creates a tensor whose diagonals of certain 2D planes (specified by dim1 and dim2)
are filled by ``input``. By default, a 2D plane formed by the last two dimensions
of the returned tensor will be selected.

The argument ``offset`` determines which diagonal is generated:

- If offset = 0, it is the main diagonal.
- If offset > 0, it is above the main diagonal.
- If offset < 0, it is below the main diagonal.

Args:
input(Tensor|numpy.ndarray): The input tensor. Must be at least 1-dimensional. The input data type should be float32, float64, int32, int64.
offset(int, optional): Which diagonal to consider. Default: 0 (main diagonal).
dim1(int, optional): The first dimension with respect to which to take diagonal. Default: -2.
dim2(int, optional): The second dimension with respect to which to take diagonal. Default: -1.

Returns:
Tensor, the output data type is the same as input data type.

Examples:
.. code-block:: python

>>> import paddle

>>> diag_embed_input = paddle.arange(6)

>>> diag_embed_output1 = paddle.diag_embed(diag_embed_input)
>>> print(diag_embed_output1)
Tensor(shape=[6, 6], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0],
[0, 0, 0, 3, 0, 0],
[0, 0, 0, 0, 4, 0],
[0, 0, 0, 0, 0, 5]])

>>> diag_embed_output2 = paddle.diag_embed(diag_embed_input, offset=-1, dim1=0,dim2=1 )
>>> print(diag_embed_output2)
Tensor(shape=[7, 7], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 0],
[0, 0, 0, 0, 4, 0, 0],
[0, 0, 0, 0, 0, 5, 0]])

>>> diag_embed_input_2dim = paddle.reshape(diag_embed_input,[2,3])
>>> print(diag_embed_input_2dim)
Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
[[0, 1, 2],
[3, 4, 5]])
>>> diag_embed_output3 = paddle.diag_embed(diag_embed_input_2dim,offset= 0, dim1=0, dim2=2 )
>>> print(diag_embed_output3)
Tensor(shape=[3, 2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
[[[0, 0, 0],
[3, 0, 0]],
[[0, 1, 0],
[0, 4, 0]],
[[0, 0, 2],
[0, 0, 5]]])
"""
if not isinstance(input, Variable):
input = assign(input)

if in_dynamic_mode():
return _C_ops.diag_embed(input, offset, dim1, dim2)

inputs = {'Input': [input]}
attrs = {'offset': offset, 'dim1': dim1, 'dim2': dim2}

def __check_input(input, offset, dim1, dim2):
check_dtype(
input.dtype,
'Input',
['int32', 'int64', 'float16', 'float32', 'float64'],
'diag_embed',
)

input_shape = list(input.shape)
assert len(input_shape) >= 1, (
"Input must be at least 1-dimensional, "
"But received Input's dimensional: %s.\n" % len(input_shape)
)

assert np.abs(dim1) <= len(input_shape), (
"Dim1 is out of range (expected to be in range of [%d, %d], but got %d).\n"
% (-(len(input_shape) + 1), len(input_shape), dim1)
)

assert np.abs(dim2) <= len(input_shape), (
"Dim2 is out of range (expected to be in range of [%d, %d], but got %d).\n"
% (-(len(input_shape) + 1), len(input_shape), dim2)
)

dim1_ = dim1 if dim1 >= 0 else len(input_shape) + dim1 + 1
dim2_ = dim2 if dim2 >= 0 else len(input_shape) + dim2 + 1
assert dim1_ != dim2_, (
"dim1 and dim2 cannot be the same dimension."
"But received dim1 = %d, dim2 = %d\n" % (dim1, dim2)
)

__check_input(input, offset, dim1, dim2)
helper = LayerHelper("diag_embed", **locals())

out = helper.create_variable_for_type_inference(dtype=input.dtype)

helper.append_op(
type='diag_embed',
inputs={'Input': [input]},
attrs={'offset': offset, 'dim1': dim1, 'dim2': dim2},
outputs={'Out': [out]},
)
out.stop_gradient = True
return out


def diagflat(x, offset=0, name=None):
"""
If ``x`` is a vector (1-D tensor), a 2-D square tensor with the elements of ``x`` as the diagonal is returned.
Expand Down
Loading