diff --git a/paddle/fluid/operators/pad_op.cc b/paddle/fluid/operators/pad_op.cc index 8eccf97ff265a4135c7815381f0cc16b6b47f48f..962feb2ee92629f798d1f79fcf7af2ab38008c23 100644 --- a/paddle/fluid/operators/pad_op.cc +++ b/paddle/fluid/operators/pad_op.cc @@ -54,7 +54,8 @@ class PadOpMaker : public framework::OpProtoAndCheckerMaker { AddAttr("pad_value", "(float, default 0.0) " "The value to fill the padded areas.") - .SetDefault(0.0f); + .SetDefault(0.0f) + .SupportTensor(); AddComment(R"DOC( Pad Operator. diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index 8f9257d124675b678e7fb61b08127c281a384c37..c74e0b0f73a027679f9bcd74f11d88b8127c72b7 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1931,7 +1931,7 @@ backward : p_norm_grad - api : pad - args : (Tensor x, int[] paddings, float pad_value) + args : (Tensor x, int[] paddings, Scalar pad_value) output : Tensor infer_meta : func : PadInferMeta diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index 24793465b53ab6ef06101b1d0f8bf444088fc0e6..0a3326574ee67b55ade403def6d381a80c288dd0 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1706,8 +1706,8 @@ backward : pad3d_double_grad - backward_api : pad_double_grad - forward : pad_grad(Tensor x, Tensor grad_out, int[] paddings, float pad_value) -> Tensor(grad_x) - args : (Tensor grad_x_grad, int[] paddings, float pad_value) + forward : pad_grad(Tensor x, Tensor grad_out, int[] paddings, Scalar pad_value) -> Tensor(grad_x) + args : (Tensor grad_x_grad, int[] paddings, Scalar pad_value) output : Tensor(grad_out_grad) infer_meta : func : PadInferMeta @@ -1715,8 +1715,8 @@ func : pad - backward_api : pad_grad - forward : pad(Tensor x, int[] paddings, float pad_value) -> Tensor(out) - args : (Tensor x, Tensor out_grad, int[] paddings, float pad_value) + forward : pad(Tensor x, int[] paddings, Scalar pad_value) -> Tensor(out) + args : (Tensor x, Tensor out_grad, int[] paddings, Scalar pad_value) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index bab0b84f4752a25f5ba086b6031283cd88e80173..82ebc89c666b5e4742727167ac7ab1134980fbc2 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2121,7 +2121,7 @@ void OverlapAddInferMeta(const MetaTensor& x, void PadInferMeta(const MetaTensor& input, const std::vector& paddings, - float pad_value, + const Scalar& padding_value, MetaTensor* out, MetaConfig config) { auto x_dim = input.dims(); diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index db2d51b5fe1fca75691d0318ebe222762f60f3ec..1d1995db43f64c6beaf758dc3384344251470cdd 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -305,7 +305,7 @@ void OverlapAddInferMeta(const MetaTensor& x, void PadInferMeta(const MetaTensor& input, const std::vector& paddings, - float pad_value, + const Scalar& padding_value, MetaTensor* out, MetaConfig config = MetaConfig()); diff --git a/paddle/phi/kernels/impl/pad_grad_kernel_impl.h b/paddle/phi/kernels/impl/pad_grad_kernel_impl.h index 91f198f9fb681e4fabf7029fcc22343bb81953fd..4939a41c25a69757647bd4f991fcd49063d5cf76 100644 --- a/paddle/phi/kernels/impl/pad_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/pad_grad_kernel_impl.h @@ -13,6 +13,8 @@ // limitations under the License. #pragma once + +#include "paddle/phi/common/scalar.h" #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/kernels/funcs/padding.h" namespace phi { @@ -20,7 +22,7 @@ template void PadGradKernel(const Context& dev_ctx, const DenseTensor& d_out, const std::vector& paddings, - float pad_value, + const Scalar& pad_value, DenseTensor* d_x) { if (d_x == nullptr) { return; diff --git a/paddle/phi/kernels/impl/pad_kernel_impl.h b/paddle/phi/kernels/impl/pad_kernel_impl.h index c4ff32f8b327218b2b42a4a38384b82da880ee5d..7737882c42fd92920985c2be4a35db44c3ee7667 100644 --- a/paddle/phi/kernels/impl/pad_kernel_impl.h +++ b/paddle/phi/kernels/impl/pad_kernel_impl.h @@ -16,6 +16,7 @@ #include #include +#include "paddle/phi/common/scalar.h" #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/kernels/funcs/padding.h" namespace phi { @@ -23,11 +24,11 @@ template void PadKernel(const Context& dev_ctx, const DenseTensor& x, const std::vector& paddings, - float pad_value, + const Scalar& pad_value, DenseTensor* out) { dev_ctx.template Alloc(out); int rank = x.dims().size(); funcs::PaddingFunctor( - rank, dev_ctx, paddings, static_cast(pad_value), x, out); + rank, dev_ctx, paddings, pad_value.to(), x, out); } } // namespace phi diff --git a/paddle/phi/kernels/pad_grad_kernel.h b/paddle/phi/kernels/pad_grad_kernel.h index f39d87e5c0ef6503d772e5f9ee95e307a13eda13..aef30f8f5e21dc09a6e14559475bf9b5100d612e 100644 --- a/paddle/phi/kernels/pad_grad_kernel.h +++ b/paddle/phi/kernels/pad_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once +#include "paddle/phi/common/scalar.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -23,6 +24,6 @@ template void PadGradKernel(const Context& dev_ctx, const DenseTensor& d_out, const std::vector& paddings, - float pad_value, + const Scalar& pad_value, DenseTensor* d_x); } // namespace phi diff --git a/paddle/phi/kernels/pad_kernel.h b/paddle/phi/kernels/pad_kernel.h index 511e8cf73df97ffb250b1106aa98155de33a97d1..f3496edba0ff5f1e75dbe332aad7c0d80f8f6c92 100644 --- a/paddle/phi/kernels/pad_kernel.h +++ b/paddle/phi/kernels/pad_kernel.h @@ -15,6 +15,7 @@ #pragma once +#include "paddle/phi/common/scalar.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -23,6 +24,6 @@ template void PadKernel(const Context& dev_ctx, const DenseTensor& x, const std::vector& paddings, - float pad_value, + const Scalar& pad_value, DenseTensor* out); } // namespace phi diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index ebb50604b7311f492d24e0b3582053c0ffa02096..939767a7a5e914cdc1db04e8f9b9112d105ca50c 100755 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -7062,6 +7062,10 @@ def pad(x, paddings, pad_value=0., name=None): 'complex128' ], "pad") + check_type(pad_value, 'pad_value', (float, int, Variable), 'pad') + if isinstance(pad_value, int): + pad_value = float(pad_value) + helper = LayerHelper('pad', **locals()) dtype = helper.input_dtype(input_param_name='x') out = helper.create_variable_for_type_inference(dtype) @@ -7070,7 +7074,7 @@ def pad(x, paddings, pad_value=0., name=None): outputs={'Out': out}, attrs={ 'paddings': paddings, - 'pad_value': float(pad_value) + 'pad_value': pad_value }) return out diff --git a/python/paddle/fluid/tests/unittests/test_pad_op.py b/python/paddle/fluid/tests/unittests/test_pad_op.py index 15b33bc97006b1d5f5c11c8bd06831b0661882de..7560727c7ac844bbd89e61cc66daa3194bbc342c 100644 --- a/python/paddle/fluid/tests/unittests/test_pad_op.py +++ b/python/paddle/fluid/tests/unittests/test_pad_op.py @@ -14,6 +14,7 @@ from __future__ import print_function +import os import unittest import numpy as np from op_test import OpTest @@ -22,6 +23,8 @@ import paddle.fluid.core as core import paddle.fluid as fluid from paddle.fluid import Program, program_guard +from test_attribute_var import UnittestBase + class TestPadOp(OpTest): @@ -123,5 +126,68 @@ class TestPadOpError(unittest.TestCase): fluid.layers.pad(x=data, paddings=[0, 1]) +class TestPaddingValueTensor(UnittestBase): + + def init_info(self): + self.shapes = [[2, 4]] + self.save_path = os.path.join(self.temp_dir.name, self.path_prefix()) + + def test_static(self): + main_prog = Program() + starup_prog = Program() + with program_guard(main_prog, starup_prog): + fc = paddle.nn.Linear(4, 10) + x = paddle.randn([2, 4]) + x.stop_gradient = False + feat = fc(x) # [2,3,10] + + out = self.call_func(feat) + + sgd = paddle.optimizer.SGD() + sgd.minimize(paddle.mean(out)) + self.assertTrue(self.var_prefix() in str(main_prog)) + + exe = paddle.static.Executor() + exe.run(starup_prog) + res = exe.run(fetch_list=[feat, out]) + gt = np.pad(res[0], [1, 1], 'constant', constant_values=[1., 1.]) + np.testing.assert_allclose(res[1], gt) + paddle.static.save_inference_model(self.save_path, [x], [feat, out], + exe) + # Test for Inference Predictor + infer_outs = self.infer_prog() + gt = np.pad(infer_outs[0], [1, 1], + 'constant', + constant_values=[1., 1.]) + np.testing.assert_allclose(infer_outs[1], gt) + + def path_prefix(self): + return 'padding_value' + + def var_prefix(self): + return "Var[" + + def call_func(self, x): + padding_value = paddle.assign([1.0]) + out = paddle.nn.functional.pad(x, + pad=[1, 1, 1, 1], + value=padding_value, + mode='constant') + return out + + +class TestPaddingValueTensor2(TestPaddingValueTensor): + + def call_func(self, x): + padding_value = paddle.assign([1.0]) + # test for int value + tmp = paddle.fluid.layers.pad(x, paddings=[1, 1, 1, 1], pad_value=1) + out = paddle.fluid.layers.pad(x, + paddings=[1, 1, 1, 1], + pad_value=padding_value) + return out + + if __name__ == '__main__': + paddle.enable_static() unittest.main() diff --git a/python/paddle/nn/functional/common.py b/python/paddle/nn/functional/common.py index 846427782f12ca15b13e43243fcd1bfe50988121..d4d3e9759e0199da8256295826f65660238d8a61 100644 --- a/python/paddle/nn/functional/common.py +++ b/python/paddle/nn/functional/common.py @@ -26,7 +26,7 @@ from ...tensor.manipulation import unsqueeze from ...tensor import clip from ...tensor import sum from ...tensor import sqrt -from ...fluid.data_feeder import check_variable_and_dtype, check_dtype +from ...fluid.data_feeder import check_variable_and_dtype, check_dtype, check_type from ...fluid.framework import _varbase_creator, _in_legacy_dygraph, in_dygraph_mode, _non_static_mode from ...fluid import dygraph_utils @@ -1477,6 +1477,10 @@ def pad(x, pad, mode='constant', value=0, data_format="NCHW", name=None): 'complex128' ], "pad") + check_type(pad_value, 'pad_value', (float, int, Variable), 'pad') + if isinstance(pad_value, int): + pad_value = float(pad_value) + helper = LayerHelper('pad', **locals()) dtype = helper.input_dtype(input_param_name='x') out = helper.create_variable_for_type_inference(dtype) @@ -1485,7 +1489,7 @@ def pad(x, pad, mode='constant', value=0, data_format="NCHW", name=None): outputs={'Out': out}, attrs={ 'paddings': paddings, - 'pad_value': float(pad_value) + 'pad_value': pad_value }) return out