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

【PaddlePaddle Hackathon】6、在 Paddle 中新增 ZeroPad2d #37151

Merged
merged 16 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions python/paddle/fluid/tests/unittests/test_imperative_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ def test_layer_str(self):
'Pad2D(padding=[1, 0, 1, 2], mode=constant, value=0.0, data_format=NCHW)'
)

module = nn.ZeroPad2D(padding=[1, 0, 1, 2])
self.assertEqual(
str(module), 'ZeroPad2D(padding=[1, 0, 1, 2], data_format=NCHW)')

module = nn.Pad3D(padding=[1, 0, 1, 2, 0, 0], mode='constant')
self.assertEqual(
str(module),
Expand Down
135 changes: 135 additions & 0 deletions python/paddle/fluid/tests/unittests/test_zeropad2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import unittest
import numpy as np
from paddle import to_tensor
from paddle.nn.functional import zeropad2d
from paddle.nn import ZeroPad2D


class TestZeroPad2dAPIError(unittest.TestCase):
"""
test paddle.zeropad2d error.
"""

def setUp(self):
"""
unsupport dtypes
"""
self.shape = [4, 3, 224, 224]
self.unsupport_dtypes = ['bool', 'int8']

def test_unsupport_dtypes(self):
"""
test unsupport dtypes.
"""
for dtype in self.unsupport_dtypes:
pad = 2
x = np.random.randint(-255, 255, size=self.shape)
x_tensor = to_tensor(x).astype(dtype)
self.assertRaises(TypeError, zeropad2d, x=x_tensor, padding=pad)


class TestZeroPad2dAPI(unittest.TestCase):
"""
test paddle.zeropad2d
"""

def setUp(self):
"""
support dtypes
"""
self.shape = [4, 3, 224, 224]
self.support_dtypes = ['float32', 'float64', 'int32', 'int64']

def test_support_dtypes(self):
"""
test support types
"""
for dtype in self.support_dtypes:
pad = 2
x = np.random.randint(-255, 255, size=self.shape).astype(dtype)
expect_res = np.pad(x, [[0, 0], [0, 0], [pad, pad], [pad, pad]])

x_tensor = to_tensor(x).astype(dtype)
ret_res = zeropad2d(x_tensor, [pad, pad, pad, pad]).numpy()
self.assertTrue(np.allclose(expect_res, ret_res))

def test_support_pad2(self):
"""
test the type of 'pad' is list.
"""
pad = [1, 2, 3, 4]
x = np.random.randint(-255, 255, size=self.shape)
expect_res = np.pad(
x, [[0, 0], [0, 0], [pad[2], pad[3]], [pad[0], pad[1]]])

x_tensor = to_tensor(x)
ret_res = zeropad2d(x_tensor, pad).numpy()
self.assertTrue(np.allclose(expect_res, ret_res))

def test_support_pad3(self):
"""
test the type of 'pad' is tuple.
"""
pad = (1, 2, 3, 4)
x = np.random.randint(-255, 255, size=self.shape)
expect_res = np.pad(
x, [[0, 0], [0, 0], [pad[2], pad[3]], [pad[0], pad[1]]])

x_tensor = to_tensor(x)
ret_res = zeropad2d(x_tensor, pad).numpy()
self.assertTrue(np.allclose(expect_res, ret_res))

def test_support_pad4(self):
"""
test the type of 'pad' is paddle.Tensor.
"""
pad = [1, 2, 3, 4]
x = np.random.randint(-255, 255, size=self.shape)
expect_res = np.pad(
x, [[0, 0], [0, 0], [pad[2], pad[3]], [pad[0], pad[1]]])

x_tensor = to_tensor(x)
pad_tensor = to_tensor(pad, dtype='int32')
ret_res = zeropad2d(x_tensor, pad_tensor).numpy()
self.assertTrue(np.allclose(expect_res, ret_res))


class TestZeroPad2DLayer(unittest.TestCase):
"""
test nn.ZeroPad2D
"""

def setUp(self):
self.shape = [4, 3, 224, 224]
self.pad = [2, 2, 4, 1]
self.padLayer = ZeroPad2D(padding=self.pad)
gsq7474741 marked this conversation as resolved.
Show resolved Hide resolved
self.x = np.random.randint(-255, 255, size=self.shape)
self.expect_res = np.pad(self.x,
[[0, 0], [0, 0], [self.pad[2], self.pad[3]],
[self.pad[0], self.pad[1]]])

def test_layer(self):
self.assertTrue(
np.allclose(
zeropad2d(to_tensor(self.x), self.pad).numpy(),
self.padLayer(to_tensor(self.x))))


if __name__ == '__main__':
unittest.main()
4 changes: 3 additions & 1 deletion python/paddle/nn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from .layer.activation import Maxout # noqa: F401
from .layer.common import Pad1D # noqa: F401
from .layer.common import Pad2D # noqa: F401
from .layer.common import ZeroPad2D # noqa: F401
from .layer.common import Pad3D # noqa: F401
from .layer.common import CosineSimilarity # noqa: F401
from .layer.common import Embedding # noqa: F401
Expand Down Expand Up @@ -293,5 +294,6 @@ def weight_norm(*args):
'PixelShuffle',
'ELU',
'ReLU6',
'LayerDict'
'LayerDict',
'ZeroPad2D'
]
2 changes: 2 additions & 0 deletions python/paddle/nn/functional/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from .common import alpha_dropout # noqa: F401
from .common import label_smooth # noqa: F401
from .common import pad # noqa: F401
from .common import zeropad2d # noqa: F401
from .common import cosine_similarity # noqa: F401
from .common import unfold # noqa: F401
from .common import interpolate # noqa: F401
Expand Down Expand Up @@ -162,6 +163,7 @@
'label_smooth',
'linear',
'pad',
'zeropad2d',
'unfold',
'interpolate',
'upsample',
Expand Down
40 changes: 40 additions & 0 deletions python/paddle/nn/functional/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,46 @@ def pad(x, pad, mode='constant', value=0, data_format="NCHW", name=None):
return out


def zeropad2d(x, padding, data_format="NCHW", name=None):
"""
Pads the input tensor boundaries with zero according to 'pad'.

Args:
x(Tensor): The input tensor with data type float16/float32/float64/int32/int64.
padding(int | Tensor | List[int] | Tuple[int]): The padding size with data type int.
The input dimension should be 4 and pad has the form (pad_left, pad_right,
pad_top, pad_bottom).
data_format(str): An string from: "NHWC", "NCHW". Specify the data format of
the input data. Default: "NCHW".
name(str, optional): The default value is None. Normally there is no need for user
to set this property.

Returns:Tensor,padded with 0 according to pad and data type is same as input.

Examples:
.. code-block:: python

import paddle
import numpy as np
import paddle.nn.functional as F

x_shape = (1, 1, 2, 3)
x = paddle.arange(np.prod(x_shape), dtype="float32").reshape(x_shape) + 1
y = F.zeropad2d(x, [1, 2, 1, 1])
# [[[[0. 0. 0. 0. 0. 0.]
# [0. 1. 2. 3. 0. 0.]
# [0. 4. 5. 6. 0. 0.]
# [0. 0. 0. 0. 0. 0.]]]]
"""

return pad(x,
gsq7474741 marked this conversation as resolved.
Show resolved Hide resolved
pad=padding,
mode='constant',
value=0,
data_format=data_format,
name=name)


def cosine_similarity(x1, x2, axis=1, eps=1e-8):
"""
Compute cosine similarity between x1 and x2 along axis.
Expand Down
1 change: 1 addition & 0 deletions python/paddle/nn/layer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from .common import Bilinear # noqa: F401
from .common import Pad1D # noqa: F401
from .common import Pad2D # noqa: F401
from .common import ZeroPad2D # noqa: F401
from .common import Pad3D # noqa: F401
from .common import CosineSimilarity # noqa: F401
from .common import Embedding # noqa: F401
Expand Down
66 changes: 66 additions & 0 deletions python/paddle/nn/layer/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,72 @@ def extra_repr(self):
self._pad, self._mode, self._value, self._data_format, name_str)


class ZeroPad2D(Layer):
"""
This interface is used to construct a callable object of the ``ZeroPad2D`` class.
Pads the input tensor boundaries with zero.

Parameters:
padding (Tensor | List[int] | int): The padding size with data type int. If is int, use the
same padding in all dimensions. Else [len(padding)/2] dimensions of input will be padded.
The pad has the form (pad_left, pad_right, pad_top, pad_bottom).
data_format (str): An string from: "NCHW", "NHWC". Specify the data format of the input data.
Default is "NCHW"
name (str, optional) : The default value is None. Normally there is no need for
user to set this property. For more information, please refer to :ref:`api_guide_Name`.

Shape:
- x(Tensor): The input tensor of zeropad2d operator, which is a 4-D tensor.
The data type can be float32, float64.
- output(Tensor): The output tensor of zeropad2d operator, which is a 4-D tensor.
The data type is same as input x.

Examples:
gsq7474741 marked this conversation as resolved.
Show resolved Hide resolved
Examples are as follows.

.. code-block:: python

import paddle
gsq7474741 marked this conversation as resolved.
Show resolved Hide resolved
import paddle.nn as nn
import numpy as np

input_shape = (1, 1, 2, 3)
pad = [1, 0, 1, 2]
data = paddle.arange(np.prod(input_shape), dtype="float32").reshape(input_shape) + 1

my_pad = nn.ZeroPad2D(padding=pad)
result = my_pad(data)

print(result)
# [[[[0. 0. 0. 0.]
# [0. 1. 2. 3.]
# [0. 4. 5. 6.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]]]
"""

def __init__(self, padding, data_format="NCHW", name=None):
super(ZeroPad2D, self).__init__()
self._pad = _npairs(padding, 2)
self._mode = 'constant'
self._value = 0.
self._data_format = data_format
self._name = name

def forward(self, x):
return F.pad(x,
pad=self._pad,
mode=self._mode,
value=self._value,
data_format=self._data_format,
name=self._name)

def extra_repr(self):
name_str = ', name={}'.format(self._name) if self._name else ''
return 'padding={}, data_format={}{}'.format(
self._pad, self._data_format, name_str)


class Pad3D(Layer):
"""
This interface is used to construct a callable object of the ``Pad3D`` class.
Expand Down