Files
2026-07-13 12:40:42 +08:00

1875 lines
58 KiB
Python

# Copyright (c) 2026 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 math
import unittest
import numpy as np
from op_test import OpTest
import paddle
from paddle.nn import functional as F
def max_pool1d_dilation_forward_naive(
x, ksize, strides, paddings, dilations, ceil_mode=False
):
"""
Compute 1D dilated max pooling result using numpy.
For dilated pooling, the effective kernel size is:
effective_ksize = dilation * (ksize - 1) + 1
Output size formula:
output_size = (input_size + 2*padding - dilation*(ksize-1) - 1) / stride + 1
"""
N, C, L = x.shape
dilation = dilations
# Compute effective kernel size
effective_ksize = dilation * (ksize - 1) + 1
# Compute output length
if ceil_mode:
L_out = math.ceil((L + 2 * paddings - effective_ksize) / strides) + 1
else:
L_out = (L + 2 * paddings - effective_ksize) // strides + 1
out = np.zeros((N, C, L_out), dtype=x.dtype)
mask = np.zeros((N, C, L_out), dtype=np.int32)
# Pad input
x_padded = np.pad(
x,
((0, 0), (0, 0), (paddings, paddings)),
mode='constant',
constant_values=float('-inf'),
)
for i in range(L_out):
start = i * strides
# Collect elements at dilated positions
for n in range(N):
for c in range(C):
max_val = float('-inf')
max_idx = 0
for k in range(ksize):
pos = start + k * dilation
if pos < x_padded.shape[2]:
val = x_padded[n, c, pos]
if val > max_val:
max_val = val
# Original index in padded tensor
max_idx = pos - paddings + k * dilation
out[n, c, i] = max_val
mask[n, c, i] = max_idx
return out, mask
def max_pool2d_dilation_forward_naive(
x, ksize, strides, paddings, dilations, ceil_mode=False
):
"""
Compute 2D dilated max pooling result using numpy.
For dilated pooling, the effective kernel size is:
effective_ksize[i] = dilation[i] * (ksize[i] - 1) + 1
Output size formula:
output_size = (input_size + 2*padding - dilation*(ksize-1) - 1) / stride + 1
"""
N, C, H, W = x.shape
kh, kw = ksize
sh, sw = strides
ph, pw = paddings
dh, dw = dilations
# Compute effective kernel size
effective_kh = dh * (kh - 1) + 1
effective_kw = dw * (kw - 1) + 1
# Compute output size
if ceil_mode:
H_out = math.ceil((H + 2 * ph - effective_kh) / sh) + 1
W_out = math.ceil((W + 2 * pw - effective_kw) / sw) + 1
else:
H_out = (H + 2 * ph - effective_kh) // sh + 1
W_out = (W + 2 * pw - effective_kw) // sw + 1
out = np.zeros((N, C, H_out, W_out), dtype=x.dtype)
mask = np.zeros((N, C, H_out, W_out), dtype=np.int32)
# Pad input
x_padded = np.pad(
x,
((0, 0), (0, 0), (ph, ph), (pw, pw)),
mode='constant',
constant_values=float('-inf'),
)
for i in range(H_out):
for j in range(W_out):
h_start = i * sh
w_start = j * sw
for n in range(N):
for c in range(C):
max_val = float('-inf')
max_idx = 0
for kh_idx in range(kh):
for kw_idx in range(kw):
h_pos = h_start + kh_idx * dh
w_pos = w_start + kw_idx * dw
if (
h_pos < x_padded.shape[2]
and w_pos < x_padded.shape[3]
):
val = x_padded[n, c, h_pos, w_pos]
if val > max_val:
max_val = val
orig_h = h_pos - ph
orig_w = w_pos - pw
max_idx = orig_h * W + orig_w
out[n, c, i, j] = max_val
mask[n, c, i, j] = max_idx
return out, mask
def max_pool3d_dilation_forward_naive(
x, ksize, strides, paddings, dilations, ceil_mode=False
):
"""
Compute 3D dilated max pooling result using numpy.
"""
N, C, D, H, W = x.shape
kd, kh, kw = ksize
sd, sh, sw = strides
pd, ph, pw = paddings
dd, dh, dw = dilations
# Compute effective kernel size
effective_kd = dd * (kd - 1) + 1
effective_kh = dh * (kh - 1) + 1
effective_kw = dw * (kw - 1) + 1
# Compute output size
if ceil_mode:
D_out = math.ceil((D + 2 * pd - effective_kd) / sd) + 1
H_out = math.ceil((H + 2 * ph - effective_kh) / sh) + 1
W_out = math.ceil((W + 2 * pw - effective_kw) / sw) + 1
else:
D_out = (D + 2 * pd - effective_kd) // sd + 1
H_out = (H + 2 * ph - effective_kh) // sh + 1
W_out = (W + 2 * pw - effective_kw) // sw + 1
out = np.zeros((N, C, D_out, H_out, W_out), dtype=x.dtype)
mask = np.zeros((N, C, D_out, H_out, W_out), dtype=np.int32)
# Pad input
x_padded = np.pad(
x,
((0, 0), (0, 0), (pd, pd), (ph, ph), (pw, pw)),
mode='constant',
constant_values=float('-inf'),
)
for d_idx in range(D_out):
for i in range(H_out):
for j in range(W_out):
d_start = d_idx * sd
h_start = i * sh
w_start = j * sw
for n in range(N):
for c in range(C):
max_val = float('-inf')
max_idx = 0
for kd_idx in range(kd):
for kh_idx in range(kh):
for kw_idx in range(kw):
d_pos = d_start + kd_idx * dd
h_pos = h_start + kh_idx * dh
w_pos = w_start + kw_idx * dw
if (
d_pos < x_padded.shape[2]
and h_pos < x_padded.shape[3]
and w_pos < x_padded.shape[4]
):
val = x_padded[
n, c, d_pos, h_pos, w_pos
]
if val > max_val:
max_val = val
orig_d = d_pos - pd
orig_h = h_pos - ph
orig_w = w_pos - pw
max_idx = (
orig_d * H * W
+ orig_h * W
+ orig_w
)
out[n, c, d_idx, i, j] = max_val
mask[n, c, d_idx, i, j] = max_idx
return out, mask
# ===================== Functional API Tests =====================
class TestMaxPool1DDilation(unittest.TestCase):
"""Test MaxPool1D with dilation parameter."""
def setUp(self):
np.random.seed(123)
def test_max_pool1d_dilation_functional(self):
"""Test F.max_pool1d with dilation parameter."""
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool1d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
# Verify output shape
# effective_ksize = 2 * (3 - 1) + 1 = 5
# L_out = (32 + 2*1 - 5) / 2 + 1 = 15
expected_shape = [2, 3, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool1d_dilation_using_paddle_pos_args(self):
"""Test F.max_pool1d using paddle positional arguments."""
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool1d(
input_tensor,
3,
2,
1,
True, # return_mask
False, # ceil_mode
2,
)
expected_shape = [2, 3, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool1d_dilation_using_torch_pos_args(self):
"""Test F.max_pool1d using torch-like positional arguments."""
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool1d(
input_tensor,
3,
2,
1,
2,
False, # ceil_mode
True, # return_indices
)
expected_shape = [2, 3, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool1d_dilation_layer(self):
"""Test nn.MaxPool1D with dilation parameter."""
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
pool_layer = paddle.nn.MaxPool1D(
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
result, mask = pool_layer(input_tensor)
expected_shape = [2, 3, 15]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool1d_dilation_default(self):
"""Test that dilation=1 gives the same result as without dilation."""
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# With dilation=1 (default behavior)
result_dilation1, _ = F.max_pool1d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=1,
)
# Without specifying dilation (should default to 1)
result_no_dilation = F.max_pool1d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=False,
)
np.testing.assert_allclose(
result_dilation1.numpy(),
result_no_dilation.numpy(),
rtol=1e-05,
)
def test_max_pool1d_dilation_numerical_correctness(self):
"""Test the numerical correctness of 1D dilated max pooling."""
# Use small tensor for easy verification
input_np = np.random.random([1, 2, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
ksize = 3
stride = 2
padding = 1
dilation = 2
result, mask = F.max_pool1d(
input_tensor,
kernel_size=ksize,
stride=stride,
padding=padding,
return_mask=True,
dilation=dilation,
)
# Compare with numpy reference implementation
expected_result, expected_mask = max_pool1d_dilation_forward_naive(
input_np,
ksize=ksize,
strides=stride,
paddings=padding,
dilations=dilation,
)
np.testing.assert_allclose(
result.numpy(),
expected_result,
rtol=1e-05,
err_msg="MaxPool1D dilation output mismatch",
)
def test_max_pool1d_dilation_various_params(self):
"""Test 1D dilated max pooling with various parameter combinations."""
test_configs = [
{"ksize": 2, "stride": 1, "padding": 0, "dilation": 2},
{"ksize": 3, "stride": 2, "padding": 1, "dilation": 3},
{"ksize": 4, "stride": 2, "padding": 2, "dilation": 2},
]
for config in test_configs:
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = F.max_pool1d(
input_tensor,
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=config["ksize"],
strides=config["stride"],
paddings=config["padding"],
dilations=config["dilation"],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool1D mismatch with config: {config}",
)
class TestMaxPool2DDilation(unittest.TestCase):
"""Test MaxPool2D with dilation parameter."""
def setUp(self):
np.random.seed(123)
def test_max_pool2d_dilation_functional(self):
"""Test F.max_pool2d with dilation parameter."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
# Verify output shape
# effective_ksize = 2 * (3 - 1) + 1 = 5
# H_out = (32 + 2*1 - 5) / 2 + 1 = 15
expected_shape = [2, 3, 15, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool2d_dilation_using_paddle_pos_args(self):
"""Test F.max_pool2d using paddle positional arguments."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool2d(
input_tensor,
3,
2,
1,
True, # return_mask
False, # ceil_mode
2,
)
expected_shape = [2, 3, 15, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool2d_dilation_using_torch_pos_args(self):
"""Test F.max_pool2d using torch-like positional arguments."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool2d(
input_tensor,
3,
2,
1,
2,
False, # ceil_mode
True, # return_indices
)
expected_shape = [2, 3, 15, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_max_pool2d_dilation_layer(self):
"""Test nn.MaxPool2D with dilation parameter."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
pool_layer = paddle.nn.MaxPool2D(
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
result, mask = pool_layer(input_tensor)
expected_shape = [2, 3, 15, 15]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool2d_dilation_asymmetric(self):
"""Test with different dilation values for height and width."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# dilation = (2, 3)
result, mask = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=(2, 3),
)
# effective_kh = 2 * (3 - 1) + 1 = 5
# effective_kw = 3 * (3 - 1) + 1 = 7
# H_out = (32 + 2 - 5) / 2 + 1 = 15
# W_out = (32 + 2 - 7) / 2 + 1 = 14
expected_shape = [2, 3, 15, 14]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool2d_dilation_default(self):
"""Test that dilation=1 gives the same result as without dilation."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# With dilation=1
result_dilation1, _ = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=1,
)
# Without specifying dilation
result_no_dilation = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=False,
)
np.testing.assert_allclose(
result_dilation1.numpy(),
result_no_dilation.numpy(),
rtol=1e-05,
)
def test_max_pool2d_dilation_correctness(self):
"""Test the correctness of dilated max pooling result."""
input_np = np.random.random([1, 1, 8, 8]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = F.max_pool2d(
input_tensor,
kernel_size=2,
stride=1,
padding=0,
return_mask=True,
dilation=2,
)
# With dilation=2 and kernel=2x2, the effective kernel covers:
# positions (0,0), (0,2), (2,0), (2,2) in first window
# Output size: (8 + 0 - 2*(2-1) - 1) / 1 + 1 = (8 - 3) / 1 + 1 = 6
expected_shape = [1, 1, 6, 6]
self.assertEqual(list(result.shape), expected_shape)
# Compare with numpy reference
expected_result, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[2, 2],
strides=[1, 1],
paddings=[0, 0],
dilations=[2, 2],
)
np.testing.assert_allclose(result.numpy(), expected_result, rtol=1e-05)
def test_max_pool2d_dilation_various_params(self):
"""Test 2D dilated max pooling with various parameter combinations."""
test_configs = [
{
"ksize": [2, 2],
"stride": [1, 1],
"padding": [0, 0],
"dilation": [2, 2],
},
{
"ksize": [3, 3],
"stride": [2, 2],
"padding": [1, 1],
"dilation": [2, 3],
},
{
"ksize": [2, 3],
"stride": [1, 2],
"padding": [1, 1],
"dilation": [3, 2],
},
]
for config in test_configs:
input_np = np.random.random([2, 3, 24, 24]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = F.max_pool2d(
input_tensor,
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=config["ksize"],
strides=config["stride"],
paddings=config["padding"],
dilations=config["dilation"],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool2D mismatch with config: {config}",
)
class TestMaxPool3DDilation(unittest.TestCase):
"""Test MaxPool3D with dilation parameter."""
def setUp(self):
np.random.seed(123)
def test_max_pool3d_dilation_functional(self):
"""Test F.max_pool3d with dilation parameter."""
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool3d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
# effective_ksize = 2 * (3 - 1) + 1 = 5
# D_out = (8 + 2 - 5) / 2 + 1 = 3
# H_out = (16 + 2 - 5) / 2 + 1 = 7
expected_shape = [2, 3, 3, 7, 7]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool3d_dilation_using_paddle_pos_args(self):
"""Test F.max_pool3d using paddle positional arguments."""
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool3d(
input_tensor,
3,
2,
1,
True, # return_mask
False, # ceil_mode
2,
)
expected_shape = [2, 3, 3, 7, 7]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool3d_dilation_using_torch_pos_args(self):
"""Test F.max_pool3d using torch-like positional arguments."""
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# Test with dilation=2
result, mask = F.max_pool3d(
input_tensor,
3,
2,
1,
2,
False, # ceil_mode
True, # return_indices
)
expected_shape = [2, 3, 3, 7, 7]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool3d_dilation_layer(self):
"""Test nn.MaxPool3D with dilation parameter."""
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
pool_layer = paddle.nn.MaxPool3D(
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
result, mask = pool_layer(input_tensor)
expected_shape = [2, 3, 3, 7, 7]
self.assertEqual(list(result.shape), expected_shape)
def test_max_pool3d_dilation_default(self):
"""Test that dilation=1 gives the same result as without dilation."""
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# With dilation=1
result_dilation1, _ = F.max_pool3d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=1,
)
# Without specifying dilation
result_no_dilation = F.max_pool3d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=False,
)
np.testing.assert_allclose(
result_dilation1.numpy(),
result_no_dilation.numpy(),
rtol=1e-05,
)
def test_max_pool3d_dilation_numerical_correctness(self):
"""Test the numerical correctness of 3D dilated max pooling."""
# Use smaller tensor for 3D to reduce computation
input_np = np.random.random([1, 2, 8, 8, 8]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
ksize = [2, 2, 2]
stride = [1, 1, 1]
padding = [0, 0, 0]
dilation = [2, 2, 2]
result, mask = F.max_pool3d(
input_tensor,
kernel_size=ksize,
stride=stride,
padding=padding,
return_mask=True,
dilation=dilation,
)
# Compare with numpy reference
expected_result, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=ksize,
strides=stride,
paddings=padding,
dilations=dilation,
)
np.testing.assert_allclose(
result.numpy(),
expected_result,
rtol=1e-05,
err_msg="MaxPool3D dilation output mismatch",
)
def test_max_pool3d_dilation_various_params(self):
"""Test 3D dilated max pooling with various parameter combinations."""
test_configs = [
{
"ksize": [2, 2, 2],
"stride": [1, 1, 1],
"padding": [0, 0, 0],
"dilation": [2, 2, 2],
},
{
"ksize": [2, 3, 3],
"stride": [2, 2, 2],
"padding": [1, 1, 1],
"dilation": [2, 2, 3],
},
]
for config in test_configs:
input_np = np.random.random([1, 2, 10, 12, 12]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = F.max_pool3d(
input_tensor,
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=config["ksize"],
strides=config["stride"],
paddings=config["padding"],
dilations=config["dilation"],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool3D mismatch with config: {config}",
)
class TestMaxPoolDilationValidation(unittest.TestCase):
"""Test parameter validation for dilation in MaxPool operations."""
def test_negative_dilation(self):
"""Test that negative dilation raises an error."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
with self.assertRaises((ValueError, RuntimeError)):
F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=-1,
)
def test_dilation_one_no_return_mask(self):
"""Test that dilation=1 works without return_mask."""
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
# This should work fine
result = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=False,
dilation=1,
)
expected_shape = [2, 3, 16, 16]
self.assertEqual(list(result.shape), expected_shape)
def test_dilation_channel_last_2d(self):
"""Test that dilation with NHWC format raises error."""
input_np = np.random.uniform(-1, 1, [2, 3, 32, 32]).astype(np.float32)
input_pd = paddle.to_tensor(input_np)
with self.assertRaises(ValueError):
F.max_pool2d(
input_pd,
kernel_size=2,
stride=2,
padding=0,
return_mask=False,
ceil_mode=False,
dilation=2,
data_format='NHWC',
)
def test_dilation_channel_last_3d(self):
"""Test that dilation with NDHWC format raises error."""
input_np = np.random.uniform(-1, 1, [2, 3, 32, 32, 32]).astype(
np.float32
)
input_pd = paddle.to_tensor(input_np)
with self.assertRaises(ValueError):
F.max_pool3d(
input_pd,
kernel_size=2,
stride=2,
padding=1,
return_mask=False,
dilation=2,
data_format='NDHWC',
)
class TestMaxPoolDilationGradient(unittest.TestCase):
"""Test gradient computation for dilated max pooling."""
def test_max_pool2d_dilation_gradient(self):
"""Test that gradient can be computed for dilated max pooling."""
input_np = np.random.random([2, 3, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
input_tensor.stop_gradient = False
# Forward with dilation
result, mask = F.max_pool2d(
input_tensor,
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=2,
)
# Backward
loss = paddle.mean(result)
loss.backward()
# Check gradient exists and has correct shape
self.assertIsNotNone(input_tensor.grad)
self.assertEqual(list(input_tensor.grad.shape), [2, 3, 16, 16])
def test_max_pool3d_dilation_gradient(self):
"""Test that gradient can be computed for 3D dilated max pooling."""
input_np = np.random.random([2, 3, 8, 8, 8]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
input_tensor.stop_gradient = False
# Forward with dilation
result, mask = F.max_pool3d(
input_tensor,
kernel_size=2,
stride=2,
padding=0,
return_mask=True,
dilation=2,
)
# Backward
loss = paddle.mean(result)
loss.backward()
# Check gradient exists and has correct shape
self.assertIsNotNone(input_tensor.grad)
self.assertEqual(list(input_tensor.grad.shape), [2, 3, 8, 8, 8])
class TestMaxPoolExtraRepr(unittest.TestCase):
"""Test extra_repr includes dilation for MaxPool layers."""
def test_maxpool1d_extra_repr(self):
"""Test MaxPool1D extra_repr includes dilation."""
pool = paddle.nn.MaxPool1D(
kernel_size=3, stride=2, padding=1, dilation=2
)
repr_str = pool.extra_repr()
self.assertIn('dilation', repr_str)
self.assertIn('2', repr_str)
def test_maxpool2d_extra_repr(self):
"""Test MaxPool2D extra_repr includes dilation."""
pool = paddle.nn.MaxPool2D(
kernel_size=3, stride=2, padding=1, dilation=2
)
repr_str = pool.extra_repr()
self.assertIn('dilation', repr_str)
self.assertIn('2', repr_str)
def test_maxpool3d_extra_repr(self):
"""Test MaxPool3D extra_repr includes dilation."""
pool = paddle.nn.MaxPool3D(
kernel_size=3, stride=2, padding=1, dilation=2
)
repr_str = pool.extra_repr()
self.assertIn('dilation', repr_str)
self.assertIn('2', repr_str)
class TestMaxPool1DLayerDilation(unittest.TestCase):
"""Test paddle.nn.MaxPool1D layer with dilation parameter."""
def setUp(self):
np.random.seed(42)
def test_maxpool1d_layer_dilation_basic(self):
"""Test MaxPool1D layer with dilation parameter."""
pool = paddle.nn.MaxPool1D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
# effective_ksize = 2 * (3 - 1) + 1 = 5
# L_out = (32 + 2*1 - 5) / 2 + 1 = 15
expected_shape = [2, 3, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_maxpool1d_layer_dilation_numerical_correctness(self):
"""Test MaxPool1D layer dilation numerical correctness."""
input_np = np.random.random([1, 2, 16]).astype("float32")
pool = paddle.nn.MaxPool1D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=3,
strides=2,
paddings=1,
dilations=2,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool1D layer dilation output mismatch",
)
def test_maxpool1d_layer_dilation_various_values(self):
"""Test MaxPool1D layer with various dilation values."""
test_configs = [
{"ksize": 2, "stride": 1, "padding": 0, "dilation": 2},
{"ksize": 3, "stride": 2, "padding": 1, "dilation": 3},
{"ksize": 2, "stride": 1, "padding": 1, "dilation": 4},
]
for config in test_configs:
pool = paddle.nn.MaxPool1D(
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=config["ksize"],
strides=config["stride"],
paddings=config["padding"],
dilations=config["dilation"],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool1D layer mismatch with config: {config}",
)
def test_maxpool1d_layer_dilation_gradient(self):
"""Test MaxPool1D layer gradient with dilation."""
pool = paddle.nn.MaxPool1D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
input_tensor.stop_gradient = False
result, _ = pool(input_tensor)
loss = paddle.mean(result)
loss.backward()
self.assertIsNotNone(input_tensor.grad)
self.assertEqual(list(input_tensor.grad.shape), [2, 3, 16])
def test_maxpool1d_layer_dilation_with_ceil_mode(self):
"""Test MaxPool1D layer with dilation and ceil_mode."""
pool = paddle.nn.MaxPool1D(
kernel_size=3,
stride=2,
padding=0,
return_mask=True,
ceil_mode=True,
dilation=2,
)
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=3,
strides=2,
paddings=0,
dilations=2,
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool1D layer dilation with ceil_mode mismatch",
)
def test_maxpool1d_layer_dilation_using_paddle_pos_args(self):
"""Test MaxPool1D layer using paddle positional arguments."""
pool = paddle.nn.MaxPool1D(
3,
2,
0,
True, # return_mask
True, # ceil_mode
2,
)
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=3,
strides=2,
paddings=0,
dilations=2,
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool1D layer using torch positional arguments mismatch",
)
def test_maxpool1d_layer_dilation_using_torch_pos_args(self):
"""Test MaxPool1D layer using torch-like positional arguments."""
pool = paddle.nn.MaxPool1D(
3,
2,
0,
2,
True, # return_indices
True, # ceil_mode
)
input_np = np.random.random([2, 3, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool1d_dilation_forward_naive(
input_np,
ksize=3,
strides=2,
paddings=0,
dilations=2,
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool1D layer using torch positional arguments mismatch",
)
class TestMaxPool2DLayerDilation(unittest.TestCase):
"""Test paddle.nn.MaxPool2D layer with dilation parameter."""
def setUp(self):
np.random.seed(42)
def test_maxpool2d_layer_dilation_basic(self):
"""Test MaxPool2D layer with dilation parameter."""
pool = paddle.nn.MaxPool2D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
# effective_ksize = 2 * (3 - 1) + 1 = 5
# H_out = (32 + 2*1 - 5) / 2 + 1 = 15
expected_shape = [2, 3, 15, 15]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_maxpool2d_layer_dilation_numerical_correctness(self):
"""Test MaxPool2D layer dilation numerical correctness."""
input_np = np.random.random([1, 2, 16, 16]).astype("float32")
pool = paddle.nn.MaxPool2D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[3, 3],
strides=[2, 2],
paddings=[1, 1],
dilations=[2, 2],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool2D layer dilation output mismatch",
)
def test_maxpool2d_layer_dilation_asymmetric(self):
"""Test MaxPool2D layer with asymmetric dilation values."""
pool = paddle.nn.MaxPool2D(
kernel_size=3,
stride=2,
padding=1,
return_mask=True,
dilation=(2, 3),
)
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
# effective_kh = 2 * (3 - 1) + 1 = 5
# effective_kw = 3 * (3 - 1) + 1 = 7
expected_shape = [2, 3, 15, 14]
self.assertEqual(list(result.shape), expected_shape)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[3, 3],
strides=[2, 2],
paddings=[1, 1],
dilations=[2, 3],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool2D layer asymmetric dilation mismatch",
)
def test_maxpool2d_layer_dilation_various_values(self):
"""Test MaxPool2D layer with various dilation values."""
test_configs = [
{"ksize": 2, "stride": 1, "padding": 0, "dilation": (2, 2)},
{"ksize": 3, "stride": 2, "padding": 1, "dilation": (2, 3)},
{"ksize": 2, "stride": 1, "padding": 1, "dilation": (3, 2)},
]
for config in test_configs:
pool = paddle.nn.MaxPool2D(
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
input_np = np.random.random([2, 3, 24, 24]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
ksize = [config["ksize"], config["ksize"]]
stride = [config["stride"], config["stride"]]
padding = [config["padding"], config["padding"]]
dilation = list(config["dilation"])
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=ksize,
strides=stride,
paddings=padding,
dilations=dilation,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool2D layer mismatch with config: {config}",
)
def test_maxpool2d_layer_dilation_gradient(self):
"""Test MaxPool2D layer gradient with dilation."""
pool = paddle.nn.MaxPool2D(
kernel_size=3, stride=2, padding=1, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
input_tensor.stop_gradient = False
result, _ = pool(input_tensor)
loss = paddle.mean(result)
loss.backward()
self.assertIsNotNone(input_tensor.grad)
self.assertEqual(list(input_tensor.grad.shape), [2, 3, 16, 16])
def test_maxpool2d_layer_dilation_with_ceil_mode(self):
"""Test MaxPool2D layer with dilation and ceil_mode."""
pool = paddle.nn.MaxPool2D(
kernel_size=3,
stride=2,
padding=0,
return_mask=True,
ceil_mode=True,
dilation=2,
)
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[3, 3],
strides=[2, 2],
paddings=[0, 0],
dilations=[2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool2D layer dilation with ceil_mode mismatch",
)
def test_maxpool2d_layer_dilation_using_paddle_pos_args(self):
"""Test MaxPool2D layer using paddle positional arguments."""
pool = paddle.nn.MaxPool2D(
3,
2,
0,
True, # return_mask
True, # ceil_mode
2,
)
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[3, 3],
strides=[2, 2],
paddings=[0, 0],
dilations=[2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool2D layer using paddle positional arguments mismatch",
)
def test_maxpool2d_layer_dilation_using_torch_pos_args(self):
"""Test MaxPool2D layer using torch-like positional arguments."""
pool = paddle.nn.MaxPool2D(
3,
2,
0,
2,
True, # return_indices
True, # ceil_mode
)
input_np = np.random.random([2, 3, 32, 32]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool2d_dilation_forward_naive(
input_np,
ksize=[3, 3],
strides=[2, 2],
paddings=[0, 0],
dilations=[2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool2D layer using torch-like positional arguments mismatch",
)
class TestMaxPool3DLayerDilation(unittest.TestCase):
"""Test paddle.nn.MaxPool3D layer with dilation parameter."""
def setUp(self):
np.random.seed(42)
def test_maxpool3d_layer_dilation_basic(self):
"""Test MaxPool3D layer with dilation parameter."""
pool = paddle.nn.MaxPool3D(
kernel_size=2, stride=2, padding=0, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 8, 16, 16]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
# effective_ksize = 2 * (2 - 1) + 1 = 3
# D_out = (8 - 3) / 2 + 1 = 3
# H_out = (16 - 3) / 2 + 1 = 7
expected_shape = [2, 3, 3, 7, 7]
self.assertEqual(list(result.shape), expected_shape)
self.assertEqual(list(mask.shape), expected_shape)
def test_maxpool3d_layer_dilation_numerical_correctness(self):
"""Test MaxPool3D layer dilation numerical correctness."""
input_np = np.random.random([1, 2, 8, 8, 8]).astype("float32")
pool = paddle.nn.MaxPool3D(
kernel_size=2, stride=1, padding=0, return_mask=True, dilation=2
)
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=[2, 2, 2],
strides=[1, 1, 1],
paddings=[0, 0, 0],
dilations=[2, 2, 2],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool3D layer dilation output mismatch",
)
def test_maxpool3d_layer_dilation_asymmetric(self):
"""Test MaxPool3D layer with asymmetric dilation values."""
pool = paddle.nn.MaxPool3D(
kernel_size=2,
stride=2,
padding=0,
return_mask=True,
dilation=(2, 2, 3),
)
input_np = np.random.random([1, 2, 10, 12, 14]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=[2, 2, 2],
strides=[2, 2, 2],
paddings=[0, 0, 0],
dilations=[2, 2, 3],
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool3D layer asymmetric dilation mismatch",
)
def test_maxpool3d_layer_dilation_various_values(self):
"""Test MaxPool3D layer with various dilation values."""
test_configs = [
{"ksize": 2, "stride": 1, "padding": 0, "dilation": (2, 2, 2)},
{"ksize": 2, "stride": 2, "padding": 1, "dilation": (2, 2, 3)},
]
for config in test_configs:
pool = paddle.nn.MaxPool3D(
kernel_size=config["ksize"],
stride=config["stride"],
padding=config["padding"],
return_mask=True,
dilation=config["dilation"],
)
input_np = np.random.random([1, 2, 10, 12, 12]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, _ = pool(input_tensor)
ksize = [config["ksize"]] * 3
stride = [config["stride"]] * 3
padding = [config["padding"]] * 3
dilation = list(config["dilation"])
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=ksize,
strides=stride,
paddings=padding,
dilations=dilation,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg=f"MaxPool3D layer mismatch with config: {config}",
)
def test_maxpool3d_layer_dilation_gradient(self):
"""Test MaxPool3D layer gradient with dilation."""
pool = paddle.nn.MaxPool3D(
kernel_size=2, stride=2, padding=0, return_mask=True, dilation=2
)
input_np = np.random.random([2, 3, 8, 8, 8]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
input_tensor.stop_gradient = False
result, _ = pool(input_tensor)
loss = paddle.mean(result)
loss.backward()
self.assertIsNotNone(input_tensor.grad)
self.assertEqual(list(input_tensor.grad.shape), [2, 3, 8, 8, 8])
def test_maxpool3d_layer_dilation_with_ceil_mode(self):
"""Test MaxPool3D layer with dilation and ceil_mode."""
pool = paddle.nn.MaxPool3D(
kernel_size=2,
stride=2,
padding=0,
return_mask=True,
ceil_mode=True,
dilation=2,
)
input_np = np.random.random([1, 2, 8, 10, 10]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=[2, 2, 2],
strides=[2, 2, 2],
paddings=[0, 0, 0],
dilations=[2, 2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool3D layer dilation with ceil_mode mismatch",
)
def test_maxpool3d_layer_dilation_using_paddle_pos_args(self):
"""Test MaxPool3D layer using paddle positional arguments."""
pool = paddle.nn.MaxPool3D(
2,
2,
0,
True, # return_mask
True, # ceil_mode
2,
)
input_np = np.random.random([1, 2, 8, 10, 10]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=[2, 2, 2],
strides=[2, 2, 2],
paddings=[0, 0, 0],
dilations=[2, 2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool3D layer using paddle positional arguments mismatch",
)
def test_maxpool3d_layer_dilation_using_torch_pos_args(self):
"""Test MaxPool3D layer using torch-like positional arguments."""
pool = paddle.nn.MaxPool3D(
2,
2,
0,
2,
True, # return_indices
True, # ceil_mode
)
input_np = np.random.random([1, 2, 8, 10, 10]).astype("float32")
input_tensor = paddle.to_tensor(input_np)
result, mask = pool(input_tensor)
expected, _ = max_pool3d_dilation_forward_naive(
input_np,
ksize=[2, 2, 2],
strides=[2, 2, 2],
paddings=[0, 0, 0],
dilations=[2, 2, 2],
ceil_mode=True,
)
np.testing.assert_allclose(
result.numpy(),
expected,
rtol=1e-05,
err_msg="MaxPool3D layer using torch-like positional arguments mismatch",
)
# ===================== OpTest for max_pool2d_with_index with dilation =====================
def max_pool2d_with_index_dilation_wrapper(
x,
kernel_size=[],
strides=[],
paddings=[],
dilations=[],
global_pooling=False,
adaptive=False,
ceil_mode=False,
):
return paddle._C_ops.max_pool2d_with_index(
x,
kernel_size,
strides,
paddings,
dilations,
global_pooling,
adaptive,
ceil_mode,
)
class TestMaxPool2DWithIndexDilationOp(OpTest):
"""OpTest for max_pool2d_with_index with dilation parameter."""
def setUp(self):
self.op_type = "max_pool2d_with_index"
self.python_api = max_pool2d_with_index_dilation_wrapper
self.init_test_case()
self.init_dtype()
input = np.random.random(self.shape).astype(self.dtype)
input = np.round(input * 100.0, 2)
output, mask = max_pool2d_dilation_forward_naive(
input,
ksize=self.ksize,
strides=self.strides,
paddings=self.paddings,
dilations=self.dilations,
)
mask = mask.astype("int32")
output = output.astype(self.dtype)
self.inputs = {'X': input}
self.outputs = {'Out': output, 'Mask': mask}
self.attrs = {
'strides': self.strides,
'paddings': self.paddings,
'ksize': self.ksize,
'dilations': self.dilations,
'global_pooling': False,
'adaptive': False,
}
def init_dtype(self):
self.dtype = np.float64
def init_test_case(self):
self.shape = [2, 3, 16, 16]
self.ksize = [3, 3]
self.strides = [2, 2]
self.paddings = [1, 1]
self.dilations = [2, 2]
def test_check_output(self):
self.check_output()
def test_check_grad(self):
self.check_grad({'X'}, ['Out'])
class TestMaxPool2DWithIndexDilationOp2(TestMaxPool2DWithIndexDilationOp):
"""Test with different dilation values."""
def init_test_case(self):
self.shape = [2, 3, 24, 24]
self.ksize = [2, 2]
self.strides = [1, 1]
self.paddings = [0, 0]
self.dilations = [3, 3]
class TestMaxPool2DWithIndexDilationOp3(TestMaxPool2DWithIndexDilationOp):
"""Test with asymmetric dilation."""
def init_test_case(self):
self.shape = [2, 3, 20, 20]
self.ksize = [3, 3]
self.strides = [2, 2]
self.paddings = [1, 1]
self.dilations = [2, 3]
class TestMaxPool2DWithIndexDilationOp4(TestMaxPool2DWithIndexDilationOp):
"""Test with larger kernel and dilation."""
def init_test_case(self):
self.shape = [1, 2, 32, 32]
self.ksize = [4, 4]
self.strides = [2, 2]
self.paddings = [2, 2]
self.dilations = [2, 2]
class TestMaxPool2DWithIndexDilationOp5(TestMaxPool2DWithIndexDilationOp):
"""Test with asymmetric dilation."""
def init_test_case(self):
self.shape = [1, 2, 12, 14]
self.ksize = [2, 2]
self.strides = [2, 2]
self.paddings = [0, 0]
self.dilations = [2, 3]
class TestMaxPool2DWithIndexDilationOp6(TestMaxPool2DWithIndexDilationOp):
"""Coverage with cpu branch."""
def test_check_output(self):
self.check_output_with_place(paddle.CPUPlace())
def test_check_grad(self):
self.check_grad_with_place(paddle.CPUPlace(), {'X'}, ['Out'])
# ===================== OpTest for max_pool3d_with_index with dilation =====================
def max_pool3d_with_index_dilation_wrapper(
x,
kernel_size=[],
strides=[],
paddings=[],
dilations=[],
global_pooling=False,
adaptive=False,
ceil_mode=False,
):
return paddle._C_ops.max_pool3d_with_index(
x,
kernel_size,
strides,
paddings,
dilations,
global_pooling,
adaptive,
ceil_mode,
)
class TestMaxPool3DWithIndexDilationOp(OpTest):
"""OpTest for max_pool3d_with_index with dilation parameter."""
def setUp(self):
self.op_type = "max_pool3d_with_index"
self.python_api = max_pool3d_with_index_dilation_wrapper
self.init_test_case()
self.init_dtype()
input = np.random.random(self.shape).astype(self.dtype)
input = np.round(input * 100.0, 2)
output, mask = max_pool3d_dilation_forward_naive(
input,
ksize=self.ksize,
strides=self.strides,
paddings=self.paddings,
dilations=self.dilations,
)
mask = mask.astype("int32")
output = output.astype(self.dtype)
self.inputs = {'X': input}
self.outputs = {'Out': output, 'Mask': mask}
self.attrs = {
'strides': self.strides,
'paddings': self.paddings,
'ksize': self.ksize,
'dilations': self.dilations,
'global_pooling': False,
'adaptive': False,
}
def init_dtype(self):
self.dtype = np.float64
def init_test_case(self):
self.shape = [2, 3, 8, 8, 8]
self.ksize = [2, 2, 2]
self.strides = [2, 2, 2]
self.paddings = [0, 0, 0]
self.dilations = [2, 2, 2]
def test_check_output(self):
self.check_output()
def test_check_grad(self):
self.check_grad({'X'}, ['Out'])
class TestMaxPool3DWithIndexDilationOp2(TestMaxPool3DWithIndexDilationOp):
"""Test with different dilation values."""
def init_test_case(self):
self.shape = [1, 2, 10, 10, 10]
self.ksize = [3, 3, 3]
self.strides = [2, 2, 2]
self.paddings = [1, 1, 1]
self.dilations = [2, 2, 2]
class TestMaxPool3DWithIndexDilationOp3(TestMaxPool3DWithIndexDilationOp):
"""Test with asymmetric dilation."""
def init_test_case(self):
self.shape = [1, 2, 12, 12, 15]
self.ksize = [2, 2, 2]
self.strides = [2, 2, 2]
self.paddings = [0, 0, 0]
self.dilations = [2, 2, 3]
class TestMaxPool3DWithIndexDilationOp4(TestMaxPool3DWithIndexDilationOp):
"""Coverage with cpu branch."""
def test_check_output(self):
self.check_output_with_place(paddle.CPUPlace())
def test_check_grad(self):
self.check_grad_with_place(paddle.CPUPlace(), {'X'}, ['Out'])
if __name__ == '__main__':
unittest.main()