Files
paddlepaddle--paddle/test/legacy_test/test_compat_pad.py
T
2026-07-13 12:40:42 +08:00

255 lines
9.2 KiB
Python

# Copyright (c) 2025 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.
import unittest
import numpy as np
import paddle
import paddle.compat.nn.functional as F
class TestCompatPad(unittest.TestCase):
def test_basic_pad(self):
"""Test basic splitting with integer size"""
gt = np.array(
[
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [0.0, 0.0]],
[[7.0, 8.0], [9.0, 10.0], [11.0, 12.0], [0.0, 0.0]],
[[13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [0.0, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
],
dtype=np.float32,
)
x_shape = (3, 3, 2)
x = (
paddle.arange(
paddle.prod(paddle.Tensor(x_shape)), dtype=paddle.float32
).reshape(x_shape)
+ 1
)
result = F.pad(
input=x, pad=[0, 0, 0, 1, 2, 3], mode='constant', value=0
)
np.testing.assert_allclose(result.numpy(), gt)
def test_constant_fast_pass(self):
gt_res = np.array(
[
[[-1, -1, -1, -1, -1], [-1, 0, 1, -1, -1], [-1, 2, 3, -1, -1]],
[[-1, -1, -1, -1, -1], [-1, 4, 5, -1, -1], [-1, 6, 7, -1, -1]],
[
[-1, -1, -1, -1, -1],
[-1, 8, 9, -1, -1],
[-1, 10, 11, -1, -1],
],
],
dtype=np.int64,
)
def const_pad_dy(x, pad_shape):
return F.pad(input=x, pad=pad_shape, mode='constant', value=-1)
@paddle.jit.to_static(full_graph=True)
def const_pad_st(x, pad_shape):
return F.pad(
input=x,
pad=pad_shape,
mode='constant',
value=paddle.to_tensor(-1),
)
x = paddle.arange(12).reshape(3, 2, 2)
res_dy = const_pad_dy(x, [1, 2, 1])
res_st = const_pad_st(x, [1, 2, 1])
np.testing.assert_array_equal(res_dy.numpy(), gt_res)
np.testing.assert_array_equal(res_st.numpy(), gt_res)
def test_single_dim(self):
gt = np.array([0, 0, 1, 2], dtype=np.float64)
x_shape = 2
x = paddle.arange(2, dtype=paddle.float64) + 1
result = F.pad(x, mode='constant', pad=[2])
np.testing.assert_allclose(result.numpy(), gt)
def test_no_pad(self):
gt = np.array(
[
[
[
[[0.0, 0.0, 1.0], [2.0, 2.0, 3.0], [2.0, 2.0, 3.0]],
[[4.0, 4.0, 5.0], [6.0, 6.0, 7.0], [6.0, 6.0, 7.0]],
],
[
[
[8.0, 8.0, 9.0],
[10.0, 10.0, 11.0],
[10.0, 10.0, 11.0],
],
[
[12.0, 12.0, 13.0],
[14.0, 14.0, 15.0],
[14.0, 14.0, 15.0],
],
],
],
[
[
[
[16.0, 16.0, 17.0],
[18.0, 18.0, 19.0],
[18.0, 18.0, 19.0],
],
[
[20.0, 20.0, 21.0],
[22.0, 22.0, 23.0],
[22.0, 22.0, 23.0],
],
],
[
[
[24.0, 24.0, 25.0],
[26.0, 26.0, 27.0],
[26.0, 26.0, 27.0],
],
[
[28.0, 28.0, 29.0],
[30.0, 30.0, 31.0],
[30.0, 30.0, 31.0],
],
],
],
],
dtype=np.float64,
)
x = paddle.arange(32, dtype=paddle.float64).reshape([2] * 5)
result = F.pad(x, mode='replicate', pad=[1, 0, 0, 1, 0, 0])
np.testing.assert_allclose(result.numpy(), gt)
def test_static_graph_circular(self):
cir_gt = np.array(
[
[
[10.0, 11.0, 8.0, 9.0, 10.0, 11.0, 8.0],
[2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0],
[6.0, 7.0, 4.0, 5.0, 6.0, 7.0, 4.0],
[10.0, 11.0, 8.0, 9.0, 10.0, 11.0, 8.0],
],
[
[22.0, 23.0, 20.0, 21.0, 22.0, 23.0, 20.0],
[14.0, 15.0, 12.0, 13.0, 14.0, 15.0, 12.0],
[18.0, 19.0, 16.0, 17.0, 18.0, 19.0, 16.0],
[22.0, 23.0, 20.0, 21.0, 22.0, 23.0, 20.0],
],
],
dtype=np.float32,
)
paddle.enable_static()
with paddle.static.program_guard(paddle.static.Program()):
input_tensor = paddle.arange(24, dtype=paddle.float32).reshape(
[2, 3, 4]
)
pad = paddle.to_tensor([2, 1, 1], dtype="int32")
result = F.pad(input_tensor, pad=pad, mode='circular')
place = (
paddle.CUDAPlace(0)
if paddle.base.is_compiled_with_cuda()
else paddle.CPUPlace()
)
exe = paddle.static.Executor(place)
cir_res = exe.run(fetch_list=[result])
np.testing.assert_allclose(cir_res[0], cir_gt)
paddle.disable_static()
def test_dyn_graph_reflect(self):
x = paddle.full([10, 10], 2, dtype=paddle.float64)
result = F.pad(x, mode='reflect', pad=(1,))
np.testing.assert_allclose(
result.numpy(), np.full([10, 11], 2, dtype=np.float64)
)
def test_special_cases(self):
# empty padding tensor
x = paddle.randn([10, 7], dtype=paddle.float64)
result = F.pad(x, mode='replicate', pad=paddle.tensor([]))
np.testing.assert_allclose(result.numpy(), x.numpy())
def test_error_handling(self):
dummy_x = paddle.arange(3)
wrong_api_used = (
"paddle.compat.nn.functional.pad() received unexpected keyword arguments 'name', 'x'. "
"\nDid you mean to use paddle.nn.functional.pad() instead?"
)
ndim_no_impl = "Input tensor dimension must be in [1-5] but got {x_dim}"
non_const_ndim_no_impl = "Only 2D, 3D, 4D, 5D padding with non-constant padding are supported for now, got ndim: {x_dim}"
mode_no_impl = "mode should be one of constant, reflect, replicate, circular, but got mirror."
pad_len_invalid1 = "Expect len(pad) <= 6 and not -1, got: {pad_len}"
pad_len_invalid2 = "len(pad) is bounded by input.ndim: expect len(pad) <= {max_dim}, got: {pad_len}"
with self.assertRaises(TypeError) as cm:
tensors = F.pad(
x=dummy_x,
mode='constant',
pad=paddle.to_tensor(2),
name='pad_layer',
)
self.assertEqual(str(cm.exception), wrong_api_used)
with self.assertRaises(AssertionError) as cm:
tensors = F.pad(
paddle.arange(64).reshape([2] * 6),
mode='constant',
pad=paddle.to_tensor(2),
)
self.assertEqual(str(cm.exception), ndim_no_impl.format(x_dim=6))
with self.assertRaises(ValueError) as cm:
tensors = F.pad(paddle.arange(2), mode='circular', pad=[0, 1])
self.assertEqual(
str(cm.exception), non_const_ndim_no_impl.format(x_dim=1)
)
with self.assertRaises(AssertionError) as cm:
tensors = F.pad(paddle.arange(2), mode='mirror', pad=[0, 1])
self.assertEqual(str(cm.exception), mode_no_impl)
with self.assertRaises(ValueError) as cm:
tensors = F.pad(
paddle.ones([2, 3, 4]),
mode='replicate',
pad=[0, 1, 1, 1, 1, 1, 1, 1],
)
self.assertEqual(str(cm.exception), pad_len_invalid1.format(pad_len=8))
with self.assertRaises(ValueError) as cm:
tensors = F.pad(
paddle.ones([2, 3]), mode='replicate', pad=[0, 1, 1, 1, 1]
)
self.assertEqual(
str(cm.exception), pad_len_invalid2.format(max_dim=2, pad_len=5)
)
if __name__ == '__main__':
unittest.main()