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

395 lines
13 KiB
Python

# Copyright (c) 2019 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
from op_test import OpTest, get_places
import paddle
from paddle import base
paddle.enable_static()
class TestFoldOp(OpTest):
"""
This is for test on fold Op
"""
def init_data(self):
self.batch_size = 3
self.input_channels = 3 * 2 * 2
self.length = 12
self.kernel_sizes = [2, 2]
self.strides = [1, 1]
self.paddings = [0, 0, 0, 0]
self.dilations = [1, 1]
self.output_sizes = [4, 5]
input_shape = [self.batch_size, self.input_channels, self.length]
self.x = np.random.rand(*input_shape).astype(self.dtype)
if self.dtype == np.complex64 or self.dtype == np.complex128:
self.x = (
np.random.uniform(-1, 1, input_shape)
+ 1j * np.random.uniform(-1, 1, input_shape)
).astype(self.dtype)
def init_dtype(self):
self.dtype = np.float64
def calc_fold(self):
output_shape = [0] * 4
output_shape[0] = self.batch_size
output_shape[1] = int(
self.input_channels / (self.kernel_sizes[0] * self.kernel_sizes[1])
)
output_shape[2] = self.output_sizes[0]
output_shape[3] = self.output_sizes[1]
dkernel_h = self.dilations[0] * (self.kernel_sizes[0] - 1) + 1
dkernel_w = self.dilations[1] * (self.kernel_sizes[1] - 1) + 1
col_height = (
int(
(
self.output_sizes[0]
+ self.paddings[0]
+ self.paddings[2]
- dkernel_h
)
/ self.strides[0]
)
+ 1
)
col_width = (
int(
(
self.output_sizes[1]
+ self.paddings[1]
+ self.paddings[3]
- dkernel_w
)
/ self.strides[1]
)
+ 1
)
output = np.zeros(output_shape).astype(self.dtype)
# ------------- calculate output ------------- #
for b in range(output_shape[0]):
for c in range(self.input_channels):
w_offset = int(c % self.kernel_sizes[1])
h_offset = int(
(c / self.kernel_sizes[1]) % self.kernel_sizes[0]
)
c_out = int(c / self.kernel_sizes[0] / self.kernel_sizes[1])
for h in range(col_height):
h_out = int(
h * self.strides[0]
- self.paddings[0]
+ h_offset * self.dilations[0]
)
for w in range(col_width):
w_out = int(
w * self.strides[1]
- self.paddings[1]
+ w_offset * self.dilations[1]
)
if (h_out >= 0 and h_out < self.output_sizes[0]) and (
w_out >= 0 and w_out < self.output_sizes[1]
):
output[b, c_out, h_out, w_out] += self.x[
b, c, w + col_width * h
]
self.outputs = output
def set_data(self):
self.init_dtype()
self.init_data()
self.calc_fold()
self.inputs = {'X': OpTest.np_dtype_to_base_dtype(self.x)}
self.attrs = {
'kernel_sizes': self.kernel_sizes,
'paddings': self.paddings,
'dilations': self.dilations,
'strides': self.strides,
'output_sizes': self.output_sizes,
}
self.outputs = {'Y': self.outputs}
def setUp(self):
self.op_type = 'fold'
self.python_api = paddle.nn.functional.fold
self.set_data()
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad(self):
self.check_grad(['X'], 'Y', check_pir=True)
class TestFold_Complex64(TestFoldOp):
def init_dtype(self):
self.dtype = np.complex64
class TestFold_Complex128(TestFoldOp):
def init_dtype(self):
self.dtype = np.complex128
class TestFoldshape(TestFoldOp):
def init_data(self):
self.batch_size = 8
self.input_channels = 3 * 3 * 3
self.length = 6
self.kernel_sizes = [3, 3]
self.strides = [1, 1]
self.paddings = [0, 0, 0, 0]
self.dilations = [1, 1]
self.output_sizes = [4, 5]
input_shape = [self.batch_size, self.input_channels, self.length]
self.x = np.random.rand(*input_shape).astype(np.float64)
class TestFoldshape1d(TestFoldOp):
def init_data(self):
self.batch_size = 8
self.input_channels = 3 * 3 * 3
self.length = 3
self.kernel_sizes = [1, 3]
self.strides = [1, 1]
self.paddings = [0, 0, 0, 0]
self.dilations = [1, 1]
self.output_sizes = [1, 5]
input_shape = [self.batch_size, self.input_channels, self.length]
self.x = np.random.rand(*input_shape).astype(np.float64)
class TestFoldAPI(TestFoldOp):
# This is for test on paddle.nn.Fold
def setUp(self):
self.op_type = 'fold'
self.python_api = paddle.nn.functional.fold
self.set_data()
self.places = get_places()
def test_api(self):
for place in self.places:
with base.dygraph.guard(place):
input = paddle.to_tensor(self.x)
m = paddle.nn.Fold(**self.attrs)
m.eval()
result = m(input)
np.testing.assert_allclose(
result.numpy(), self.outputs['Y'], rtol=1e-05
)
def test_info(self):
str(paddle.nn.Fold(**self.attrs))
class TestFoldAPI_Compatibility(TestFoldOp):
# This is for test on paddle.nn.Fold
def set_data(self):
self.init_dtype()
self.init_data()
self.calc_fold()
self.inputs = {'X': OpTest.np_dtype_to_base_dtype(self.x)}
self.outputs = {'Y': self.outputs}
def setUp(self):
self.op_type = 'fold'
self.python_api = paddle.nn.functional.fold
self.set_data()
if isinstance(self.paddings, list):
self.paddings = tuple(self.paddings)
self.places = get_places()
def test_check_output(self):
# self.attrs in OpTest needs original parameters
self.attrs = {
'kernel_sizes': self.kernel_sizes,
'paddings': self.paddings,
'dilations': self.dilations,
'strides': self.strides,
'output_sizes': self.output_sizes,
}
self.check_output(check_pir=True)
def test_check_grad(self):
self.attrs = {
'kernel_sizes': self.kernel_sizes,
'paddings': self.paddings,
'dilations': self.dilations,
'strides': self.strides,
'output_sizes': self.output_sizes,
}
self.check_grad(['X'], 'Y', check_pir=True)
def test_layer_api(self):
# self.attrs in nn.Fold can be alias
self.attrs = {
'kernel_size': self.kernel_sizes,
'padding': self.paddings,
'dilation': self.dilations,
'stride': self.strides,
'output_size': self.output_sizes,
}
for place in self.places:
with base.dygraph.guard(place):
input = paddle.to_tensor(self.x)
m = paddle.nn.Fold(**self.attrs)
self.assertEqual(m.kernel_size, self.kernel_sizes)
self.assertEqual(m.padding, self.paddings)
self.assertEqual(m.dilation, self.dilations)
self.assertEqual(m.stride, self.strides)
self.assertEqual(m.output_size, self.output_sizes)
m.kernel_size = self.kernel_sizes
m.padding = self.paddings
m.dilation = self.dilations
m.stride = self.strides
m.output_size = self.output_sizes
m.eval()
result = m(input)
np.testing.assert_allclose(
result.numpy(), self.outputs['Y'], rtol=1e-05
)
def test_function_api(self):
# self.attrs in nn.Fold can be alias
self.fold_input = {
'kernel_size': self.kernel_sizes,
'padding': self.paddings,
'dilation': self.dilations,
'stride': self.strides,
'output_size': self.output_sizes,
}
for place in self.places:
with base.dygraph.guard(place):
input = paddle.to_tensor(self.x)
result = paddle.nn.functional.fold(
input=input, **self.fold_input
)
np.testing.assert_allclose(
result.numpy(), self.outputs['Y'], rtol=1e-05
)
def test_info(self):
self.attrs = {
'kernel_size': self.kernel_sizes,
'padding': self.paddings,
'dilation': self.dilations,
'stride': self.strides,
'output_size': self.output_sizes,
}
str(paddle.nn.Fold(**self.attrs))
class TestFoldOpError(unittest.TestCase):
def test_errors(self):
from paddle.base.framework import Program, program_guard
from paddle.nn.functional import fold
with program_guard(Program(), Program()):
def test_input_shape():
# input_shape must be 3-D
x = paddle.randn(shape=[2, 3, 6, 7], dtype="float32")
out = fold(x, output_sizes=[2, 3], kernel_sizes=[2, 2])
def test_kernel_shape():
# kernel_size must be 2
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(x, output_sizes=[2, 3], kernel_sizes=[2, 2, 3])
def test_padding_shape():
# padding_size must be 2 or 4
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(
x,
output_sizes=[2, 3],
kernel_sizes=[2, 2],
paddings=[2, 2, 3],
)
def test_dilations_shape():
# dilations_size must be 2
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(
x,
output_sizes=[2, 3],
kernel_sizes=[2, 2],
dilations=[2, 2, 3],
)
def test_strides_shape():
# strides_size must be 2
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(
x,
output_sizes=[2, 3],
kernel_sizes=[2, 2],
strides=[2, 2, 3],
)
def test_output_size():
# im_h * im_w must be L
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(
x, output_sizes=[6, 6], kernel_sizes=[2, 2], strides=[1, 1]
)
def test_output_size_2():
# out_size must GT 1
x = paddle.randn(shape=[2, 6, 6], dtype="float32")
out = fold(
x,
output_sizes=[0.1, 0.2],
kernel_sizes=[2, 2],
strides=[1, 1],
)
def test_block_h_w():
# test_block_h_w GT 0
x = paddle.randn(shape=[2, 1, 1], dtype="float32")
out = fold(
x, output_sizes=[1, 1], kernel_sizes=[2, 2], strides=1
)
def test_GT_0():
x = paddle.randn(shape=[2, 1, 1], dtype="float32")
out = fold(
x,
output_sizes=[0, 0],
kernel_sizes=[0, 0],
dilations=0,
paddings=[0, 0],
strides=0,
)
self.assertRaises(AssertionError, test_input_shape)
self.assertRaises(AssertionError, test_kernel_shape)
self.assertRaises(ValueError, test_padding_shape)
self.assertRaises(AssertionError, test_dilations_shape)
self.assertRaises(AssertionError, test_strides_shape)
self.assertRaises(ValueError, test_output_size)
self.assertRaises(TypeError, test_output_size_2)
self.assertRaises(ValueError, test_block_h_w)
self.assertRaises(ValueError, test_GT_0)
if __name__ == '__main__':
unittest.main()