4412 lines
153 KiB
Python
4412 lines
153 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 sys
|
|
import unittest
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
|
|
|
|
# Test histc compatibility
|
|
class TestHistcAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(100).astype("float32") * 10
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.histc(x, bins=10, min=0, max=10)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.histc(input=x, bins=10, min=0, max=10)
|
|
# 3. Tensor method
|
|
out3 = x.histc(bins=10, min=0, max=10)
|
|
# 4. out parameter test
|
|
out4 = paddle.empty_like(out1)
|
|
paddle.histc(x, bins=10, min=0, max=10, out=out4)
|
|
|
|
# Verify outputs are float32 (PyTorch compatibility)
|
|
self.assertEqual(out1.dtype, paddle.float32)
|
|
for out in [out1, out2, out3, out4]:
|
|
self.assertEqual(out.dtype, paddle.float32)
|
|
# Verify numerical correctness
|
|
expected = np.histogram(self.np_x, bins=10, range=(0, 10))[
|
|
0
|
|
].astype("float32")
|
|
if out is out4:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
else:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[100], dtype="float32")
|
|
|
|
out1 = paddle.histc(x, bins=10, min=0, max=10)
|
|
out2 = paddle.histc(input=x, bins=10, min=0, max=10)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
expected = np.histogram(self.np_x, bins=10, range=(0, 10))[
|
|
0
|
|
].astype("float32")
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test mvlgamma compatibility (alias for multigammaln)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestMvlgammaAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([2.5, 3.5, 4.5]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments (mvlgamma is alias for multigammaln)
|
|
out1 = paddle.mvlgamma(x, p=2)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.mvlgamma(x=x, p=2)
|
|
# 3. Tensor method
|
|
out3 = x.mvlgamma(p=2)
|
|
|
|
# Verify outputs
|
|
for out in [out1, out2, out3]:
|
|
self.assertEqual(out.shape, (3,))
|
|
|
|
|
|
# Test mvlgamma_ compatibility (inplace)
|
|
class TestMvlgamma_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([2.5, 3.5, 4.5]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x.copy())
|
|
|
|
# Inplace operation
|
|
x.mvlgamma_(p=2)
|
|
|
|
# Verify shape unchanged
|
|
self.assertEqual(x.shape, (3,))
|
|
|
|
|
|
# Test negative_ compatibility (alias for neg_)
|
|
class TestNegative_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, -2.0, 3.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x.copy())
|
|
|
|
# Inplace operation (negative_ is alias for neg_)
|
|
x.negative_()
|
|
|
|
expected = -self.np_x
|
|
np.testing.assert_allclose(x.numpy(), expected, rtol=1e-5)
|
|
|
|
|
|
# Test to_sparse compatibility (alias for to_sparse_coo)
|
|
class TestToSparseAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
if paddle.is_compiled_with_xpu():
|
|
self.skipTest("sparse ops are not supported on XPU")
|
|
|
|
dense_x = paddle.to_tensor(
|
|
[[0, 1, 0, 2], [0, 0, 3, 4]], dtype='float32'
|
|
)
|
|
|
|
# to_sparse is alias for to_sparse_coo
|
|
sparse_x = dense_x.to_sparse(sparse_dim=2)
|
|
|
|
self.assertTrue(sparse_x.is_sparse_coo())
|
|
|
|
|
|
# Test special.round compatibility
|
|
class TestSpecialRoundAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([0.5, -0.3, 1.7, -2.4]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# paddle.special.round is alias for paddle.round
|
|
out1 = paddle.special.round(x)
|
|
out2 = paddle.round(x)
|
|
|
|
np.testing.assert_allclose(out1.numpy(), out2.numpy(), rtol=1e-5)
|
|
|
|
|
|
# Test autograd.enable_grad compatibility
|
|
class TestAutogradEnableGradAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# paddle.autograd.enable_grad should work
|
|
@paddle.autograd.enable_grad()
|
|
def test_func(x):
|
|
return x * 2
|
|
|
|
x = paddle.to_tensor([1.0, 2.0])
|
|
with paddle.no_grad():
|
|
y = test_func(x)
|
|
|
|
np.testing.assert_allclose(y.numpy(), [2.0, 4.0], rtol=1e-5)
|
|
|
|
|
|
# Test col_indices compatibility (alias for cols)
|
|
class TestColIndicesAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
if paddle.is_compiled_with_xpu():
|
|
self.skipTest("sparse ops are not supported on XPU")
|
|
|
|
# Create a sparse CSR tensor
|
|
crows = paddle.to_tensor([0, 2, 3, 5], dtype='int64')
|
|
cols = paddle.to_tensor([1, 3, 2, 0, 1], dtype='int64')
|
|
values = paddle.to_tensor([1.0, 2.0, 3.0, 4.0, 5.0], dtype='float32')
|
|
dense_shape = [3, 4]
|
|
|
|
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape)
|
|
|
|
# col_indices is alias for cols
|
|
result1 = csr.col_indices()
|
|
result2 = csr.cols()
|
|
|
|
np.testing.assert_array_equal(result1.numpy(), result2.numpy())
|
|
|
|
|
|
# Test crow_indices compatibility (alias for crows)
|
|
class TestCrowIndicesAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
if paddle.is_compiled_with_xpu():
|
|
self.skipTest("sparse ops are not supported on XPU")
|
|
|
|
# Create a sparse CSR tensor
|
|
crows = paddle.to_tensor([0, 2, 3, 5], dtype='int64')
|
|
cols = paddle.to_tensor([1, 3, 2, 0, 1], dtype='int64')
|
|
values = paddle.to_tensor([1.0, 2.0, 3.0, 4.0, 5.0], dtype='float32')
|
|
dense_shape = [3, 4]
|
|
|
|
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape)
|
|
|
|
# crow_indices is alias for crows
|
|
result1 = csr.crow_indices()
|
|
result2 = csr.crows()
|
|
|
|
np.testing.assert_array_equal(result1.numpy(), result2.numpy())
|
|
|
|
|
|
# Test take compatibility
|
|
class TestTakeAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1, 2, 3, 4, 5]).astype("float32")
|
|
self.np_indices = np.array([0, 2, 4]).astype("int64")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
indices = paddle.to_tensor(self.np_indices)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.take(x, indices)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.take(x=x, index=indices)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.take(input=x, index=indices)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.take(x, index=indices)
|
|
|
|
# 5. Tensor method - args
|
|
out5 = x.take(indices)
|
|
|
|
# Verify all outputs
|
|
expected = self.np_x[self.np_indices]
|
|
for out in [out1, out2, out3, out4, out5]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=self.np_x.shape, dtype=str(self.np_x.dtype)
|
|
)
|
|
indices = paddle.static.data(
|
|
name="indices",
|
|
shape=self.np_indices.shape,
|
|
dtype=str(self.np_indices.dtype),
|
|
)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.take(x, indices)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.take(x=x, index=indices)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.take(input=x, index=indices)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"indices": self.np_indices,
|
|
},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
expected = self.np_x[self.np_indices]
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test matrix_exp compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestMatrixExpAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([[1.0, 0.0], [0.0, 1.0]]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
if paddle.is_compiled_with_rocm():
|
|
self.skipTest("Skip on DCU due to kernel issue")
|
|
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. paddle.linalg.matrix_exp
|
|
out1 = paddle.linalg.matrix_exp(x)
|
|
# 2. Tensor method
|
|
out2 = x.matrix_exp()
|
|
|
|
# Verify outputs - matrix_exp of identity is e^1 * identity
|
|
expected = np.exp(1.0) * np.eye(2)
|
|
for out in [out1, out2]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
if paddle.is_compiled_with_rocm():
|
|
self.skipTest("Skip on DCU due to kernel issue")
|
|
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=self.np_x.shape, dtype=str(self.np_x.dtype)
|
|
)
|
|
|
|
out1 = paddle.linalg.matrix_exp(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1],
|
|
)
|
|
|
|
expected = np.exp(1.0) * np.eye(2)
|
|
np.testing.assert_allclose(fetches[0], expected, rtol=1e-5)
|
|
|
|
# Test retain_grad compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestRetainGradAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Test retain_grad on leaf tensor
|
|
x = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
x.stop_gradient = False
|
|
x.retain_grad()
|
|
|
|
y = x * 2
|
|
y.sum().backward()
|
|
|
|
# Gradient should be retained
|
|
np.testing.assert_allclose(x.grad.numpy(), [2.0, 2.0, 2.0], rtol=1e-5)
|
|
|
|
# Test retain_grad on non-leaf tensor
|
|
a = paddle.to_tensor([1.0, 2.0])
|
|
a.stop_gradient = False
|
|
b = a * 3 # non-leaf
|
|
b.retain_grad()
|
|
c = b * 2
|
|
c.sum().backward()
|
|
|
|
# b's gradient should be retained
|
|
np.testing.assert_allclose(b.grad.numpy(), [2.0, 2.0], rtol=1e-5)
|
|
|
|
|
|
# Test sparse_mask compatibility
|
|
class TestSparseMaskAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
# Skip on XPU as sparse_mask is not supported
|
|
if paddle.is_compiled_with_xpu():
|
|
self.skipTest("sparse_mask is not supported on XPU")
|
|
|
|
# Create dense tensor
|
|
x = paddle.to_tensor([[1.0, 2.0], [3.0, 4.0]])
|
|
|
|
# Create sparse COO tensor as mask
|
|
indices = paddle.to_tensor([[0, 1], [0, 1]], dtype='int64')
|
|
values = paddle.to_tensor([1.0, 1.0], dtype='float32')
|
|
mask = paddle.sparse.sparse_coo_tensor(indices, values, [2, 2])
|
|
|
|
# Apply sparse_mask
|
|
result = x.sparse_mask(mask)
|
|
|
|
# Verify result is sparse and has correct values
|
|
np.testing.assert_allclose(
|
|
result.values().numpy(), [1.0, 4.0], rtol=1e-5
|
|
)
|
|
|
|
|
|
# Test ParameterList compatibility (values -> parameters alias)
|
|
class TestParameterListAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Paddle keyword arguments (parameters)
|
|
params1 = [
|
|
paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
for _ in range(3)
|
|
]
|
|
pl1 = paddle.nn.ParameterList(parameters=params1)
|
|
|
|
# 2. PyTorch keyword arguments (values alias)
|
|
params2 = [
|
|
paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
for _ in range(3)
|
|
]
|
|
pl2 = paddle.nn.ParameterList(values=params2)
|
|
|
|
# 3. PyTorch positional arguments
|
|
params3 = [
|
|
paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
for _ in range(3)
|
|
]
|
|
pl3 = paddle.nn.ParameterList(params3)
|
|
|
|
# 4. Mixed arguments
|
|
params4 = [
|
|
paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
for _ in range(3)
|
|
]
|
|
pl4 = paddle.nn.ParameterList(params4)
|
|
|
|
# 5. Test append with value alias
|
|
pl5 = paddle.nn.ParameterList()
|
|
param = paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
pl5.append(value=param)
|
|
|
|
# 6. Test extend with parameters alias
|
|
pl6 = paddle.nn.ParameterList()
|
|
params6 = [
|
|
paddle.create_parameter(shape=[2, 3], dtype='float32')
|
|
for _ in range(2)
|
|
]
|
|
pl6.extend(parameters=params6)
|
|
|
|
# Verify lengths
|
|
self.assertEqual(len(pl1), 3)
|
|
self.assertEqual(len(pl2), 3)
|
|
self.assertEqual(len(pl3), 3)
|
|
self.assertEqual(len(pl4), 3)
|
|
self.assertEqual(len(pl5), 1)
|
|
self.assertEqual(len(pl6), 2)
|
|
|
|
|
|
# Test scatter_reduce_ compatibility (inplace)
|
|
class TestScatterReduce_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([[10, 20, 30], [40, 50, 60]]).astype("float32")
|
|
self.np_index = np.zeros((2, 3)).astype("int64")
|
|
self.np_src = np.array([[1, 2, 3], [4, 5, 6]]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Paddle scatter_reduce_ positional
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
index = paddle.to_tensor(self.np_index)
|
|
src = paddle.to_tensor(self.np_src)
|
|
out1 = x1.scatter_reduce_(0, index, src, "sum", include_self=True)
|
|
|
|
# 2. Paddle keyword arguments
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = x2.scatter_reduce_(
|
|
dim=0, index=index, src=src, reduce="sum", include_self=True
|
|
)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
# Note: src is alias for src in Paddle too, but let's check
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = x3.scatter_reduce_(dim=0, index=index, src=src, reduce="sum")
|
|
|
|
# 4. Mixed arguments
|
|
x4 = paddle.to_tensor(self.np_x.copy())
|
|
out4 = x4.scatter_reduce_(0, index, src=src, reduce="sum")
|
|
|
|
# Verify inplace operation returns self
|
|
self.assertIs(out1, x1)
|
|
self.assertIs(out2, x2)
|
|
self.assertIs(out3, x3)
|
|
self.assertIs(out4, x4)
|
|
|
|
# Verify results
|
|
self.assertEqual(out1.shape, [2, 3])
|
|
np.testing.assert_allclose(out1.numpy(), out2.numpy())
|
|
|
|
|
|
# Test xavier_uniform compatibility (alias for xavier_uniform_)
|
|
class TestXavierUniformAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. paddle.nn.init.xavier_uniform_ (with underscore)
|
|
x1 = paddle.empty([3, 4], dtype='float32')
|
|
paddle.nn.init.xavier_uniform_(x1, gain=1.0)
|
|
|
|
# 2. paddle.nn.init.xavier_uniform (without underscore, PyTorch deprecated alias)
|
|
x2 = paddle.empty([3, 4], dtype='float32')
|
|
paddle.nn.init.xavier_uniform(x2, gain=1.0)
|
|
|
|
# 3. PyTorch keyword arguments (tensor alias for x)
|
|
x3 = paddle.empty([3, 4], dtype='float32')
|
|
paddle.nn.init.xavier_uniform(tensor=x3, gain=1.0)
|
|
|
|
# 4. Mixed arguments
|
|
x4 = paddle.empty([3, 4], dtype='float32')
|
|
paddle.nn.init.xavier_uniform(x4, gain=1.0)
|
|
|
|
# Both should work the same
|
|
self.assertEqual(x1.shape, x2.shape)
|
|
self.assertEqual(x1.shape, x3.shape)
|
|
self.assertEqual(x1.shape, x4.shape)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x1 = paddle.static.data(name="x1", shape=[3, 4], dtype="float32")
|
|
x2 = paddle.static.data(name="x2", shape=[3, 4], dtype="float32")
|
|
|
|
# 1. paddle.nn.init.xavier_uniform_ (with underscore)
|
|
paddle.nn.init.xavier_uniform_(x1)
|
|
|
|
# 2. paddle.nn.init.xavier_uniform (without underscore, PyTorch deprecated alias)
|
|
paddle.nn.init.xavier_uniform(x2)
|
|
|
|
# Just verify it doesn't crash
|
|
self.assertIsNotNone(x1)
|
|
self.assertIsNotNone(x2)
|
|
|
|
# Test sign_ compatibility (inplace)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestSign_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([-2.0, -1.0, 0.0, 1.0, 2.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Tensor method - args
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
out1 = x1.sign_()
|
|
|
|
# 2. Paddle function - positional
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = paddle.sign_(x2)
|
|
|
|
# 3. Paddle function - keyword
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = paddle.sign_(x=x3)
|
|
|
|
# 4. PyTorch function - keyword (input alias)
|
|
x4 = paddle.to_tensor(self.np_x.copy())
|
|
out4 = paddle.sign_(input=x4)
|
|
|
|
# Verify all outputs
|
|
expected = np.sign(self.np_x)
|
|
for out in [out1, out2, out3, out4]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_pir_infer_symbolic_shape(self):
|
|
from paddle.base.libpaddle import pir
|
|
|
|
with paddle.pir_utils.IrGuard():
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[5], dtype="float32")
|
|
out = paddle.sign_(x)
|
|
|
|
pm = pir.PassManager()
|
|
pir.infer_symbolic_shape_pass(pm, main)
|
|
pm.run(main)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x.copy()},
|
|
fetch_list=[out],
|
|
)
|
|
out_ref = np.sign(self.np_x)
|
|
np.testing.assert_allclose(fetches[0], out_ref, rtol=1e-5)
|
|
|
|
|
|
# Test linalg.pinv compatibility (atol, rtol, out parameters)
|
|
class TestLinalgPinvAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(3, 5).astype("float32")
|
|
self.shape = [3, 5]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle positional arguments (using rcond)
|
|
out1 = paddle.linalg.pinv(x, rcond=1e-15)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.pinv(x=x, rcond=1e-15, hermitian=False)
|
|
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
out3 = paddle.linalg.pinv(input=x)
|
|
|
|
# 4. PyTorch keyword arguments (rtol alias)
|
|
out4 = paddle.linalg.pinv(x, rtol=1e-15)
|
|
|
|
# 5. Mixed arguments (atol, rtol)
|
|
out5 = paddle.linalg.pinv(x, atol=1e-10, rtol=1e-10)
|
|
|
|
# 6. out parameter test
|
|
out6 = paddle.empty([5, 3], dtype='float32')
|
|
paddle.linalg.pinv(x, out=out6)
|
|
|
|
# 7. Tensor method - args
|
|
out7 = x.pinverse()
|
|
|
|
# 8. Alias paddle.pinverse
|
|
out8 = paddle.pinverse(x)
|
|
|
|
# 9. hermitian=True with atol (need square matrix for hermitian)
|
|
x_sq = paddle.to_tensor(np.random.rand(3, 3).astype("float32"))
|
|
x_sym = x_sq @ x_sq.T + paddle.eye(3) * 0.5 # full rank
|
|
out9 = paddle.linalg.pinv(x_sym, hermitian=True, atol=1e-4)
|
|
|
|
# 10. hermitian=True with rtol
|
|
out10 = paddle.linalg.pinv(x_sym, hermitian=True, rtol=1e-4)
|
|
|
|
# 11. hermitian=True with both atol and rtol
|
|
out11 = paddle.linalg.pinv(x_sym, hermitian=True, atol=1e-4, rtol=1e-4)
|
|
|
|
# Verify all outputs
|
|
expected = np.linalg.pinv(self.np_x)
|
|
for out in [out1, out2, out3, out4, out5, out6, out7, out8]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
expected_sym = np.linalg.pinv(x_sym.numpy(), hermitian=True)
|
|
for out in [out9, out10, out11]:
|
|
np.testing.assert_allclose(out.numpy(), expected_sym, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.pinv(x)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.pinv(x=x)
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
out3 = paddle.linalg.pinv(input=x)
|
|
# 4. Tensor method - args
|
|
out4 = x.pinverse()
|
|
# 5. Alias paddle.pinverse
|
|
out5 = paddle.pinverse(x)
|
|
|
|
# 6. atol parameter test (keyword-only)
|
|
out6 = paddle.linalg.pinv(x, atol=1e-10)
|
|
|
|
# 7. rtol parameter test (keyword-only)
|
|
out7 = paddle.linalg.pinv(x, rtol=1e-10)
|
|
|
|
# 8. atol and rtol combined (keyword-only)
|
|
out8 = paddle.linalg.pinv(x, atol=1e-10, rtol=1e-10)
|
|
|
|
# 9. out parameter test
|
|
out9 = paddle.static.data(
|
|
name="out9", shape=[5, 3], dtype="float32"
|
|
)
|
|
paddle.linalg.pinv(x, out=out9)
|
|
|
|
# 10. hermitian=True with atol (square matrix)
|
|
x_sym = paddle.static.data(
|
|
name="x_sym", shape=[3, 3], dtype="float32"
|
|
)
|
|
out10 = paddle.linalg.pinv(x_sym, hermitian=True, atol=1e-4)
|
|
|
|
# 11. hermitian=True with rtol
|
|
out11 = paddle.linalg.pinv(x_sym, hermitian=True, rtol=1e-4)
|
|
|
|
# 12. hermitian=True with both atol and rtol
|
|
out12 = paddle.linalg.pinv(
|
|
x_sym, hermitian=True, atol=1e-4, rtol=1e-4
|
|
)
|
|
|
|
exe = paddle.static.Executor()
|
|
np_x_sym = (
|
|
self.np_x @ self.np_x.T
|
|
+ np.eye(3, dtype=self.dtype) * 0.5 # full rank
|
|
)
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"out9": np.empty([5, 3], dtype="float32"),
|
|
"x_sym": np_x_sym,
|
|
},
|
|
fetch_list=[
|
|
out1,
|
|
out2,
|
|
out3,
|
|
out4,
|
|
out5,
|
|
out6,
|
|
out7,
|
|
out8,
|
|
out9,
|
|
out10,
|
|
out11,
|
|
out12,
|
|
],
|
|
)
|
|
|
|
expected = np.linalg.pinv(self.np_x)
|
|
for out in fetches[:9]:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
expected_sym = np.linalg.pinv(np_x_sym, hermitian=True)
|
|
for out in fetches[9:]:
|
|
np.testing.assert_allclose(out, expected_sym, rtol=1e-5)
|
|
|
|
# Test nll_loss compatibility (target -> label alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestNllLossAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_input = np.random.rand(5, 3).astype("float32")
|
|
self.np_label = np.array([0, 2, 1, 1, 0], dtype="int64")
|
|
self.shape_input = [5, 3]
|
|
self.shape_label = [5]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
log_softmax = paddle.nn.LogSoftmax(axis=1)
|
|
input = log_softmax(paddle.to_tensor(self.np_input))
|
|
label = paddle.to_tensor(self.np_label)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.nll_loss(input, label)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.nll_loss(input=input, label=label)
|
|
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.nll_loss(input=input, target=label)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.nn.functional.nll_loss(
|
|
input, target=label, reduction='mean'
|
|
)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4]:
|
|
np.testing.assert_allclose(out.numpy(), out1.numpy(), rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
input = paddle.static.data(
|
|
name="input", shape=self.shape_input, dtype=self.dtype
|
|
)
|
|
label = paddle.static.data(
|
|
name="label", shape=self.shape_label, dtype="int64"
|
|
)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.nll_loss(input, label)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.nll_loss(input=input, label=label)
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.nll_loss(input=input, target=label)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"input": self.np_input, "label": self.np_label},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, ())
|
|
|
|
# Test bernoulli_ compatibility (inplace)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestBernoulli_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(3, 4).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Tensor method - args
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
out1 = x1.bernoulli_()
|
|
|
|
# 2. Tensor method - kwargs
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = x2.bernoulli_(p=0.3)
|
|
|
|
# 3. Paddle function - positional
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = paddle.bernoulli_(x3, p=0.5)
|
|
|
|
# 4. Paddle function - keyword
|
|
x4 = paddle.to_tensor(self.np_x.copy())
|
|
out4 = paddle.bernoulli_(x=x4, p=0.5)
|
|
|
|
# Verify inplace operation returns self
|
|
self.assertIs(out1, x1)
|
|
self.assertIs(out2, x2)
|
|
self.assertIs(out3, x3)
|
|
self.assertIs(out4, x4)
|
|
|
|
# Verify output contains only 0s and 1s
|
|
for out in [out1, out2, out3, out4]:
|
|
self.assertTrue(paddle.all((out == 0) | (out == 1)).item())
|
|
|
|
|
|
# Test kl_div compatibility (target -> label alias)
|
|
class TestKlDivAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_input = np.random.rand(5, 10).astype("float32")
|
|
self.np_target = np.random.rand(5, 10).astype("float32")
|
|
self.shape_input = [5, 10]
|
|
self.shape_target = [5, 10]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
input = paddle.to_tensor(self.np_input)
|
|
target = paddle.to_tensor(self.np_target)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.kl_div(input, target)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.kl_div(input=input, label=target)
|
|
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.kl_div(input=input, target=target)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.nn.functional.kl_div(
|
|
input, target=target, reduction='mean'
|
|
)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4]:
|
|
np.testing.assert_allclose(out.numpy(), out1.numpy(), rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
input = paddle.static.data(
|
|
name="input", shape=self.shape_input, dtype=self.dtype
|
|
)
|
|
target = paddle.static.data(
|
|
name="target", shape=self.shape_target, dtype=self.dtype
|
|
)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.kl_div(input, target)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.kl_div(input=input, label=target)
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.kl_div(input=input, target=target)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"input": self.np_input, "target": self.np_target},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, ())
|
|
|
|
# Test hann_window compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestHannWindowAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.hann_window(512)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.hann_window(window_length=512, periodic=True)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.hann_window(window_length=512, periodic=False)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.hann_window(512, periodic=True)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4]:
|
|
self.assertEqual(out.shape, [512])
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.hann_window(512)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.hann_window(window_length=512)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.hann_window(window_length=512, periodic=True)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(main, feed={}, fetch_list=[out1, out2, out3])
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, (512,))
|
|
|
|
# Test paddle.float compatibility (dtype alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestFloatDtypeAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. paddle.float should be float32
|
|
self.assertEqual(paddle.float, paddle.float32)
|
|
|
|
# 2. Create tensor with paddle.float dtype
|
|
x = paddle.to_tensor([1.0, 2.0], dtype=paddle.float)
|
|
self.assertEqual(x.dtype, paddle.float32)
|
|
|
|
# 3. Use in create_parameter
|
|
param = paddle.create_parameter(shape=[2, 3], dtype=paddle.float)
|
|
self.assertEqual(param.dtype, paddle.float32)
|
|
|
|
|
|
# Test fmod_ compatibility (inplace)
|
|
class TestFmod_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([5.0, 7.0, 9.0]).astype("float32")
|
|
self.np_y = np.array([2.0, 3.0, 4.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
y = paddle.to_tensor(self.np_y)
|
|
|
|
# 1. Tensor method - positional
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
out1 = x1.fmod_(y)
|
|
|
|
# 2. Tensor method - keyword
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = x2.fmod_(other=y)
|
|
|
|
# 3. paddle function - positional
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = paddle.fmod_(x3, y)
|
|
|
|
# 4. paddle function - keyword (input alias)
|
|
x4 = paddle.to_tensor(self.np_x.copy())
|
|
out4 = paddle.fmod_(input=x4, other=y)
|
|
|
|
# 5. Mixed arguments
|
|
x5 = paddle.to_tensor(self.np_x.copy())
|
|
out5 = paddle.fmod_(x5, other=y)
|
|
|
|
# Verify inplace operation returns self
|
|
self.assertIs(out1, x1)
|
|
self.assertIs(out2, x2)
|
|
self.assertIs(out3, x3)
|
|
self.assertIs(out4, x4)
|
|
self.assertIs(out5, x5)
|
|
|
|
# Verify result
|
|
expected = np.fmod(self.np_x, self.np_y)
|
|
for out in [out1, out2, out3, out4, out5]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
|
|
# Test fill_diagonal_ compatibility (inplace)
|
|
class TestFillDiagonal_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.ones((4, 3)).astype("float32") * 2
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Tensor method - positional
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
out1 = x1.fill_diagonal_(1.0)
|
|
|
|
# 2. Tensor method - keyword
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = x2.fill_diagonal_(fill_value=1.0)
|
|
|
|
# 3. Mixed arguments
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = x3.fill_diagonal_(1.0, wrap=False)
|
|
|
|
# Verify inplace operation returns self
|
|
self.assertIs(out1, x1)
|
|
self.assertIs(out2, x2)
|
|
self.assertIs(out3, x3)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3]:
|
|
self.assertEqual(out[0, 0].item(), 1.0)
|
|
self.assertEqual(out[1, 1].item(), 1.0)
|
|
self.assertEqual(out[2, 2].item(), 1.0)
|
|
|
|
|
|
# Test weight_norm compatibility (module -> layer alias)
|
|
class TestWeightNormAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Create a simple layer
|
|
conv = paddle.nn.Conv2D(3, 5, 3)
|
|
|
|
# 1. Paddle keyword arguments
|
|
wn1 = paddle.nn.utils.weight_norm(layer=conv)
|
|
|
|
# 2. PyTorch keyword arguments (module alias)
|
|
conv2 = paddle.nn.Conv2D(3, 5, 3)
|
|
wn2 = paddle.nn.utils.weight_norm(module=conv2)
|
|
|
|
# 3. Paddle Positional arguments
|
|
conv3 = paddle.nn.Conv2D(3, 5, 3)
|
|
wn3 = paddle.nn.utils.weight_norm(conv3)
|
|
|
|
# Verify all work correctly
|
|
self.assertIsNotNone(wn1.weight_g)
|
|
self.assertIsNotNone(wn2.weight_g)
|
|
self.assertIsNotNone(wn3.weight_g)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
# 1. Paddle Positional arguments
|
|
conv1 = paddle.nn.Conv2D(3, 5, 3)
|
|
wn1 = paddle.nn.utils.weight_norm(conv1)
|
|
# 2. PyTorch keyword arguments (module alias)
|
|
conv2 = paddle.nn.Conv2D(3, 5, 3)
|
|
wn2 = paddle.nn.utils.weight_norm(module=conv2)
|
|
|
|
# Just verify it doesn't crash in static graph definition
|
|
self.assertIsNotNone(wn1)
|
|
self.assertIsNotNone(wn2)
|
|
|
|
# Test resize_ compatibility (variable args support)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestResize_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x.copy())
|
|
|
|
# 1. Paddle list/tuple argument
|
|
out1 = x.resize_([2, 3])
|
|
|
|
# 2. PyTorch variable args
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = x2.resize_(2, 3)
|
|
|
|
# Verify both produce same shape
|
|
self.assertEqual(out1.shape, [2, 3])
|
|
self.assertEqual(out2.shape, [2, 3])
|
|
|
|
|
|
# Test Flatten compatibility (start_dim/end_dim -> start_axis/stop_axis)
|
|
class TestFlattenAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3, 4, 5).astype("float32")
|
|
self.shape = (2, 3, 4, 5)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle keyword arguments
|
|
layer1 = paddle.nn.Flatten(start_axis=1, stop_axis=-1)
|
|
out1 = layer1(x)
|
|
|
|
# 2. PyTorch keyword arguments (dim aliases)
|
|
layer2 = paddle.nn.Flatten(start_dim=1, end_dim=-1)
|
|
out2 = layer2(x)
|
|
|
|
# 3. PyTorch positional arguments
|
|
layer3 = paddle.nn.Flatten(1, -1)
|
|
out3 = layer3(x)
|
|
|
|
# 4. Mixed arguments
|
|
layer4 = paddle.nn.Flatten(start_dim=1, stop_axis=-1)
|
|
out4 = layer4(x)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4]:
|
|
self.assertEqual(out.shape, [2, 60])
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype="float32")
|
|
|
|
# 1. Paddle keyword arguments
|
|
layer1 = paddle.nn.Flatten(start_axis=1, stop_axis=-1)
|
|
out1 = layer1(x)
|
|
|
|
# 2. PyTorch keyword arguments (dim aliases)
|
|
layer2 = paddle.nn.Flatten(start_dim=1, end_dim=-1)
|
|
out2 = layer2(x)
|
|
|
|
# 3. PyTorch positional arguments
|
|
layer3 = paddle.nn.Flatten(1, -1)
|
|
out3 = layer3(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, (2, 60))
|
|
|
|
# Test L1Loss compatibility (size_average/reduce parameters)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestL1LossAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_input = np.random.rand(3, 5).astype("float32")
|
|
self.np_label = np.random.rand(3, 5).astype("float32")
|
|
self.shape = (3, 5)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
input = paddle.to_tensor(self.np_input)
|
|
label = paddle.to_tensor(self.np_label)
|
|
|
|
# 1. Paddle keyword arguments
|
|
loss1 = paddle.nn.L1Loss(reduction='mean')
|
|
out1 = loss1(input, label)
|
|
|
|
# 2. PyTorch keyword arguments (size_average, reduce)
|
|
loss2 = paddle.nn.L1Loss(size_average=True, reduce=True)
|
|
out2 = loss2(input, label)
|
|
|
|
# 3. PyTorch size_average=False
|
|
loss3 = paddle.nn.L1Loss(size_average=False, reduce=True)
|
|
out3 = loss3(input, label)
|
|
|
|
# 4. PyTorch reduce=False
|
|
loss4 = paddle.nn.L1Loss(reduce=False)
|
|
out4 = loss4(input, label)
|
|
|
|
# 5. Mixed arguments
|
|
loss5 = paddle.nn.L1Loss(size_average=True, reduction='mean')
|
|
out5 = loss5(input, label)
|
|
|
|
# Verify all outputs
|
|
self.assertEqual(out1.shape, [])
|
|
self.assertEqual(out2.shape, [])
|
|
self.assertEqual(out3.shape, [])
|
|
self.assertEqual(out4.shape, [3, 5])
|
|
self.assertEqual(out5.shape, [])
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
input = paddle.static.data(
|
|
name="input", shape=self.shape, dtype="float32"
|
|
)
|
|
label = paddle.static.data(
|
|
name="label", shape=self.shape, dtype="float32"
|
|
)
|
|
|
|
# 1. Paddle keyword arguments
|
|
loss1 = paddle.nn.L1Loss(reduction='mean')
|
|
out1 = loss1(input, label)
|
|
|
|
# 2. PyTorch keyword arguments (size_average, reduce)
|
|
loss2 = paddle.nn.L1Loss(size_average=True, reduce=True)
|
|
out2 = loss2(input, label)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"input": self.np_input, "label": self.np_label},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, ())
|
|
|
|
# Test linalg.inv compatibility (A -> x alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestLinalgInvAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 2).astype("float32")
|
|
# Make it invertible
|
|
self.np_x = (np.eye(2) + 0.1 * self.np_x).astype("float32")
|
|
self.shape = [2, 2]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.inv(x)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.inv(x=x)
|
|
|
|
# 3. PyTorch keyword arguments (A alias)
|
|
out3 = paddle.linalg.inv(A=x)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.linalg.inv(x, name=None)
|
|
|
|
# 5. out parameter test
|
|
out5 = paddle.empty_like(x)
|
|
paddle.linalg.inv(x, out=out5)
|
|
|
|
# 6. Tensor method - args
|
|
out6 = x.inverse()
|
|
|
|
# 7. Alias paddle.inverse
|
|
out7 = paddle.inverse(A=x)
|
|
|
|
# Verify all outputs
|
|
expected = np.linalg.inv(self.np_x)
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.inv(x)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.inv(x=x)
|
|
# 3. PyTorch keyword arguments (A alias)
|
|
out3 = paddle.linalg.inv(A=x)
|
|
# 4. Tensor method - args
|
|
out4 = x.inverse()
|
|
# 5. Alias paddle.inverse
|
|
out5 = paddle.inverse(A=x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3, out4, out5],
|
|
)
|
|
|
|
expected = np.linalg.inv(self.np_x)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test det compatibility (paddle.det alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestDetAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 2).astype("float32")
|
|
self.shape = [2, 2]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.det(x)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.det(x=x)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.linalg.det(input=x)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.linalg.det(x, name=None)
|
|
|
|
# 5. Tensor method - args
|
|
out5 = x.det()
|
|
|
|
# Verify all outputs
|
|
expected = np.linalg.det(self.np_x)
|
|
for out in [out1, out2, out3, out4, out5]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.det(x)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.linalg.det(x=x)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.linalg.det(input=x)
|
|
# 4. Tensor method - args
|
|
out4 = x.det()
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3, out4],
|
|
)
|
|
|
|
expected = np.linalg.det(self.np_x)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test pinverse compatibility (paddle.pinverse alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestPinverseAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(3, 2).astype("float32")
|
|
self.shape = [3, 2]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. paddle.pinverse positional
|
|
out1 = paddle.pinverse(x)
|
|
|
|
# 2. paddle.pinverse keyword
|
|
out2 = paddle.pinverse(x=x)
|
|
|
|
# 3. paddle.pinverse with input alias
|
|
out3 = paddle.pinverse(input=x)
|
|
|
|
# 4. out parameter test
|
|
out4 = paddle.empty([2, 3], dtype='float32')
|
|
paddle.pinverse(x, out=out4)
|
|
|
|
# 5. atol parameter test (keyword-only)
|
|
out5 = paddle.pinverse(x, atol=1e-10)
|
|
|
|
# 6. rtol parameter test (keyword-only)
|
|
out6 = paddle.pinverse(x, rtol=1e-10)
|
|
|
|
# 7. atol and rtol combined (keyword-only)
|
|
out7 = paddle.pinverse(x, atol=1e-10, rtol=1e-10)
|
|
|
|
# 8. Tensor method - args
|
|
out8 = x.pinverse()
|
|
|
|
# 9. hermitian=True with atol (need square matrix for hermitian)
|
|
x_sq = paddle.to_tensor(np.random.rand(3, 3).astype("float32"))
|
|
x_sym = x_sq @ x_sq.T + paddle.eye(3) * 0.5 # full rank
|
|
out9 = paddle.pinverse(x_sym, hermitian=True, atol=1e-4)
|
|
|
|
# 10. hermitian=True with rtol
|
|
out10 = paddle.pinverse(x_sym, hermitian=True, rtol=1e-4)
|
|
|
|
# 11. hermitian=True with both atol and rtol
|
|
out11 = paddle.pinverse(x_sym, hermitian=True, atol=1e-4, rtol=1e-4)
|
|
|
|
# Verify all outputs
|
|
expected = np.linalg.pinv(self.np_x)
|
|
for out in [out1, out2, out3, out4, out5, out6, out7, out8]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
expected_sym = np.linalg.pinv(x_sym.numpy(), hermitian=True)
|
|
for out in [out9, out10, out11]:
|
|
np.testing.assert_allclose(out.numpy(), expected_sym, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. paddle.pinverse positional
|
|
out1 = paddle.pinverse(x)
|
|
# 2. paddle.pinverse keyword
|
|
out2 = paddle.pinverse(x=x)
|
|
# 3. paddle.pinverse with input alias
|
|
out3 = paddle.pinverse(input=x)
|
|
# 4. Tensor method
|
|
out4 = x.pinverse()
|
|
# 5. atol parameter test (keyword-only)
|
|
out5 = paddle.pinverse(x, atol=1e-10)
|
|
# 6. rtol parameter test (keyword-only)
|
|
out6 = paddle.pinverse(x, rtol=1e-10)
|
|
# 7. atol and rtol combined (keyword-only)
|
|
out7 = paddle.pinverse(x, atol=1e-10, rtol=1e-10)
|
|
# 8. out parameter test
|
|
out8 = paddle.static.data(
|
|
name="out8", shape=[2, 3], dtype="float32"
|
|
)
|
|
paddle.pinverse(x, out=out8)
|
|
|
|
# 9. hermitian=True with atol (square matrix)
|
|
x_sym = paddle.static.data(
|
|
name="x_sym", shape=[3, 3], dtype="float32"
|
|
)
|
|
out9 = paddle.pinverse(x_sym, hermitian=True, atol=1e-4)
|
|
|
|
# 10. hermitian=True with rtol
|
|
out10 = paddle.pinverse(x_sym, hermitian=True, rtol=1e-4)
|
|
|
|
# 11. hermitian=True with both atol and rtol
|
|
out11 = paddle.pinverse(x_sym, hermitian=True, atol=1e-4, rtol=1e-4)
|
|
|
|
exe = paddle.static.Executor()
|
|
np_x_sym = (
|
|
self.np_x @ self.np_x.T
|
|
+ np.eye(3, dtype=self.dtype) * 0.5 # full rank
|
|
)
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"out8": np.empty([2, 3], dtype="float32"),
|
|
"x_sym": np_x_sym,
|
|
},
|
|
fetch_list=[
|
|
out1,
|
|
out2,
|
|
out3,
|
|
out4,
|
|
out5,
|
|
out6,
|
|
out7,
|
|
out8,
|
|
out9,
|
|
out10,
|
|
out11,
|
|
],
|
|
)
|
|
|
|
expected = np.linalg.pinv(self.np_x)
|
|
for out in fetches[:8]:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
expected_sym = np.linalg.pinv(np_x_sym, hermitian=True)
|
|
for out in fetches[8:]:
|
|
np.testing.assert_allclose(out, expected_sym, rtol=1e-5)
|
|
|
|
# Test addcdiv_ compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestAddcdiv_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, 2.0, 3.0]).astype("float32")
|
|
self.np_t1 = np.array([4.0, 5.0, 6.0]).astype("float32")
|
|
self.np_t2 = np.array([2.0, 2.0, 2.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
t1 = paddle.to_tensor(self.np_t1)
|
|
t2 = paddle.to_tensor(self.np_t2)
|
|
|
|
# 1. Paddle Positional arguments
|
|
x1 = paddle.to_tensor(self.np_x.copy())
|
|
out1 = paddle.addcdiv(x1, t1, t2, 1.0)
|
|
|
|
# 2. Paddle keyword arguments
|
|
x2 = paddle.to_tensor(self.np_x.copy())
|
|
out2 = paddle.addcdiv(input=x2, tensor1=t1, tensor2=t2, value=1.0)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
out3 = paddle.addcdiv(input=x3, tensor1=t1, tensor2=t2, value=1.0)
|
|
|
|
# 4. Mixed arguments
|
|
x4 = paddle.to_tensor(self.np_x.copy())
|
|
out4 = paddle.addcdiv(x4, t1, tensor2=t2, value=1.0)
|
|
|
|
# 5. out parameter test
|
|
x5 = paddle.to_tensor(self.np_x.copy())
|
|
out5 = paddle.empty_like(x5)
|
|
paddle.addcdiv(x5, t1, t2, value=1.0, out=out5)
|
|
|
|
# 6. Tensor method - args
|
|
x6 = paddle.to_tensor(self.np_x.copy())
|
|
out6 = x6.addcdiv_(t1, t2, value=1.0)
|
|
|
|
# 7. Tensor method - kwargs
|
|
x7 = paddle.to_tensor(self.np_x.copy())
|
|
out7 = x7.addcdiv_(tensor1=t1, tensor2=t2, value=1.0)
|
|
|
|
# Verify all outputs
|
|
expected = self.np_x + 1.0 * (self.np_t1 / self.np_t2)
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
|
|
# Test imag compatibility (compat function)
|
|
class TestImagAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array(
|
|
[[1 + 6j, 2 + 5j], [3 + 4j, 5 + 2j]], dtype='complex64'
|
|
)
|
|
self.shape = [2, 2]
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. paddle.imag positional
|
|
out1 = paddle.imag(x)
|
|
|
|
# 2. paddle.imag keyword
|
|
out2 = paddle.imag(x=x)
|
|
|
|
# 3. paddle.imag with input alias
|
|
out3 = paddle.imag(input=x)
|
|
|
|
# Verify outputs
|
|
for out in [out1, out2, out3]:
|
|
self.assertEqual(out.dtype, paddle.float32)
|
|
np.testing.assert_allclose(out.numpy(), self.np_x.imag)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=self.shape, dtype="complex64"
|
|
)
|
|
|
|
# 1. paddle.imag positional
|
|
out1 = paddle.imag(x)
|
|
# 2. paddle.imag keyword
|
|
out2 = paddle.imag(x=x)
|
|
# 3. paddle.imag with input alias
|
|
out3 = paddle.imag(input=x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, self.np_x.imag)
|
|
|
|
# Test real compatibility (compat function)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestRealAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array(
|
|
[[1 + 6j, 2 + 5j], [3 + 4j, 5 + 2j]], dtype='complex64'
|
|
)
|
|
self.shape = [2, 2]
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. paddle.real positional
|
|
out1 = paddle.real(x)
|
|
|
|
# 2. paddle.real keyword
|
|
out2 = paddle.real(x=x)
|
|
|
|
# 3. paddle.real with input alias
|
|
out3 = paddle.real(input=x)
|
|
# Verify outputs
|
|
for out in [out1, out2, out3]:
|
|
np.testing.assert_allclose(out.numpy(), self.np_x.real)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=self.shape, dtype="complex64"
|
|
)
|
|
|
|
# 1. paddle.real positional
|
|
out1 = paddle.real(x)
|
|
# 2. paddle.real keyword
|
|
out2 = paddle.real(x=x)
|
|
# 3. paddle.real with input alias
|
|
out3 = paddle.real(input=x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, self.np_x.real)
|
|
|
|
# Test nan_to_num compatibility (PyTorch parameter alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestNanToNumAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([np.nan, 0.3, np.inf, -np.inf], dtype="float32")
|
|
self.shape = [4]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.nan_to_num(x, 0.0)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nan_to_num(x=x, nan=0.0)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.nan_to_num(input=x, nan=0.0)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.nan_to_num(x, nan=0.0, posinf=None)
|
|
|
|
# 5. out parameter test
|
|
out5 = paddle.empty_like(out1)
|
|
paddle.nan_to_num(x, nan=0.0, out=out5)
|
|
|
|
# 6. Tensor method - args
|
|
out6 = x.nan_to_num(0.0)
|
|
|
|
# 7. Tensor method - kwargs
|
|
out7 = x.nan_to_num(nan=0.0)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
np.testing.assert_allclose(out.numpy(), out1.numpy())
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.nan_to_num(x, 0.0)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nan_to_num(x=x, nan=0.0)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.nan_to_num(input=x, nan=0.0)
|
|
# 4. Tensor method - args
|
|
out4 = x.nan_to_num(0.0)
|
|
# 5. Tensor method - kwargs
|
|
out5 = x.nan_to_num(nan=0.0)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2, out3, out4, out5],
|
|
)
|
|
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, fetches[0])
|
|
|
|
# Test randint_like compatibility (PyTorch parameter alias and new params)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestRandintLikeAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.shape = [2, 3]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.zeros(self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.randint_like(x, 0, 10)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.randint_like(x=x, low=0, high=10)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.randint_like(input=x, low=0, high=10)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.randint_like(x, high=10)
|
|
|
|
# 5. pin_memory parameter (keyword-only)
|
|
out5 = paddle.randint_like(x, 0, 10, pin_memory=False)
|
|
|
|
# 6. requires_grad parameter (keyword-only)
|
|
out6 = paddle.randint_like(x, 0, 10, requires_grad=False)
|
|
|
|
# 7. Both pin_memory and requires_grad (keyword-only)
|
|
out7 = paddle.randint_like(
|
|
x, 0, 10, pin_memory=False, requires_grad=False
|
|
)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
self.assertEqual(out.shape, x.shape)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.randint_like(x, 0, 10)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.randint_like(x=x, low=0, high=10)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.randint_like(input=x, low=0, high=10)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": np.zeros(self.shape, dtype=self.dtype)},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, tuple(self.shape))
|
|
|
|
# Test resize_as_ compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestResizeAsAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3).astype("float32")
|
|
self.np_y = np.random.rand(4, 5).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
y = paddle.to_tensor(self.np_y)
|
|
|
|
# 1. Paddle Positional arguments
|
|
x1 = paddle.to_tensor(self.np_x)
|
|
out1 = paddle.resize_as_(x1, y)
|
|
|
|
# 2. Paddle keyword arguments
|
|
x2 = paddle.to_tensor(self.np_x)
|
|
out2 = paddle.resize_as_(x=x2, y=y)
|
|
|
|
# 3. Mixed arguments
|
|
x3 = paddle.to_tensor(self.np_x)
|
|
out3 = paddle.resize_as_(x3, y=y)
|
|
|
|
# 4. Tensor method - args
|
|
x4 = paddle.to_tensor(self.np_x)
|
|
out4 = x4.resize_as_(y)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4]:
|
|
self.assertEqual(out.shape, y.shape)
|
|
|
|
|
|
# Test huber_loss compatibility (alias for smooth_l1_loss)
|
|
class TestHuberLossAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.input = np.random.rand(3, 5).astype("float32")
|
|
self.target = np.random.rand(3, 5).astype("float32")
|
|
self.shape = (3, 5)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
input = paddle.to_tensor(self.input)
|
|
target = paddle.to_tensor(self.target)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.nn.functional.huber_loss(input, target)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.huber_loss(input=input, label=target)
|
|
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.huber_loss(input=input, target=target)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.nn.functional.huber_loss(input, target=target, delta=1.0)
|
|
|
|
# 5. smooth_l1_loss should be equivalent
|
|
out5 = paddle.nn.functional.smooth_l1_loss(input, target)
|
|
|
|
# Verify outputs are equivalent
|
|
np.testing.assert_allclose(out1.numpy(), out2.numpy())
|
|
np.testing.assert_allclose(out1.numpy(), out3.numpy())
|
|
np.testing.assert_allclose(out1.numpy(), out4.numpy())
|
|
np.testing.assert_allclose(out1.numpy(), out5.numpy())
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
input = paddle.static.data(
|
|
name="input", shape=self.shape, dtype="float32"
|
|
)
|
|
target = paddle.static.data(
|
|
name="target", shape=self.shape, dtype="float32"
|
|
)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.huber_loss(
|
|
input, target, reduction='none'
|
|
)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.huber_loss(
|
|
input=input, label=target, reduction='none'
|
|
)
|
|
# 3. PyTorch keyword arguments (target alias)
|
|
out3 = paddle.nn.functional.huber_loss(
|
|
input=input, target=target, reduction='none'
|
|
)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"input": self.input, "target": self.target},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, (3, 5))
|
|
|
|
# Test fmod compatibility (alias for remainder/mod)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestFmodAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([5.0, 7.0, 9.0], dtype="float32")
|
|
self.np_y = np.array([2.0, 3.0, 4.0], dtype="float32")
|
|
self.shape = [3]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
y = paddle.to_tensor(self.np_y)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.fmod(x, y)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.fmod(x=x, y=y)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.fmod(input=x, other=y)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.fmod(x, other=y)
|
|
|
|
# 5. out parameter test
|
|
out5 = paddle.empty_like(x)
|
|
paddle.fmod(x, y, out=out5)
|
|
|
|
# 6. Tensor method - args
|
|
out6 = x.fmod(y)
|
|
|
|
# 7. Tensor method - kwargs
|
|
out7 = x.fmod(other=y)
|
|
|
|
# Verify all outputs
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
np.testing.assert_allclose(out.numpy(), out1.numpy())
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
y = paddle.static.data(name="y", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.fmod(x, y)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.fmod(x=x, y=y)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.fmod(input=x, other=y)
|
|
# 4. Tensor method - args
|
|
out4 = x.fmod(y)
|
|
# 5. Tensor method - kwargs
|
|
out5 = x.fmod(other=y)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x, "y": self.np_y},
|
|
fetch_list=[out1, out2, out3, out4, out5],
|
|
)
|
|
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, fetches[0])
|
|
|
|
# Test absolute compatibility (alias for abs)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestAbsoluteAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([-1.0, 2.0, -3.0], dtype="float32")
|
|
self.shape = [3]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.absolute(x)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.absolute(x=x)
|
|
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.absolute(input=x)
|
|
|
|
# 4. Mixed arguments
|
|
out4 = paddle.absolute(x, name=None)
|
|
|
|
# 5. out parameter test
|
|
out5 = paddle.empty_like(x)
|
|
paddle.absolute(x, out=out5)
|
|
|
|
# 6. Tensor method - args
|
|
out6 = x.absolute()
|
|
|
|
# 7. Alias paddle.abs
|
|
out7 = paddle.abs(x)
|
|
|
|
# Verify all outputs
|
|
expected = np.abs(self.np_x)
|
|
for out in [out1, out2, out3, out4, out5, out6, out7]:
|
|
np.testing.assert_allclose(out.numpy(), expected)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=self.shape, dtype=self.dtype)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.absolute(x)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.absolute(x=x)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.absolute(input=x)
|
|
# 4. Alias paddle.abs
|
|
out4 = paddle.abs(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main, feed={"x": self.np_x}, fetch_list=[out1, out2, out3, out4]
|
|
)
|
|
|
|
expected = np.abs(self.np_x)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected)
|
|
|
|
# Test assert_allclose compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestAssertAllcloseAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
y = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
|
|
# 1. Should not raise
|
|
paddle.testing.assert_allclose(x, y)
|
|
|
|
# 2. With tolerances
|
|
paddle.testing.assert_allclose(x, y, rtol=1e-5, atol=1e-8)
|
|
|
|
# 4. Non-Tensor inputs (isinstance branches)
|
|
paddle.testing.assert_allclose(
|
|
paddle.to_tensor([1.0, 2.0, 3.0]).numpy(), # actual is ndarray
|
|
paddle.to_tensor([1.0, 2.0, 3.0]).numpy(), # expected is ndarray
|
|
)
|
|
|
|
# 5. Non-Tensor actual with list
|
|
paddle.testing.assert_allclose(
|
|
[1.0, 2.0, 3.0], paddle.to_tensor([1.0, 2.0, 3.0])
|
|
)
|
|
|
|
# 6. Non-Tensor expected with list
|
|
paddle.testing.assert_allclose(
|
|
paddle.to_tensor([1.0, 2.0, 3.0]), [1.0, 2.0, 3.0]
|
|
)
|
|
|
|
# 3. Should raise on mismatch
|
|
z = paddle.to_tensor([1.0, 2.0, 4.0])
|
|
with self.assertRaises(AssertionError):
|
|
paddle.testing.assert_allclose(x, z)
|
|
|
|
|
|
# Test GRU compatibility
|
|
class TestGRUAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.input_size = 16
|
|
self.hidden_size = 32
|
|
self.num_layers = 2
|
|
self.batch_size = 4
|
|
self.seq_len = 23
|
|
self.shape_x = [self.batch_size, self.seq_len, self.input_size]
|
|
self.shape_h = [self.num_layers, self.batch_size, self.hidden_size]
|
|
self.dtype = "float32"
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
np.random.seed(2025)
|
|
np_x = np.random.randn(*self.shape_x).astype(self.dtype)
|
|
np_h = np.random.randn(*self.shape_h).astype(self.dtype)
|
|
x = paddle.to_tensor(np_x)
|
|
prev_h = paddle.to_tensor(np_h)
|
|
|
|
# --- Forward, with bias (num_layers=self.num_layers) ---
|
|
ref = paddle.nn.GRU(self.input_size, self.hidden_size, self.num_layers)
|
|
ref_sd = ref.state_dict()
|
|
ref_y, ref_h = ref(x, prev_h)
|
|
|
|
# 1. Paddle positional arguments
|
|
rnn1 = paddle.nn.GRU(self.input_size, self.hidden_size, self.num_layers)
|
|
rnn1.set_state_dict(ref_sd)
|
|
y1, h1 = rnn1(x, prev_h)
|
|
np.testing.assert_allclose(y1.numpy(), ref_y.numpy(), rtol=1e-5)
|
|
np.testing.assert_allclose(h1.numpy(), ref_h.numpy(), rtol=1e-5)
|
|
|
|
# 2. Paddle keyword arguments
|
|
rnn2 = paddle.nn.GRU(
|
|
input_size=self.input_size,
|
|
hidden_size=self.hidden_size,
|
|
num_layers=self.num_layers,
|
|
)
|
|
rnn2.set_state_dict(ref_sd)
|
|
y2, h2 = rnn2(x, prev_h)
|
|
np.testing.assert_allclose(y2.numpy(), ref_y.numpy(), rtol=1e-5)
|
|
np.testing.assert_allclose(h2.numpy(), ref_h.numpy(), rtol=1e-5)
|
|
|
|
# 3. PyTorch positional arguments (bias=True at 4th position)
|
|
rnn3 = paddle.nn.GRU(
|
|
self.input_size, self.hidden_size, self.num_layers, True
|
|
)
|
|
rnn3.set_state_dict(ref_sd)
|
|
y3, h3 = rnn3(x, prev_h)
|
|
np.testing.assert_allclose(y3.numpy(), ref_y.numpy(), rtol=1e-5)
|
|
np.testing.assert_allclose(h3.numpy(), ref_h.numpy(), rtol=1e-5)
|
|
|
|
# 4. PyTorch keyword arguments (bias, batch_first, bidirectional)
|
|
rnn4 = paddle.nn.GRU(
|
|
self.input_size,
|
|
self.hidden_size,
|
|
num_layers=self.num_layers,
|
|
bias=True,
|
|
batch_first=True,
|
|
bidirectional=False,
|
|
)
|
|
rnn4.set_state_dict(ref_sd)
|
|
y4, h4 = rnn4(x, prev_h)
|
|
np.testing.assert_allclose(y4.numpy(), ref_y.numpy(), rtol=1e-5)
|
|
np.testing.assert_allclose(h4.numpy(), ref_h.numpy(), rtol=1e-5)
|
|
|
|
# --- bias=False ---
|
|
ref_nb = paddle.nn.GRU(
|
|
self.input_size,
|
|
self.hidden_size,
|
|
self.num_layers,
|
|
bias_ih_attr=False,
|
|
bias_hh_attr=False,
|
|
)
|
|
ref_nb_sd = ref_nb.state_dict()
|
|
ref_y_nb, ref_h_nb = ref_nb(x, prev_h)
|
|
|
|
# 5. bias parameter test (bias=False)
|
|
rnn5 = paddle.nn.GRU(
|
|
self.input_size, self.hidden_size, self.num_layers, bias=False
|
|
)
|
|
rnn5.set_state_dict(ref_nb_sd)
|
|
y5, h5 = rnn5(x, prev_h)
|
|
np.testing.assert_allclose(y5.numpy(), ref_y_nb.numpy(), rtol=1e-5)
|
|
np.testing.assert_allclose(h5.numpy(), ref_h_nb.numpy(), rtol=1e-5)
|
|
|
|
# 6. device parameter test (constructor only)
|
|
paddle.nn.GRU(self.input_size, self.hidden_size, device="cpu")
|
|
|
|
# 7. dtype parameter test (constructor only)
|
|
paddle.nn.GRU(self.input_size, self.hidden_size, dtype="float32")
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x",
|
|
shape=self.shape_x,
|
|
dtype=self.dtype,
|
|
)
|
|
prev_h = paddle.static.data(
|
|
name="prev_h",
|
|
shape=self.shape_h,
|
|
dtype=self.dtype,
|
|
)
|
|
|
|
# 1. Paddle positional arguments
|
|
rnn1 = paddle.nn.GRU(
|
|
self.input_size, self.hidden_size, self.num_layers
|
|
)
|
|
y1, h1 = rnn1(x, prev_h)
|
|
|
|
# 2. PyTorch keyword arguments (bias, batch_first, bidirectional)
|
|
rnn2 = paddle.nn.GRU(
|
|
self.input_size,
|
|
self.hidden_size,
|
|
num_layers=self.num_layers,
|
|
bias=True,
|
|
batch_first=True,
|
|
bidirectional=False,
|
|
)
|
|
y2, h2 = rnn2(x, prev_h)
|
|
|
|
exe = paddle.static.Executor()
|
|
exe.run(startup)
|
|
# Just verify it runs in static mode
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": np.random.randn(*self.shape_x).astype(self.dtype),
|
|
"prev_h": np.random.randn(*self.shape_h).astype(self.dtype),
|
|
},
|
|
fetch_list=[y1, h1, y2, h2],
|
|
)
|
|
|
|
self.assertEqual(
|
|
fetches[0].shape,
|
|
(self.batch_size, self.seq_len, self.hidden_size),
|
|
)
|
|
|
|
# Test set_default_tensor_type compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestSetDefaultTensorTypeAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Save original dtype
|
|
original_dtype = paddle.get_default_dtype()
|
|
|
|
# ========== float32 tests ==========
|
|
paddle.set_default_tensor_type(paddle.FloatTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
paddle.set_default_tensor_type(paddle.cuda.FloatTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
|
|
paddle.set_default_tensor_type("paddle.FloatTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
paddle.set_default_tensor_type("paddle.cuda.FloatTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
|
|
paddle.set_default_tensor_type("torch.FloatTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
paddle.set_default_tensor_type("torch.cuda.FloatTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float32")
|
|
|
|
# ========== float64 tests ==========
|
|
paddle.set_default_tensor_type(paddle.DoubleTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
paddle.set_default_tensor_type(paddle.cuda.DoubleTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
|
|
paddle.set_default_tensor_type("paddle.DoubleTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
paddle.set_default_tensor_type("paddle.cuda.DoubleTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
|
|
paddle.set_default_tensor_type("torch.DoubleTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
paddle.set_default_tensor_type("torch.cuda.DoubleTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float64")
|
|
|
|
# ========== float16 tests (10 formats) ==========
|
|
paddle.set_default_tensor_type(paddle.HalfTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
paddle.set_default_tensor_type(paddle.cuda.HalfTensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
|
|
paddle.set_default_tensor_type("paddle.HalfTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
paddle.set_default_tensor_type("paddle.cuda.HalfTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
|
|
paddle.set_default_tensor_type("torch.HalfTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
paddle.set_default_tensor_type("torch.cuda.HalfTensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "float16")
|
|
|
|
# ========== bfloat16 tests (10 formats) ==========
|
|
paddle.set_default_tensor_type(paddle.BFloat16Tensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
paddle.set_default_tensor_type(paddle.cuda.BFloat16Tensor)
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
|
|
paddle.set_default_tensor_type("paddle.BFloat16Tensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
paddle.set_default_tensor_type("paddle.cuda.BFloat16Tensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
|
|
paddle.set_default_tensor_type("torch.BFloat16Tensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
paddle.set_default_tensor_type("torch.cuda.BFloat16Tensor")
|
|
self.assertEqual(paddle.get_default_dtype(), "bfloat16")
|
|
|
|
# ========== TypeError branches ==========
|
|
# Invalid tensor type name (not in dtype_map)
|
|
with self.assertRaises(TypeError):
|
|
paddle.set_default_tensor_type("torch.IntTensor")
|
|
|
|
# Passing dtype instead of tensor type
|
|
with self.assertRaises(TypeError):
|
|
paddle.set_default_tensor_type(paddle.float32)
|
|
|
|
# Restore original dtype
|
|
paddle.set_default_dtype(original_dtype)
|
|
|
|
|
|
# Test PackedSequence compatibility
|
|
class TestPackedSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.data = np.random.rand(10, 5).astype("float32")
|
|
self.batch_sizes = np.array([3, 3, 2, 1, 1], dtype="int64")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Create PackedSequence with positional arguments
|
|
data_tensor = paddle.to_tensor(self.data)
|
|
batch_sizes_tensor = paddle.to_tensor(self.batch_sizes)
|
|
packed1 = paddle.nn.utils.rnn.PackedSequence(
|
|
data_tensor, batch_sizes_tensor
|
|
)
|
|
|
|
# 2. Create PackedSequence with keyword arguments
|
|
packed2 = paddle.nn.utils.rnn.PackedSequence(
|
|
data=data_tensor, batch_sizes=batch_sizes_tensor
|
|
)
|
|
|
|
# 3. Create PackedSequence with sorted_indices
|
|
sorted_indices = paddle.to_tensor([2, 0, 1], dtype="int64")
|
|
packed3 = paddle.nn.utils.rnn.PackedSequence(
|
|
data_tensor, batch_sizes_tensor, sorted_indices=sorted_indices
|
|
)
|
|
|
|
# 4. Create PackedSequence with all parameters
|
|
unsorted_indices = paddle.to_tensor([1, 2, 0], dtype="int64")
|
|
packed4 = paddle.nn.utils.rnn.PackedSequence(
|
|
data=data_tensor,
|
|
batch_sizes=batch_sizes_tensor,
|
|
sorted_indices=sorted_indices,
|
|
unsorted_indices=unsorted_indices,
|
|
)
|
|
|
|
# Verify all instances
|
|
for packed in [packed1, packed2, packed3, packed4]:
|
|
self.assertEqual(packed.data.shape, [10, 5])
|
|
self.assertEqual(packed.batch_sizes.shape, [5])
|
|
np.testing.assert_allclose(packed.data.numpy(), self.data)
|
|
np.testing.assert_array_equal(
|
|
packed.batch_sizes.numpy(), self.batch_sizes
|
|
)
|
|
|
|
# Verify sorted_indices and unsorted_indices
|
|
np.testing.assert_array_equal(packed3.sorted_indices.numpy(), [2, 0, 1])
|
|
np.testing.assert_array_equal(packed4.sorted_indices.numpy(), [2, 0, 1])
|
|
np.testing.assert_array_equal(
|
|
packed4.unsorted_indices.numpy(), [1, 2, 0]
|
|
)
|
|
|
|
# 5. Test properties
|
|
# Note: is_cuda returns True if data is on GPU, False on CPU
|
|
# Since the test may run on GPU or CPU, we just check it's a boolean
|
|
self.assertIsInstance(packed1.is_cuda, bool)
|
|
self.assertIsInstance(packed1.is_pinned, bool)
|
|
|
|
# 6. Test to() method
|
|
# When called with dtype change, data dtype changes but indices stay int64
|
|
packed_dtype = packed4.to(dtype=paddle.float64)
|
|
self.assertEqual(packed_dtype.data.dtype, paddle.float64)
|
|
self.assertEqual(packed_dtype.sorted_indices.dtype, paddle.int64)
|
|
self.assertEqual(packed_dtype.unsorted_indices.dtype, paddle.int64)
|
|
self.assertEqual(packed_dtype.unsorted_indices.dtype, paddle.int64)
|
|
|
|
# 7. Test dtype conversion methods
|
|
packed_double = packed1.double()
|
|
self.assertEqual(packed_double.data.dtype, paddle.float64)
|
|
|
|
packed_float = packed1.float()
|
|
self.assertEqual(packed_float.data.dtype, paddle.float32)
|
|
|
|
packed_half = packed1.half()
|
|
self.assertEqual(packed_half.data.dtype, paddle.float16)
|
|
|
|
packed_long = packed1.long()
|
|
self.assertEqual(packed_long.data.dtype, paddle.int64)
|
|
|
|
packed_int = packed1.int()
|
|
self.assertEqual(packed_int.data.dtype, paddle.int32)
|
|
|
|
packed_short = packed1.short()
|
|
self.assertEqual(packed_short.data.dtype, paddle.int16)
|
|
|
|
packed_char = packed1.char()
|
|
self.assertEqual(packed_char.data.dtype, paddle.int8)
|
|
|
|
packed_byte = packed1.byte()
|
|
self.assertEqual(packed_byte.data.dtype, paddle.uint8)
|
|
|
|
# 8. Test pin_memory
|
|
if paddle.is_compiled_with_cuda():
|
|
packed_pinned = packed1.pin_memory()
|
|
self.assertIsInstance(
|
|
packed_pinned, paddle.nn.utils.rnn.PackedSequence
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
data = paddle.static.data(
|
|
name="data", shape=[10, 5], dtype="float32"
|
|
)
|
|
batch_sizes = paddle.static.data(
|
|
name="batch_sizes", shape=[5], dtype="int64"
|
|
)
|
|
|
|
# 1. Create PackedSequence with positional arguments
|
|
packed1 = paddle.nn.utils.rnn.PackedSequence(data, batch_sizes)
|
|
|
|
# 2. Create PackedSequence with keyword arguments
|
|
packed2 = paddle.nn.utils.rnn.PackedSequence(
|
|
data=data, batch_sizes=batch_sizes
|
|
)
|
|
|
|
# Verify Variables are preserved
|
|
self.assertEqual(packed1.data.name, data.name)
|
|
self.assertEqual(packed1.batch_sizes.name, batch_sizes.name)
|
|
self.assertEqual(packed2.data.name, data.name)
|
|
self.assertEqual(packed2.batch_sizes.name, batch_sizes.name)
|
|
|
|
# Test invert_permutation compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestInvertPermutationAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Basic test with positional argument
|
|
perm = paddle.to_tensor([2, 0, 1], dtype="int64")
|
|
inv_perm1 = paddle.nn.utils.rnn.invert_permutation(perm)
|
|
np.testing.assert_array_equal(inv_perm1.numpy(), [1, 2, 0])
|
|
|
|
# 2. Test with keyword argument
|
|
inv_perm2 = paddle.nn.utils.rnn.invert_permutation(permutation=perm)
|
|
np.testing.assert_array_equal(inv_perm2.numpy(), [1, 2, 0])
|
|
|
|
# 3. Test with None input
|
|
result = paddle.nn.utils.rnn.invert_permutation(None)
|
|
self.assertIsNone(result)
|
|
|
|
# 4. Test with different permutation
|
|
perm2 = paddle.to_tensor([0, 1, 2, 3], dtype="int64")
|
|
inv_perm3 = paddle.nn.utils.rnn.invert_permutation(perm2)
|
|
np.testing.assert_array_equal(inv_perm3.numpy(), [0, 1, 2, 3])
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
perm = paddle.static.data(name="perm", shape=[3], dtype="int64")
|
|
inv_perm1 = paddle.nn.utils.rnn.invert_permutation(perm)
|
|
inv_perm2 = paddle.nn.utils.rnn.invert_permutation(permutation=perm)
|
|
|
|
exe = paddle.static.Executor()
|
|
exe.run(startup)
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"perm": np.array([2, 0, 1], dtype="int64")},
|
|
fetch_list=[inv_perm1, inv_perm2],
|
|
)
|
|
|
|
for out in fetches:
|
|
np.testing.assert_array_equal(out, [1, 2, 0])
|
|
|
|
# Test pack_padded_sequence compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestPackPaddedSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_seq = np.random.rand(5, 3, 10).astype("float32")
|
|
self.lengths = [5, 3, 2]
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
seq = paddle.to_tensor(self.np_seq)
|
|
|
|
# 1. Paddle Positional arguments
|
|
packed1 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq, paddle.to_tensor(self.lengths)
|
|
)
|
|
|
|
# 2. Paddle keyword arguments
|
|
packed2 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
input=seq, lengths=paddle.to_tensor(self.lengths)
|
|
)
|
|
|
|
# 3. PyTorch keyword arguments (batch_first=False)
|
|
packed3 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
input=seq, lengths=self.lengths, batch_first=False
|
|
)
|
|
|
|
# 4. With batch_first=True
|
|
seq_batch_first = seq.transpose([1, 0, 2])
|
|
packed4 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq_batch_first, self.lengths, batch_first=True
|
|
)
|
|
|
|
# 5. With enforce_sorted=False
|
|
packed5 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq, self.lengths, enforce_sorted=False
|
|
)
|
|
|
|
# 6. With enforce_sorted=False (complex case)
|
|
seq_unsorted = paddle.to_tensor(
|
|
[[1, 2, 0], [3, 0, 0], [4, 5, 6]], dtype='float32'
|
|
)
|
|
packed6 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq_unsorted, [2, 1, 3], batch_first=True, enforce_sorted=False
|
|
)
|
|
|
|
# 7. Mixed arguments (positional + keyword)
|
|
packed7 = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq, enforce_sorted=True, lengths=paddle.to_tensor(self.lengths)
|
|
)
|
|
|
|
# Verify all outputs
|
|
for packed in [packed1, packed2, packed3, packed5, packed7]:
|
|
self.assertIsInstance(packed, paddle.nn.utils.rnn.PackedSequence)
|
|
self.assertTrue(hasattr(packed, 'data'))
|
|
self.assertTrue(hasattr(packed, 'batch_sizes'))
|
|
# All these should be identical
|
|
np.testing.assert_allclose(
|
|
packed.data.numpy(), packed1.data.numpy()
|
|
)
|
|
np.testing.assert_array_equal(
|
|
packed.batch_sizes.numpy(), packed1.batch_sizes.numpy()
|
|
)
|
|
|
|
# packed4 (batch_first=True) should be same as packed1
|
|
np.testing.assert_allclose(packed4.data.numpy(), packed1.data.numpy())
|
|
np.testing.assert_array_equal(
|
|
packed4.batch_sizes.numpy(), packed1.batch_sizes.numpy()
|
|
)
|
|
|
|
# Verify unsorted case
|
|
self.assertIsNotNone(packed6.sorted_indices)
|
|
self.assertIsNotNone(packed6.unsorted_indices)
|
|
# Verify packed6 data (manual check for small unsorted case)
|
|
# seq_unsorted = [[1, 2, 0], [3, 0, 0], [4, 5, 6]], lengths = [2, 1, 3]
|
|
# sorted by lengths: [4, 5, 6] (3), [1, 2, 0] (2), [3, 0, 0] (1)
|
|
# packed: [4, 1, 3, 5, 2, 6]
|
|
expected_data = [4, 1, 3, 5, 2, 6]
|
|
expected_batch_sizes = [3, 2, 1]
|
|
np.testing.assert_array_equal(
|
|
packed6.data.numpy().flatten(), expected_data
|
|
)
|
|
np.testing.assert_array_equal(
|
|
packed6.batch_sizes.numpy(), expected_batch_sizes
|
|
)
|
|
|
|
|
|
# Test pad_packed_sequence compatibility
|
|
class TestPadPackedSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_seq = np.random.rand(5, 3, 10).astype("float32")
|
|
self.lengths = [5, 3, 2]
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
seq = paddle.to_tensor(self.np_seq)
|
|
lengths_tensor = paddle.to_tensor(self.lengths)
|
|
|
|
# Create packed sequence
|
|
packed = paddle.nn.utils.rnn.pack_padded_sequence(seq, lengths_tensor)
|
|
|
|
# 1. Paddle Positional arguments
|
|
padded1, lengths1 = paddle.nn.utils.rnn.pad_packed_sequence(packed)
|
|
|
|
# 2. Paddle keyword arguments
|
|
padded2, lengths2 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
sequence=packed
|
|
)
|
|
|
|
# 3. With batch_first=True
|
|
packed_bf = paddle.nn.utils.rnn.pack_padded_sequence(
|
|
seq.transpose([1, 0, 2]), lengths_tensor, batch_first=True
|
|
)
|
|
padded3, lengths3 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed_bf, batch_first=True
|
|
)
|
|
|
|
# 4. With padding_value
|
|
padded4, lengths4 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed, padding_value=1.0
|
|
)
|
|
|
|
# 5. With total_length
|
|
padded5, lengths5 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed, total_length=10
|
|
)
|
|
|
|
# 6. Mixed arguments (positional + keyword)
|
|
padded6, lengths6 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed, batch_first=False
|
|
)
|
|
|
|
# 7. Another padding_value test
|
|
padded7, lengths7 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed, padding_value=-1.0
|
|
)
|
|
|
|
# 8. batch_first=True on packed (which was batch_first=False)
|
|
padded8, lengths8 = paddle.nn.utils.rnn.pad_packed_sequence(
|
|
packed, batch_first=True
|
|
)
|
|
|
|
# 9. TypeError when sequence is not PackedSequence
|
|
with self.assertRaises(TypeError):
|
|
paddle.nn.utils.rnn.pad_packed_sequence("not_a_packed_sequence")
|
|
|
|
# Verify outputs numerical correctness
|
|
# For default padding (0.0)
|
|
expected_padded = self.np_seq.copy()
|
|
# For batch 0, length is 5. No padding.
|
|
# For batch 1, length is 3. Elements at time 3, 4 should be 0.
|
|
expected_padded[3:, 1, :] = 0.0
|
|
# For batch 2, length is 2. Elements at time 2, 3, 4 should be 0.
|
|
expected_padded[2:, 2, :] = 0.0
|
|
|
|
for padded, lengths in [
|
|
(padded1, lengths1),
|
|
(padded2, lengths2),
|
|
(padded6, lengths6),
|
|
]:
|
|
self.assertEqual(padded.shape, [5, 3, 10])
|
|
np.testing.assert_array_equal(lengths.numpy(), self.lengths)
|
|
np.testing.assert_allclose(padded.numpy(), expected_padded)
|
|
|
|
# For padding_value=1.0 (padded4)
|
|
expected_padded_1 = self.np_seq.copy()
|
|
expected_padded_1[3:, 1, :] = 1.0
|
|
expected_padded_1[2:, 2, :] = 1.0
|
|
np.testing.assert_allclose(padded4.numpy(), expected_padded_1)
|
|
|
|
# For padding_value=-1.0 (padded7)
|
|
expected_padded_neg1 = self.np_seq.copy()
|
|
expected_padded_neg1[3:, 1, :] = -1.0
|
|
expected_padded_neg1[2:, 2, :] = -1.0
|
|
np.testing.assert_allclose(padded7.numpy(), expected_padded_neg1)
|
|
|
|
# For batch_first=True (padded3)
|
|
expected_padded_bf = self.np_seq.transpose([1, 0, 2]).copy()
|
|
expected_padded_bf[1, 3:, :] = 0.0
|
|
expected_padded_bf[2, 2:, :] = 0.0
|
|
self.assertEqual(padded3.shape, [3, 5, 10])
|
|
np.testing.assert_allclose(padded3.numpy(), expected_padded_bf)
|
|
|
|
# For total_length=10 (padded5)
|
|
self.assertEqual(padded5.shape, [10, 3, 10])
|
|
np.testing.assert_allclose(padded5.numpy()[:5], expected_padded)
|
|
np.testing.assert_allclose(padded5.numpy()[5:], 0.0)
|
|
|
|
# For padded8 (batch_first=True on packed which was batch_first=False)
|
|
self.assertEqual(padded8.shape, [3, 5, 10])
|
|
np.testing.assert_allclose(padded8.numpy(), expected_padded_bf)
|
|
|
|
|
|
# Test pad_sequence compatibility
|
|
class TestPadSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.a = np.random.rand(25, 300).astype("float32")
|
|
self.b = np.random.rand(22, 300).astype("float32")
|
|
self.c = np.random.rand(15, 300).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
a = paddle.to_tensor(self.a)
|
|
b = paddle.to_tensor(self.b)
|
|
c = paddle.to_tensor(self.c)
|
|
sequences = [a, b, c]
|
|
|
|
# 1. Paddle Positional arguments
|
|
padded1 = paddle.nn.utils.rnn.pad_sequence(sequences)
|
|
|
|
# 2. Paddle keyword arguments
|
|
padded2 = paddle.nn.utils.rnn.pad_sequence(sequences=sequences)
|
|
|
|
# 3. PyTorch keyword arguments (batch_first=True)
|
|
padded3 = paddle.nn.utils.rnn.pad_sequence(sequences, batch_first=True)
|
|
|
|
# 4. With padding_value
|
|
padded4 = paddle.nn.utils.rnn.pad_sequence(sequences, padding_value=1.0)
|
|
|
|
# 5. With padding_side='left'
|
|
padded5 = paddle.nn.utils.rnn.pad_sequence(
|
|
sequences, padding_side='left'
|
|
)
|
|
|
|
# 6. Mixed arguments (positional + keyword)
|
|
padded6 = paddle.nn.utils.rnn.pad_sequence(
|
|
sequences, batch_first=True, padding_value=0.0
|
|
)
|
|
|
|
# 7. TypeError when sequences is a string (not a valid iterable of Tensors)
|
|
with self.assertRaises(TypeError):
|
|
paddle.nn.utils.rnn.pad_sequence("not_a_valid_input")
|
|
|
|
# 8. ValueError for invalid padding_side
|
|
with self.assertRaises(ValueError):
|
|
paddle.nn.utils.rnn.pad_sequence(sequences, padding_side='invalid')
|
|
|
|
# 9. PyTorch-style tuple input (should work the same as list)
|
|
padded_tuple = paddle.nn.utils.rnn.pad_sequence(
|
|
(a, b, c), batch_first=True
|
|
)
|
|
self.assertEqual(padded_tuple.shape, [3, 25, 300])
|
|
np.testing.assert_allclose(padded_tuple.numpy(), padded3.numpy())
|
|
|
|
# Verify outputs
|
|
self.assertEqual(padded1.shape, [25, 3, 300])
|
|
self.assertEqual(padded2.shape, [25, 3, 300])
|
|
self.assertEqual(padded3.shape, [3, 25, 300])
|
|
self.assertEqual(padded4.shape, [25, 3, 300])
|
|
self.assertEqual(padded5.shape, [25, 3, 300])
|
|
self.assertEqual(padded6.shape, [3, 25, 300])
|
|
|
|
# Numerical checks
|
|
np.testing.assert_allclose(padded1.numpy()[:, 0, :], self.a)
|
|
np.testing.assert_allclose(padded1.numpy()[:22, 1, :], self.b)
|
|
np.testing.assert_allclose(padded1.numpy()[22:, 1, :], 0.0)
|
|
np.testing.assert_allclose(padded1.numpy()[:15, 2, :], self.c)
|
|
np.testing.assert_allclose(padded1.numpy()[15:, 2, :], 0.0)
|
|
|
|
# padding_value=1.0
|
|
np.testing.assert_allclose(padded4.numpy()[22:, 1, :], 1.0)
|
|
|
|
# batch_first=True
|
|
np.testing.assert_allclose(padded3.numpy()[0, :, :], self.a)
|
|
|
|
# padding_side='left'
|
|
# padded5 shape [25, 3, 300]
|
|
# a: [25, 300] -> no padding
|
|
# b: [22, 300] -> 3 elements padded at top
|
|
# c: [15, 300] -> 10 elements padded at top
|
|
np.testing.assert_allclose(padded5.numpy()[:, 0, :], self.a)
|
|
np.testing.assert_allclose(padded5.numpy()[3:, 1, :], self.b)
|
|
np.testing.assert_allclose(padded5.numpy()[:3, 1, :], 0.0)
|
|
np.testing.assert_allclose(padded5.numpy()[10:, 2, :], self.c)
|
|
np.testing.assert_allclose(padded5.numpy()[:10, 2, :], 0.0)
|
|
|
|
|
|
# Test unpad_sequence compatibility
|
|
class TestUnpadSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.a = np.random.rand(25, 300).astype("float32")
|
|
self.b = np.random.rand(22, 300).astype("float32")
|
|
self.c = np.random.rand(15, 300).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
a = paddle.to_tensor(self.a)
|
|
b = paddle.to_tensor(self.b)
|
|
c = paddle.to_tensor(self.c)
|
|
sequences = [a, b, c]
|
|
|
|
# Pad then unpad
|
|
padded = paddle.nn.utils.rnn.pad_sequence(sequences)
|
|
lengths = paddle.to_tensor([v.shape[0] for v in sequences])
|
|
|
|
# 1. Paddle Positional arguments
|
|
unpadded1 = paddle.nn.utils.rnn.unpad_sequence(padded, lengths)
|
|
|
|
# 2. Paddle keyword arguments
|
|
unpadded2 = paddle.nn.utils.rnn.unpad_sequence(
|
|
padded_sequences=padded, lengths=lengths
|
|
)
|
|
|
|
# 3. PyTorch keyword arguments (batch_first=True)
|
|
padded_bf = paddle.nn.utils.rnn.pad_sequence(
|
|
sequences, batch_first=True
|
|
)
|
|
unpadded3 = paddle.nn.utils.rnn.unpad_sequence(
|
|
padded_bf, lengths, batch_first=True
|
|
)
|
|
|
|
# 4. Mixed arguments (positional + keyword)
|
|
unpadded4 = paddle.nn.utils.rnn.unpad_sequence(
|
|
padded, batch_first=False, lengths=lengths
|
|
)
|
|
|
|
# Verify outputs
|
|
for i, (original, unpadded) in enumerate(zip(sequences, unpadded1)):
|
|
np.testing.assert_allclose(original.numpy(), unpadded.numpy())
|
|
|
|
for i, (original, unpadded) in enumerate(zip(sequences, unpadded2)):
|
|
np.testing.assert_allclose(original.numpy(), unpadded.numpy())
|
|
|
|
for i, (original, unpadded) in enumerate(zip(sequences, unpadded3)):
|
|
np.testing.assert_allclose(original.numpy(), unpadded.numpy())
|
|
|
|
for i, (original, unpadded) in enumerate(zip(sequences, unpadded4)):
|
|
np.testing.assert_allclose(original.numpy(), unpadded.numpy())
|
|
|
|
|
|
# Test pack_sequence compatibility
|
|
class TestPackSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# 1. Paddle Positional arguments (sorted)
|
|
a = paddle.to_tensor([1, 2, 3])
|
|
b = paddle.to_tensor([4, 5])
|
|
c = paddle.to_tensor([6])
|
|
packed1 = paddle.nn.utils.rnn.pack_sequence([a, b, c])
|
|
|
|
# 2. Paddle keyword arguments
|
|
packed2 = paddle.nn.utils.rnn.pack_sequence(sequences=[a, b, c])
|
|
|
|
# 3. PyTorch keyword arguments (enforce_sorted=False)
|
|
d = paddle.to_tensor([1, 2, 3])
|
|
e = paddle.to_tensor([4])
|
|
f = paddle.to_tensor([5, 6])
|
|
packed3 = paddle.nn.utils.rnn.pack_sequence(
|
|
[d, e, f], enforce_sorted=False
|
|
)
|
|
|
|
# 4. Mixed arguments (positional + keyword)
|
|
g = paddle.to_tensor([7, 8, 9])
|
|
h = paddle.to_tensor([10, 11])
|
|
packed4 = paddle.nn.utils.rnn.pack_sequence([g, h], enforce_sorted=True)
|
|
|
|
# Verify outputs
|
|
for packed in [packed1, packed2]:
|
|
self.assertIsInstance(packed, paddle.nn.utils.rnn.PackedSequence)
|
|
np.testing.assert_array_equal(
|
|
packed.data.numpy().flatten(), [1, 4, 6, 2, 5, 3]
|
|
)
|
|
np.testing.assert_array_equal(packed.batch_sizes.numpy(), [3, 2, 1])
|
|
|
|
# packed3: d=[1,2,3], e=[4], f=[5,6]. enforce_sorted=False
|
|
# sorted by len: [1,2,3] (3), [5,6] (2), [4] (1)
|
|
# data: [1, 5, 4, 2, 6, 3]
|
|
# batch_sizes: [3, 2, 1]
|
|
self.assertIsNotNone(packed3.sorted_indices)
|
|
self.assertIsNotNone(packed3.unsorted_indices)
|
|
np.testing.assert_array_equal(
|
|
packed3.data.numpy().flatten(), [1, 5, 4, 2, 6, 3]
|
|
)
|
|
np.testing.assert_array_equal(packed3.batch_sizes.numpy(), [3, 2, 1])
|
|
|
|
# packed4: g=[7,8,9], h=[10,11]. enforce_sorted=True
|
|
# data: [7, 10, 8, 11, 9]
|
|
# batch_sizes: [2, 2, 1]
|
|
self.assertIsInstance(packed4, paddle.nn.utils.rnn.PackedSequence)
|
|
np.testing.assert_array_equal(
|
|
packed4.data.numpy().flatten(), [7, 10, 8, 11, 9]
|
|
)
|
|
np.testing.assert_array_equal(packed4.batch_sizes.numpy(), [2, 2, 1])
|
|
|
|
|
|
# Test unpack_sequence compatibility
|
|
class TestUnpackSequenceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Create sequences
|
|
a = paddle.to_tensor([1, 2, 3])
|
|
b = paddle.to_tensor([4, 5])
|
|
c = paddle.to_tensor([6])
|
|
sequences = [a, b, c]
|
|
|
|
# Pack and unpack
|
|
packed = paddle.nn.utils.rnn.pack_sequence(sequences)
|
|
|
|
# 1. Paddle Positional arguments
|
|
unpacked1 = paddle.nn.utils.rnn.unpack_sequence(packed)
|
|
|
|
# 2. Paddle keyword arguments
|
|
unpacked2 = paddle.nn.utils.rnn.unpack_sequence(packed_sequences=packed)
|
|
|
|
# 3. Mixed arguments (positional + keyword)
|
|
unpacked3 = paddle.nn.utils.rnn.unpack_sequence(packed_sequences=packed)
|
|
|
|
# Verify outputs
|
|
for i, (original, unpacked) in enumerate(zip(sequences, unpacked1)):
|
|
np.testing.assert_array_equal(original.numpy(), unpacked.numpy())
|
|
|
|
for i, (original, unpacked) in enumerate(zip(sequences, unpacked2)):
|
|
np.testing.assert_array_equal(original.numpy(), unpacked.numpy())
|
|
|
|
for i, (original, unpacked) in enumerate(zip(sequences, unpacked3)):
|
|
np.testing.assert_array_equal(original.numpy(), unpacked.numpy())
|
|
|
|
|
|
# Test vstack compatibility
|
|
class TestVstackAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x1 = np.array([1, 2, 3]).astype("float32")
|
|
self.np_x2 = np.array([4, 5, 6]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x1 = paddle.to_tensor(self.np_x1)
|
|
x2 = paddle.to_tensor(self.np_x2)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.vstack([x1, x2])
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.vstack(x=[x1, x2])
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.vstack(tensors=[x1, x2])
|
|
|
|
expected = np.array([[1, 2, 3], [4, 5, 6]])
|
|
for out in [out1, out2, out3]:
|
|
np.testing.assert_allclose(out.numpy(), expected)
|
|
|
|
# 4. out parameter test
|
|
out4 = paddle.empty([2, 3], dtype="float32")
|
|
paddle.vstack([x1, x2], out=out4)
|
|
np.testing.assert_allclose(out4.numpy(), expected)
|
|
|
|
|
|
# Test batch_norm compatibility (compat version)
|
|
class TestBatchNormFnAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3, 4, 4).astype("float32")
|
|
self.np_running_mean = np.zeros(3).astype("float32")
|
|
self.np_running_var = np.ones(3).astype("float32")
|
|
self.np_weight = np.ones(3).astype("float32")
|
|
self.np_bias = np.zeros(3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
running_mean = paddle.to_tensor(self.np_running_mean)
|
|
running_var = paddle.to_tensor(self.np_running_var)
|
|
weight = paddle.to_tensor(self.np_weight)
|
|
bias = paddle.to_tensor(self.np_bias)
|
|
|
|
compat_bn = paddle.compat.nn.functional.batch_norm
|
|
|
|
# 1. PyTorch-style positional arguments
|
|
out1 = compat_bn(x, running_mean, running_var, weight, bias)
|
|
# 2. PyTorch-style keyword arguments
|
|
out2 = compat_bn(
|
|
input=x,
|
|
running_mean=running_mean,
|
|
running_var=running_var,
|
|
weight=weight,
|
|
bias=bias,
|
|
)
|
|
# 3. Paddle-style positional (should also work via compat, as it is
|
|
# a wrapper calling paddle.nn.functional.batch_norm internally)
|
|
out3 = paddle.nn.functional.batch_norm(
|
|
x, running_mean, running_var, weight, bias
|
|
)
|
|
|
|
for out in [out1, out2]:
|
|
self.assertEqual(out.shape, x.shape)
|
|
self.assertEqual(out.dtype, paddle.float32)
|
|
|
|
# Verify compat output is consistent with paddle's native result
|
|
np.testing.assert_allclose(
|
|
out1.numpy(), out3.numpy(), rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# 4. Test momentum conversion: torch momentum=0.1 -> paddle momentum=0.9
|
|
# This verifies the compat wrapper correctly transforms the parameter.
|
|
out_torch_momentum = compat_bn(
|
|
input=x,
|
|
running_mean=running_mean,
|
|
running_var=running_var,
|
|
weight=weight,
|
|
bias=bias,
|
|
momentum=0.1,
|
|
)
|
|
out_paddle_momentum = paddle.nn.functional.batch_norm(
|
|
x,
|
|
running_mean,
|
|
running_var,
|
|
weight,
|
|
bias,
|
|
momentum=0.9,
|
|
)
|
|
np.testing.assert_allclose(
|
|
out_torch_momentum.numpy(),
|
|
out_paddle_momentum.numpy(),
|
|
rtol=1e-5,
|
|
atol=1e-5,
|
|
)
|
|
|
|
# 5. Verify result matches numerical expectation in eval mode
|
|
# batch_norm(x) = (x - running_mean) / sqrt(running_var + eps) * weight + bias
|
|
# With running_mean=0, running_var=1, weight=1, bias=0: y ≈ x
|
|
np.testing.assert_allclose(
|
|
out1.numpy(), x.numpy(), rtol=1e-4, atol=1e-4
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=[2, 3, 4, 4], dtype="float32"
|
|
)
|
|
running_mean = paddle.static.data(
|
|
name="running_mean", shape=[3], dtype="float32"
|
|
)
|
|
running_var = paddle.static.data(
|
|
name="running_var", shape=[3], dtype="float32"
|
|
)
|
|
weight = paddle.static.data(
|
|
name="weight", shape=[3], dtype="float32"
|
|
)
|
|
bias = paddle.static.data(name="bias", shape=[3], dtype="float32")
|
|
|
|
compat_bn = paddle.compat.nn.functional.batch_norm
|
|
|
|
out1 = compat_bn(x, running_mean, running_var, weight, bias)
|
|
out2 = compat_bn(
|
|
input=x,
|
|
running_mean=running_mean,
|
|
running_var=running_var,
|
|
weight=weight,
|
|
bias=bias,
|
|
)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"running_mean": self.np_running_mean,
|
|
"running_var": self.np_running_var,
|
|
"weight": self.np_weight,
|
|
"bias": self.np_bias,
|
|
},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
for out in fetches:
|
|
self.assertEqual(out.shape, (2, 3, 4, 4))
|
|
# In eval mode with running_mean=0, running_var=1, weight=1, bias=0
|
|
# output ≈ input
|
|
np.testing.assert_allclose(out, self.np_x, rtol=1e-4, atol=1e-4)
|
|
|
|
# Test gumbel_softmax compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestGumbelSoftmaxAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.randn(4, 6).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.nn.functional.gumbel_softmax(x, temperature=1.0)
|
|
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.gumbel_softmax(
|
|
x=x, temperature=1.0, hard=False, axis=-1
|
|
)
|
|
|
|
# 3. PyTorch keyword arguments (logits alias, tau alias, dim alias)
|
|
out3 = paddle.nn.functional.gumbel_softmax(
|
|
logits=x, tau=1.0, hard=False, dim=-1
|
|
)
|
|
|
|
# 4. hard=True test
|
|
out4 = paddle.nn.functional.gumbel_softmax(x, hard=True)
|
|
|
|
# 5. PyTorch 4 positional args: (logits, tau, hard, eps)
|
|
out5 = paddle.nn.functional.gumbel_softmax(x, 1.0, False, 1e-10)
|
|
|
|
# 6. PyTorch 4 positional args: (logits, tau, hard, dim)
|
|
out6 = paddle.nn.functional.gumbel_softmax(x, 1.0, False, 0)
|
|
|
|
# Verify outputs
|
|
for out in [out1, out2, out3, out5, out6]:
|
|
self.assertEqual(out.shape, x.shape)
|
|
self.assertEqual(out.dtype, paddle.float32)
|
|
|
|
# Verify hard=True returns one-hot
|
|
self.assertTrue((out4.sum(axis=-1) == 1.0).all())
|
|
|
|
|
|
# Test set_default_device compatibility
|
|
class TestSetDefaultDeviceAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Save original device
|
|
original_device = paddle.get_default_device()
|
|
|
|
# Test with string device
|
|
paddle.set_default_device("cpu")
|
|
self.assertEqual(
|
|
paddle.get_default_device(), paddle.device.Device("cpu")
|
|
)
|
|
|
|
# Test with None (reset to CPU)
|
|
paddle.set_default_device(None)
|
|
self.assertEqual(
|
|
paddle.get_default_device(), paddle.device.Device("cpu")
|
|
)
|
|
|
|
# Restore original device
|
|
if original_device is not None:
|
|
paddle.set_device(str(original_device))
|
|
|
|
|
|
# Test set_grad_enabled compatibility
|
|
class TestSetGradEnabledAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
x = paddle.to_tensor([1.0, 2.0], stop_gradient=False)
|
|
|
|
# Test via autograd.grad_mode.set_grad_enabled
|
|
with paddle.autograd.grad_mode.set_grad_enabled(False):
|
|
y = x * 2
|
|
self.assertTrue(y.stop_gradient)
|
|
|
|
with paddle.autograd.grad_mode.set_grad_enabled(True):
|
|
z = x * 2
|
|
self.assertFalse(z.stop_gradient)
|
|
|
|
|
|
# Test new_tensor compatibility
|
|
class TestNewTensorAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_data = np.array([[1, 2, 3], [4, 5, 6]], dtype="float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor([1, 2, 3], dtype="float32")
|
|
|
|
# Test new_tensor with data
|
|
out = x.new_tensor(self.np_data)
|
|
self.assertEqual(out.shape, [2, 3])
|
|
self.assertEqual(out.dtype, x.dtype)
|
|
np.testing.assert_allclose(out.numpy(), self.np_data, rtol=1e-5)
|
|
|
|
# Test new_tensor with requires_grad=False
|
|
out2 = x.new_tensor(self.np_data, requires_grad=False)
|
|
self.assertTrue(out2.stop_gradient)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3], dtype="float32")
|
|
|
|
# Test new_tensor with data
|
|
out = x.new_tensor(self.np_data)
|
|
out2 = x.new_tensor(self.np_data, dtype="float64")
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
feed={"x": np.array([1, 2, 3], dtype="float32")},
|
|
fetch_list=[out, out2],
|
|
)
|
|
self.assertEqual(fetches[0].shape, (2, 3))
|
|
self.assertEqual(fetches[0].dtype, np.float32)
|
|
np.testing.assert_allclose(fetches[0], self.np_data, rtol=1e-5)
|
|
|
|
self.assertEqual(fetches[1].dtype, np.float64)
|
|
paddle.enable_static()
|
|
|
|
# Test to_empty compatibility
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestToEmptyAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.randn(3, 4).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Test single layer with Parameters
|
|
layer = paddle.nn.Linear(4, 2)
|
|
layer.to_empty(device="cpu")
|
|
|
|
# Verify parameters are on the correct device
|
|
for param in layer.parameters():
|
|
self.assertTrue("cpu" in str(param.place).lower())
|
|
|
|
# Test with recurse=False
|
|
layer.to_empty(device="cpu", recurse=False)
|
|
|
|
# Test multi-layer (nested sublayers)
|
|
class NestedLayer(paddle.nn.Layer):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.fc1 = paddle.nn.Linear(4, 4)
|
|
self.fc2 = paddle.nn.Linear(4, 2)
|
|
|
|
def forward(self, x):
|
|
return self.fc2(self.fc1(x))
|
|
|
|
nested = NestedLayer()
|
|
nested.to_empty(device="cpu")
|
|
for param in nested.parameters():
|
|
self.assertTrue("cpu" in str(param.place).lower())
|
|
# Verify sublayer parameters are also moved
|
|
for param in nested.fc1.parameters():
|
|
self.assertTrue("cpu" in str(param.place).lower())
|
|
for param in nested.fc2.parameters():
|
|
self.assertTrue("cpu" in str(param.place).lower())
|
|
|
|
# Test with ordinary buffers (non-Parameter tensors)
|
|
class LayerWithBuf(paddle.nn.Layer):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.fc = paddle.nn.Linear(4, 2)
|
|
self.register_buffer(
|
|
"my_buf", paddle.zeros([2, 3], dtype="float32")
|
|
)
|
|
|
|
layer_buf = LayerWithBuf()
|
|
layer_buf.to_empty(device="cpu")
|
|
self.assertTrue("cpu" in str(layer_buf.my_buf.place).lower())
|
|
for param in layer_buf.fc.parameters():
|
|
self.assertTrue("cpu" in str(param.place).lower())
|
|
|
|
|
|
# Test _Loss base class compatibility
|
|
class TestLossBaseAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Verify _Loss is importable from paddle.nn.modules.loss
|
|
from paddle.nn.modules.loss import _Loss
|
|
|
|
self.assertTrue(issubclass(_Loss, paddle.nn.Layer))
|
|
|
|
# Test creating a _Loss instance with reduction
|
|
loss_base = _Loss(reduction='mean')
|
|
self.assertEqual(loss_base.reduction, 'mean')
|
|
|
|
loss_base_sum = _Loss(reduction='sum')
|
|
self.assertEqual(loss_base_sum.reduction, 'sum')
|
|
|
|
# Test _Loss with size_average/reduce (PyTorch compatibility kwargs)
|
|
loss_sa = _Loss(size_average=True, reduce=True)
|
|
self.assertEqual(loss_sa.reduction, 'mean')
|
|
|
|
loss_sa_false = _Loss(size_average=False, reduce=True)
|
|
self.assertEqual(loss_sa_false.reduction, 'sum')
|
|
|
|
loss_reduce_false = _Loss(size_average=True, reduce=False)
|
|
self.assertEqual(loss_reduce_false.reduction, 'none')
|
|
|
|
|
|
# Test _pair compatibility
|
|
class TestPairAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
# Test _pair import from paddle.nn.modules.utils
|
|
from paddle.nn.modules.utils import _pair
|
|
|
|
# Test with int
|
|
result = _pair(3)
|
|
self.assertEqual(result, (3, 3))
|
|
|
|
# Test with tuple
|
|
result2 = _pair((4, 5))
|
|
self.assertEqual(result2, (4, 5))
|
|
|
|
# Test with list
|
|
result3 = _pair([6, 7])
|
|
self.assertEqual(result3, (6, 7))
|
|
|
|
|
|
# Test GradScaler compatibility (already aligned)
|
|
class TestGradScalerAPI(unittest.TestCase):
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Test Paddle-style constructor
|
|
scaler1 = paddle.cuda.amp.GradScaler(
|
|
enable=True, init_loss_scaling=65536.0
|
|
)
|
|
self.assertIsNotNone(scaler1)
|
|
|
|
# Test PyTorch-style constructor
|
|
scaler2 = paddle.cuda.amp.GradScaler(enabled=True, init_scale=65536.0)
|
|
self.assertIsNotNone(scaler2)
|
|
|
|
# Test PyTorch-style constructor with growth params
|
|
scaler3 = paddle.cuda.amp.GradScaler(
|
|
init_scale=1024.0,
|
|
growth_factor=2.0,
|
|
backoff_factor=0.5,
|
|
growth_interval=1000,
|
|
enabled=True,
|
|
)
|
|
self.assertIsNotNone(scaler3)
|
|
|
|
|
|
# Test hstack compatibility (out parameter fix)
|
|
class TestHstackAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3).astype("float32")
|
|
self.np_y = np.random.rand(2, 3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
y = paddle.to_tensor(self.np_y)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.hstack([x, y])
|
|
# 2. Paddle keyword arguments with alias
|
|
out2 = paddle.hstack(tensors=[x, y])
|
|
# 3. out parameter test
|
|
out3 = paddle.empty_like(out1)
|
|
paddle.hstack([x, y], out=out3)
|
|
|
|
# Verify all outputs
|
|
np.testing.assert_allclose(out1.numpy(), out2.numpy())
|
|
np.testing.assert_allclose(out1.numpy(), out3.numpy())
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[2, 3], dtype="float32")
|
|
y = paddle.static.data(name="y", shape=[2, 3], dtype="float32")
|
|
|
|
out1 = paddle.hstack([x, y])
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x, "y": self.np_y},
|
|
fetch_list=[out1],
|
|
)
|
|
self.assertEqual(fetches[0].shape, (2, 6))
|
|
|
|
# Test nn.ELU compatibility (inplace parameter)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestELUAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
# Use data with both positive and negative values to test ELU
|
|
self.np_x = np.random.randn(2, 3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle position arguments
|
|
elu = paddle.nn.ELU(alpha=1.0)
|
|
out1 = elu(x)
|
|
# 2. Inplace=False
|
|
elu2 = paddle.nn.ELU(alpha=1.0, inplace=False)
|
|
out2 = elu2(x)
|
|
# 3. Inplace=True
|
|
x3 = paddle.to_tensor(self.np_x.copy())
|
|
elu3 = paddle.nn.ELU(alpha=1.0, inplace=True)
|
|
out3 = elu3(x3)
|
|
|
|
# Reference: ELU(x) = max(0,x) + min(0, alpha*(exp(x)-1))
|
|
expected = np.where(
|
|
self.np_x > 0, self.np_x, 1.0 * (np.exp(self.np_x) - 1)
|
|
)
|
|
|
|
# Verify non-inplace outputs
|
|
np.testing.assert_allclose(out1.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
np.testing.assert_allclose(out2.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
# Verify inplace modifies input
|
|
np.testing.assert_allclose(
|
|
out3.numpy(), x3.numpy(), rtol=1e-5, atol=1e-5
|
|
)
|
|
np.testing.assert_allclose(out3.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[2, 3], dtype="float32")
|
|
|
|
elu = paddle.nn.ELU(alpha=1.0)
|
|
out = elu(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out],
|
|
)
|
|
expected = np.where(
|
|
self.np_x > 0, self.np_x, 1.0 * (np.exp(self.np_x) - 1)
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[0], expected, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# Test linalg.cross compatibility (parameter aliases, out)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestLinalgCrossAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
# cross product requires last dimension = 3
|
|
self.np_x = np.random.rand(5, 3).astype("float32")
|
|
self.np_y = np.random.rand(5, 3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
y = paddle.to_tensor(self.np_y)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.linalg.cross(x, y)
|
|
# 2. PyTorch keyword arguments
|
|
out2 = paddle.linalg.cross(input=x, other=y)
|
|
# 3. PyTorch keyword arguments with dim alias
|
|
out3 = paddle.linalg.cross(x, y, dim=1)
|
|
# 4. out parameter test
|
|
out4 = paddle.empty_like(out1)
|
|
paddle.linalg.cross(x, y, out=out4)
|
|
# 5. Tensor method
|
|
out5 = x.cross(y)
|
|
|
|
# Verify all outputs
|
|
expected_np = np.cross(self.np_x, self.np_y, axisa=1, axisb=1, axisc=1)
|
|
for out in [out1, out2, out3, out4, out5]:
|
|
np.testing.assert_allclose(
|
|
out.numpy(), expected_np, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[5, 3], dtype="float32")
|
|
y = paddle.static.data(name="y", shape=[5, 3], dtype="float32")
|
|
|
|
out1 = paddle.linalg.cross(input=x, other=y)
|
|
out2 = paddle.linalg.cross(x, y, dim=1)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x, "y": self.np_y},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
expected_np = np.cross(
|
|
self.np_x, self.np_y, axisa=1, axisb=1, axisc=1
|
|
)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(
|
|
out, expected_np, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# Test Tensor.true_divide_ compatibility (alias for divide_)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestTrueDivide_InplaceAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, 2.0, 3.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x.copy())
|
|
y = paddle.to_tensor([2.0, 4.0, 6.0])
|
|
|
|
# PyTorch-style keyword arguments
|
|
x.true_divide_(other=y)
|
|
expected = self.np_x / np.array([2.0, 4.0, 6.0])
|
|
np.testing.assert_allclose(x.numpy(), expected, rtol=1e-5)
|
|
|
|
|
|
# Test Tensor.H/mH/T compatibility (new properties)
|
|
class TestTensorHAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_2d = np.array([[1.0, 2.0], [3.0, 4.0]]).astype("float32")
|
|
self.np_3d = np.arange(24).reshape(2, 3, 4).astype("float32")
|
|
self.np_complex = np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]]).astype(
|
|
"complex64"
|
|
)
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
|
|
# Test .H on real 2D tensor
|
|
x = paddle.to_tensor(self.np_2d)
|
|
h = x.H
|
|
expected = self.np_2d.transpose()
|
|
np.testing.assert_allclose(h.numpy(), expected, rtol=1e-5)
|
|
|
|
# Test .H on complex 2D tensor
|
|
x_c = paddle.to_tensor(self.np_complex)
|
|
h_c = x_c.H
|
|
expected_c = self.np_complex.transpose().conj()
|
|
np.testing.assert_allclose(h_c.numpy(), expected_c, rtol=1e-5)
|
|
|
|
# Test .mH on 2D real tensor
|
|
mh = x.mH
|
|
expected_mh = self.np_2d.transpose().conj()
|
|
np.testing.assert_allclose(mh.numpy(), expected_mh, rtol=1e-5)
|
|
|
|
# Test .mH on 3D real tensor (last two dims swap + conj)
|
|
x_3d = paddle.to_tensor(self.np_3d)
|
|
mh_3d = x_3d.mH
|
|
expected_mh_3d = self.np_3d.transpose(0, 2, 1).conj()
|
|
np.testing.assert_allclose(mh_3d.numpy(), expected_mh_3d, rtol=1e-5)
|
|
|
|
# Test .H on 0D real tensor (returns self)
|
|
x_0d = paddle.to_tensor(np.array(5.0).astype("float32"))
|
|
h_0d = x_0d.H
|
|
self.assertEqual(h_0d.shape, [])
|
|
np.testing.assert_allclose(h_0d.numpy(), np.array(5.0), rtol=1e-5)
|
|
|
|
# Test .H on 0D complex tensor (returns self)
|
|
x_0d_c = paddle.to_tensor(np.array(1 + 2j).astype("complex64"))
|
|
h_0d_c = x_0d_c.H
|
|
self.assertEqual(h_0d_c.shape, [])
|
|
np.testing.assert_allclose(h_0d_c.numpy(), np.array(1 - 2j), rtol=1e-5)
|
|
|
|
# Test .mH on 0D tensor (returns self)
|
|
mh_0d = x_0d.mH
|
|
self.assertEqual(mh_0d.shape, [])
|
|
np.testing.assert_allclose(mh_0d.numpy(), np.array(5.0), rtol=1e-5)
|
|
|
|
# Test .T on 2D real tensor
|
|
t = x.T
|
|
expected_t = self.np_2d.T
|
|
np.testing.assert_allclose(t.numpy(), expected_t, rtol=1e-5)
|
|
|
|
# Test .T on 3D real tensor (reverses all dims)
|
|
t_3d = x_3d.T
|
|
expected_t_3d = self.np_3d.transpose(2, 1, 0)
|
|
np.testing.assert_allclose(t_3d.numpy(), expected_t_3d, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[2, 2], dtype="float32")
|
|
x_c = paddle.static.data(
|
|
name="x_c", shape=[2, 2], dtype="complex64"
|
|
)
|
|
x_3d = paddle.static.data(
|
|
name="x_3d", shape=[2, 3, 4], dtype="float32"
|
|
)
|
|
x_0d = paddle.static.data(name="x_0d", shape=[], dtype="float32")
|
|
|
|
# Test .H on 2D real tensor
|
|
h = x.H
|
|
# Test .H on 2D complex tensor
|
|
h_c = x_c.H
|
|
# Test .mH on 2D real tensor
|
|
mh = x.mH
|
|
# Test .mH on 3D real tensor (last two dims swap + conj)
|
|
mh_3d = x_3d.mH
|
|
# Test .H on 0D tensor (returns self)
|
|
h_0d = x_0d.H
|
|
# Test .mH on 0D tensor (returns self)
|
|
mh_0d = x_0d.mH
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_2d,
|
|
"x_c": self.np_complex,
|
|
"x_3d": self.np_3d,
|
|
"x_0d": np.array(5.0).astype("float32"),
|
|
},
|
|
fetch_list=[h, h_c, mh, mh_3d, h_0d, mh_0d],
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[0], self.np_2d.transpose(), rtol=1e-5
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[1], self.np_complex.transpose().conj(), rtol=1e-5
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[2], self.np_2d.transpose().conj(), rtol=1e-5
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[3], self.np_3d.transpose(0, 2, 1).conj(), rtol=1e-5
|
|
)
|
|
np.testing.assert_allclose(fetches[4], np.array(5.0), rtol=1e-5)
|
|
np.testing.assert_allclose(fetches[5], np.array(5.0), rtol=1e-5)
|
|
|
|
paddle.disable_static()
|
|
|
|
# Test clamp_max compatibility (new API)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestClampMaxAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, 5.0, 3.0, 8.0, 2.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.clamp_max(x, 4.0)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.clamp_max(input=x, max=4.0)
|
|
# 3. out parameter test
|
|
out3 = paddle.empty_like(x)
|
|
paddle.clamp_max(x, 4.0, out=out3)
|
|
|
|
expected = np.minimum(self.np_x, 4.0)
|
|
for out in [out1, out2, out3]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[5], dtype="float32")
|
|
|
|
out1 = paddle.clamp_max(x, 4.0)
|
|
out2 = paddle.clamp_max(input=x, max=4.0)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
expected = np.minimum(self.np_x, 4.0)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test clamp_min compatibility (new API)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestClampMinAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([1.0, 5.0, 3.0, 8.0, 2.0]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.clamp_min(x, 3.0)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.clamp_min(input=x, min=3.0)
|
|
# 3. out parameter test
|
|
out3 = paddle.empty_like(x)
|
|
paddle.clamp_min(x, 3.0, out=out3)
|
|
|
|
expected = np.maximum(self.np_x, 3.0)
|
|
for out in [out1, out2, out3]:
|
|
np.testing.assert_allclose(out.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[5], dtype="float32")
|
|
|
|
out1 = paddle.clamp_min(x, 3.0)
|
|
out2 = paddle.clamp_min(input=x, min=3.0)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
expected = np.maximum(self.np_x, 3.0)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5)
|
|
|
|
# Test qr compatibility (new API)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestQrAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(4, 3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle Positional arguments (some=True by default)
|
|
Q1, R1 = paddle.qr(x)
|
|
Q2, R2 = paddle.qr(input=x, some=True)
|
|
Q3, R3 = paddle.qr(x, some=False)
|
|
# 4. test mode keyword
|
|
Q5, R5 = paddle.linalg.qr(x, mode='reduced')
|
|
# 5. some as positional bool (type-based dispatch)
|
|
Q6, R6 = paddle.qr(x, True)
|
|
Q7, R7 = paddle.qr(x, False)
|
|
# 6. A alias
|
|
Q8, R8 = paddle.qr(A=x, some=True)
|
|
# 7. mode='r' returns single Tensor R
|
|
R9 = paddle.qr(x, mode='r')
|
|
# 8. mode='r' with out parameter
|
|
R10 = paddle.empty(shape=[4, 3], dtype=x.dtype)
|
|
paddle.qr(x, mode='r', out=R10)
|
|
|
|
# Verify some=True matches reduced mode
|
|
np.testing.assert_allclose(Q1.numpy(), Q5.numpy(), rtol=1e-5, atol=1e-5)
|
|
np.testing.assert_allclose(R1.numpy(), R5.numpy(), rtol=1e-5, atol=1e-5)
|
|
# Verify some=True and positional True match
|
|
np.testing.assert_allclose(Q1.numpy(), Q6.numpy(), rtol=1e-5, atol=1e-5)
|
|
# Verify some=False and positional False match
|
|
np.testing.assert_allclose(Q3.numpy(), Q7.numpy(), rtol=1e-5, atol=1e-5)
|
|
# Verify A alias
|
|
np.testing.assert_allclose(Q1.numpy(), Q8.numpy(), rtol=1e-5, atol=1e-5)
|
|
# Verify reconstruction
|
|
reconstr = Q1 @ R1
|
|
np.testing.assert_allclose(
|
|
reconstr.numpy(), self.np_x, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# some=False gives complete QR
|
|
self.assertEqual(Q3.shape, (4, 4))
|
|
# mode='r' returns single Tensor
|
|
self.assertEqual(len(R9.shape), 2)
|
|
# Verify mode='r' with out parameter
|
|
np.testing.assert_allclose(
|
|
R9.numpy(), R10.numpy(), rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[4, 3], dtype="float32")
|
|
r_out = paddle.static.data(
|
|
name="r_out", shape=[4, 3], dtype="float32"
|
|
)
|
|
|
|
Q1, R1 = paddle.qr(x)
|
|
Q2, R2 = paddle.qr(x, mode='reduced')
|
|
R3 = paddle.qr(x, mode='r')
|
|
# mode='r' with out parameter
|
|
paddle.qr(x, mode='r', out=r_out)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"r_out": np.zeros([4, 3], dtype="float32"),
|
|
},
|
|
fetch_list=[Q1, R1, Q2, R2, R3, r_out],
|
|
)
|
|
# Verify default and mode='reduced' match
|
|
np.testing.assert_allclose(
|
|
fetches[0], fetches[2], rtol=1e-5, atol=1e-5
|
|
)
|
|
np.testing.assert_allclose(
|
|
fetches[1], fetches[3], rtol=1e-5, atol=1e-5
|
|
)
|
|
# Verify mode='r' returns R only
|
|
np.testing.assert_allclose(
|
|
fetches[1], fetches[4], rtol=1e-5, atol=1e-5
|
|
)
|
|
# Verify mode='r' with out parameter
|
|
np.testing.assert_allclose(
|
|
fetches[4], fetches[5], rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# Test logdet compatibility (new API)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestLogdetAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
# Positive definite matrix
|
|
A = np.random.rand(3, 3).astype("float32")
|
|
self.np_x = (A @ A.T + np.eye(3) * 0.1).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
out1 = paddle.logdet(x)
|
|
expected = np.log(np.linalg.det(self.np_x))
|
|
np.testing.assert_allclose(out1.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3, 3], dtype="float32")
|
|
|
|
out = paddle.logdet(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out],
|
|
)
|
|
expected = np.log(np.linalg.det(self.np_x))
|
|
np.testing.assert_allclose(
|
|
fetches[0], expected, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# Test linalg.eigh compatibility (out parameter, input alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestEighAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
A = np.random.rand(3, 3).astype("float32")
|
|
self.np_x = (A + A.T) / 2
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle positional arguments
|
|
w1, v1 = paddle.linalg.eigh(x)
|
|
# 2. PyTorch keyword arguments
|
|
w2, v2 = paddle.linalg.eigh(input=x, UPLO='L')
|
|
|
|
# Verify eigenvalues match
|
|
expected_w = np.linalg.eigh(self.np_x)[0]
|
|
np.testing.assert_allclose(w1.numpy(), expected_w, rtol=1e-5, atol=1e-5)
|
|
np.testing.assert_allclose(w2.numpy(), expected_w, rtol=1e-5, atol=1e-5)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3, 3], dtype="float32")
|
|
|
|
w, v = paddle.linalg.eigh(x)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[w, v],
|
|
)
|
|
expected_w = np.linalg.eigh(self.np_x)[0]
|
|
np.testing.assert_allclose(
|
|
fetches[0], expected_w, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# Test linalg.cholesky compatibility (out parameter, input alias)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestLinalgCholeskyAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
A = np.random.rand(3, 3).astype("float64")
|
|
self.np_x = (A @ A.T + np.eye(3) * 0.1).astype("float64")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.linalg.cholesky(x)
|
|
# 2. PyTorch keyword arguments
|
|
out2 = paddle.linalg.cholesky(input=x, upper=False)
|
|
# 3. Upper triangular
|
|
out3 = paddle.linalg.cholesky(x, upper=True)
|
|
|
|
expected = np.linalg.cholesky(self.np_x)
|
|
np.testing.assert_allclose(out1.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
np.testing.assert_allclose(out2.numpy(), expected, rtol=1e-5, atol=1e-5)
|
|
expected_upper = np.linalg.cholesky(self.np_x).T
|
|
np.testing.assert_allclose(
|
|
out3.numpy(), expected_upper, rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3, 3], dtype="float64")
|
|
|
|
out1 = paddle.linalg.cholesky(x)
|
|
out2 = paddle.linalg.cholesky(input=x, upper=False)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
expected = np.linalg.cholesky(self.np_x)
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-5, atol=1e-5)
|
|
|
|
# Test nn.functional.prelu compatibility (input alias for x)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestPreluAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(1, 2, 3).astype("float32")
|
|
self.np_weight = np.array([0.25], dtype="float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
w = paddle.to_tensor(self.np_weight)
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.prelu(x, w)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.prelu(x=x, weight=w)
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
out3 = paddle.nn.functional.prelu(input=x, weight=w)
|
|
|
|
expected = out1.numpy()
|
|
np.testing.assert_allclose(out1.numpy(), expected)
|
|
np.testing.assert_allclose(out2.numpy(), expected)
|
|
np.testing.assert_allclose(out3.numpy(), expected)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[1, 2, 3], dtype="float32")
|
|
w = paddle.static.data(name="w", shape=[1], dtype="float32")
|
|
|
|
out1 = paddle.nn.functional.prelu(x, w)
|
|
out2 = paddle.nn.functional.prelu(x=x, weight=w)
|
|
out3 = paddle.nn.functional.prelu(input=x, weight=w)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x, "w": self.np_weight},
|
|
fetch_list=[out1, out2, out3],
|
|
)
|
|
expected = fetches[0]
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected)
|
|
|
|
# Test linalg.qr compatibility (A alias for x)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestLinalgQrAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(3, 3).astype("float64")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
|
|
# 1. Paddle positional arguments
|
|
q1, r1 = paddle.linalg.qr(x, mode='reduced')
|
|
# 2. Paddle keyword arguments
|
|
q2, r2 = paddle.linalg.qr(x=x, mode='reduced')
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
q3, r3 = paddle.linalg.qr(input=x, mode='reduced')
|
|
# 4. PyTorch keyword arguments (A alias)
|
|
q4, r4 = paddle.linalg.qr(A=x, mode='reduced')
|
|
# 5. out parameter
|
|
q5 = paddle.empty([3, 3], dtype='float64')
|
|
r5 = paddle.empty([3, 3], dtype='float64')
|
|
q_out, r_out = paddle.linalg.qr(x, mode='reduced', out=(q5, r5))
|
|
# 6. mode='r' returns single Tensor R
|
|
r6 = paddle.linalg.qr(x, mode='r')
|
|
# 7. mode='r' with out parameter (single tensor)
|
|
r7_out = paddle.empty([3, 3], dtype='float64')
|
|
paddle.linalg.qr(x, mode='r', out=r7_out)
|
|
|
|
np.testing.assert_allclose(q1.numpy(), q2.numpy())
|
|
np.testing.assert_allclose(q1.numpy(), q3.numpy())
|
|
np.testing.assert_allclose(q1.numpy(), q4.numpy())
|
|
np.testing.assert_allclose(q1.numpy(), q_out.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r2.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r3.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r4.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r_out.numpy())
|
|
# Verify mode='r' returns matching R
|
|
np.testing.assert_allclose(r1.numpy(), r6.numpy())
|
|
# Verify mode='r' with out parameter
|
|
np.testing.assert_allclose(r6.numpy(), r7_out.numpy())
|
|
|
|
# 8. Tensor method - positional
|
|
q6, r6 = x.qr('reduced')
|
|
# 7. Tensor method - kwargs
|
|
q7, r7 = x.qr(mode='reduced')
|
|
|
|
np.testing.assert_allclose(q1.numpy(), q6.numpy())
|
|
np.testing.assert_allclose(q1.numpy(), q7.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r6.numpy())
|
|
np.testing.assert_allclose(r1.numpy(), r7.numpy())
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3, 3], dtype="float64")
|
|
|
|
# 1. Paddle positional arguments
|
|
q1, r1 = paddle.linalg.qr(x, mode='reduced')
|
|
# 2. Paddle keyword arguments
|
|
q2, r2 = paddle.linalg.qr(x=x, mode='reduced')
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
q3, r3 = paddle.linalg.qr(input=x, mode='reduced')
|
|
# 4. PyTorch keyword arguments (A alias)
|
|
q4, r4 = paddle.linalg.qr(A=x, mode='reduced')
|
|
# 5. Tensor method
|
|
q5, r5 = x.qr(mode='reduced')
|
|
# 6. mode='r' returns single Tensor R
|
|
r6 = paddle.linalg.qr(x, mode='r')
|
|
# 7. mode='r' with out parameter
|
|
r7_out = paddle.static.data(
|
|
name="r7_out", shape=[3, 3], dtype="float64"
|
|
)
|
|
paddle.linalg.qr(x, mode='r', out=r7_out)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={
|
|
"x": self.np_x,
|
|
"r7_out": np.zeros([3, 3], dtype="float64"),
|
|
},
|
|
fetch_list=[q1, r1, q2, r2, q3, r3, q4, r4, q5, r5, r6, r7_out],
|
|
)
|
|
# Verify Q matrices match
|
|
for i in range(0, 10, 2):
|
|
np.testing.assert_allclose(fetches[0], fetches[i])
|
|
# Verify R matrices match
|
|
for i in range(1, 10, 2):
|
|
np.testing.assert_allclose(fetches[1], fetches[i])
|
|
# Verify mode='r' returns matching R
|
|
np.testing.assert_allclose(fetches[1], fetches[10])
|
|
# Verify mode='r' with out parameter
|
|
np.testing.assert_allclose(fetches[10], fetches[11])
|
|
|
|
# Test clamp_ compatibility (functional inplace)
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestClamp_API(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.array([-1.0, 0.5, 2.0, 3.5]).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
# 1. Paddle positional arguments
|
|
x1 = paddle.to_tensor(self.np_x)
|
|
out1 = paddle.clamp_(x1, min=0.0, max=2.0)
|
|
|
|
# 2. Paddle keyword arguments
|
|
x2 = paddle.to_tensor(self.np_x)
|
|
out2 = paddle.clamp_(x=x2, min=0.0, max=2.0)
|
|
|
|
# 3. PyTorch keyword arguments (input alias)
|
|
x3 = paddle.to_tensor(self.np_x)
|
|
out3 = paddle.clamp_(input=x3, min=0.0, max=2.0)
|
|
|
|
# 4. Tensor method
|
|
x4 = paddle.to_tensor(self.np_x)
|
|
out4 = x4.clamp_(min=0.0, max=2.0)
|
|
|
|
expected = np.clip(self.np_x, 0.0, 2.0)
|
|
for out in [out1, out2, out3, out4]:
|
|
np.testing.assert_allclose(out.numpy(), expected)
|
|
# Verify inplace modification
|
|
np.testing.assert_allclose(x1.numpy(), expected)
|
|
np.testing.assert_allclose(x2.numpy(), expected)
|
|
np.testing.assert_allclose(x3.numpy(), expected)
|
|
np.testing.assert_allclose(x4.numpy(), expected)
|
|
|
|
# 5. Paddle positional args without keyword
|
|
x5 = paddle.to_tensor(self.np_x * 2)
|
|
expected5 = np.clip(self.np_x * 2, 0.0, 2.0)
|
|
out5 = paddle.clamp_(x5, 0.0, 2.0)
|
|
np.testing.assert_allclose(out5.numpy(), expected5)
|
|
np.testing.assert_allclose(x5.numpy(), expected5)
|
|
|
|
# 6. Mixed arguments
|
|
x6 = paddle.to_tensor(self.np_x * 2)
|
|
out6 = paddle.clamp_(x6, min=0.0, max=2.0)
|
|
np.testing.assert_allclose(out6.numpy(), expected5)
|
|
np.testing.assert_allclose(x6.numpy(), expected5)
|
|
|
|
paddle.enable_static()
|
|
|
|
# Inplace API no static graph test
|
|
|
|
|
|
# Test rms_norm compatibility
|
|
class TestRmsNormFnAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3, 4).astype("float16")
|
|
self.np_weight = np.ones(4).astype("float16")
|
|
self.np_x_fp32 = self.np_x.astype("float32")
|
|
self.np_weight_fp32 = self.np_weight.astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
if sys.platform == "win32":
|
|
return
|
|
if not paddle.device.is_compiled_with_cuda():
|
|
return
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
weight = paddle.to_tensor(self.np_weight)
|
|
|
|
# 1. Paddle Positional arguments
|
|
out1 = paddle.nn.functional.rms_norm(x, [4], weight)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.rms_norm(
|
|
input=x, normalized_shape=[4], weight=weight
|
|
)
|
|
# 3. PyTorch keyword arguments (alias)
|
|
out3 = paddle.nn.functional.rms_norm(
|
|
input=x, weight=weight, normalized_shape=[4]
|
|
)
|
|
|
|
for out in [out1, out2, out3]:
|
|
self.assertEqual(out.shape, x.shape)
|
|
self.assertEqual(out.dtype, paddle.float16)
|
|
|
|
# Numerical verification: rms_norm(x) = x / sqrt(mean(x^2) + eps) * weight
|
|
np_weight = self.np_weight_fp32.reshape(1, 1, 4)
|
|
np_rms = np.sqrt(
|
|
np.mean(self.np_x_fp32**2, axis=2, keepdims=True) + 1e-5
|
|
)
|
|
expected = self.np_x_fp32 / np_rms * np_weight
|
|
for out in [out1, out2, out3]:
|
|
np.testing.assert_allclose(
|
|
out.numpy(), expected, rtol=1e-2, atol=1e-2
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
if sys.platform == "win32":
|
|
return
|
|
if not paddle.device.is_compiled_with_cuda():
|
|
return
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[2, 3, 4], dtype="float16")
|
|
weight = paddle.static.data(
|
|
name="weight", shape=[4], dtype="float16"
|
|
)
|
|
|
|
out1 = paddle.nn.functional.rms_norm(x, [4], weight)
|
|
out2 = paddle.nn.functional.rms_norm(
|
|
input=x, normalized_shape=[4], weight=weight
|
|
)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": self.np_x, "weight": self.np_weight},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
np_weight = self.np_weight_fp32.reshape(1, 1, 4)
|
|
np_rms = np.sqrt(
|
|
np.mean(self.np_x_fp32**2, axis=2, keepdims=True) + 1e-5
|
|
)
|
|
expected = self.np_x_fp32 / np_rms * np_weight
|
|
for out in fetches:
|
|
np.testing.assert_allclose(out, expected, rtol=1e-2, atol=1e-2)
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestInstanceNormFnAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2025)
|
|
self.np_x = np.random.rand(2, 3, 4, 4).astype("float32")
|
|
self.np_weight = np.ones(3).astype("float32")
|
|
self.np_bias = np.zeros(3).astype("float32")
|
|
|
|
def test_dygraph_Compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor(self.np_x)
|
|
weight = paddle.to_tensor(self.np_weight)
|
|
bias = paddle.to_tensor(self.np_bias)
|
|
|
|
compat_in = paddle.compat.nn.functional.instance_norm
|
|
|
|
# 1. PyTorch-style positional arguments
|
|
out1 = compat_in(x, weight=weight, bias=bias)
|
|
# 2. PyTorch-style keyword arguments
|
|
out2 = compat_in(input=x, weight=weight, bias=bias)
|
|
# 3. Paddle-style positional
|
|
out3 = paddle.nn.functional.instance_norm(x, weight=weight, bias=bias)
|
|
|
|
for out in [out1, out2]:
|
|
self.assertEqual(out.shape, x.shape)
|
|
self.assertEqual(out.dtype, paddle.float32)
|
|
|
|
# Verify compat output matches native paddle
|
|
np.testing.assert_allclose(
|
|
out1.numpy(), out3.numpy(), rtol=1e-5, atol=1e-5
|
|
)
|
|
|
|
# 4. Verify result matches PyTorch numerical expectation
|
|
# Instance norm on [N,C,H,W]: compute mean/var per (N,C) plane
|
|
mean = x.mean(axis=(2, 3), keepdim=True)
|
|
var = x.var(axis=(2, 3), keepdim=True, unbiased=False)
|
|
expected = (x - mean) / (var + 1e-5).sqrt() * weight.reshape(
|
|
[1, 3, 1, 1]
|
|
) + bias.reshape([1, 3, 1, 1])
|
|
np.testing.assert_allclose(
|
|
out1.numpy(), expected.numpy(), rtol=1e-4, atol=1e-4
|
|
)
|
|
|
|
# 5. Test momentum conversion: torch momentum=0.1 -> paddle momentum=0.9
|
|
out_torch_momentum = compat_in(
|
|
input=x,
|
|
weight=weight,
|
|
bias=bias,
|
|
momentum=0.1,
|
|
)
|
|
out_paddle_momentum = paddle.nn.functional.instance_norm(
|
|
x,
|
|
weight=weight,
|
|
bias=bias,
|
|
momentum=0.9,
|
|
)
|
|
np.testing.assert_allclose(
|
|
out_torch_momentum.numpy(),
|
|
out_paddle_momentum.numpy(),
|
|
rtol=1e-5,
|
|
atol=1e-5,
|
|
)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(
|
|
name="x", shape=self.np_x.shape, dtype="float32"
|
|
)
|
|
weight = paddle.static.data(
|
|
name="weight", shape=[3], dtype="float32"
|
|
)
|
|
bias = paddle.static.data(name="bias", shape=[3], dtype="float32")
|
|
|
|
# 1. Paddle positional arguments
|
|
out1 = paddle.nn.functional.instance_norm(
|
|
x, weight=weight, bias=bias
|
|
)
|
|
# 2. Paddle keyword arguments
|
|
out2 = paddle.nn.functional.instance_norm(
|
|
x=x, weight=weight, bias=bias
|
|
)
|
|
|
|
exe = paddle.static.Executor()
|
|
fetches = exe.run(
|
|
feed={
|
|
"x": self.np_x,
|
|
"weight": self.np_weight,
|
|
"bias": self.np_bias,
|
|
},
|
|
fetch_list=[out1, out2],
|
|
)
|
|
for f in fetches:
|
|
self.assertEqual(f.shape, self.np_x.shape)
|
|
self.assertEqual(f.dtype, np.float32)
|
|
|
|
paddle.enable_static()
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestQrAPICompatibility(unittest.TestCase):
|
|
def test_dygraph_compatibility(self):
|
|
paddle.disable_static()
|
|
x = paddle.to_tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]).astype(
|
|
'float64'
|
|
)
|
|
|
|
# 1. Default mode (reduced)
|
|
q1, r1 = paddle.linalg.qr(x)
|
|
# 2. Paddle keyword arguments
|
|
q2, r2 = paddle.linalg.qr(x=x, mode='reduced')
|
|
# 3. PyTorch keyword arguments (alias)
|
|
q3, r3 = paddle.linalg.qr(input=x)
|
|
# 4. mode='r' returns single Tensor R
|
|
r4 = paddle.linalg.qr(x, mode='r')
|
|
self.assertEqual(r4.shape, [2, 2])
|
|
# 5. mode='complete'
|
|
q5, r5 = paddle.linalg.qr(x, mode='complete')
|
|
self.assertEqual(q5.shape, [3, 3])
|
|
self.assertEqual(r5.shape, [3, 2])
|
|
# 6. Tensor method
|
|
q6, r6 = x.qr()
|
|
# 7. Tensor method with mode='r' returns single Tensor R
|
|
r7 = x.qr('r')
|
|
self.assertEqual(r7.shape, [2, 2])
|
|
# 8. out parameter
|
|
q_out = paddle.empty([3, 2], dtype='float64')
|
|
r_out = paddle.empty([2, 2], dtype='float64')
|
|
result = paddle.linalg.qr(x, out=(q_out, r_out))
|
|
self.assertIs(result[0], q_out)
|
|
self.assertIs(result[1], r_out)
|
|
|
|
def test_static_Compatibility(self):
|
|
paddle.enable_static()
|
|
main = paddle.static.Program()
|
|
startup = paddle.static.Program()
|
|
with paddle.static.program_guard(main, startup):
|
|
x = paddle.static.data(name="x", shape=[3, 2], dtype="float64")
|
|
|
|
q1, r1 = paddle.linalg.qr(x)
|
|
q2, r2 = paddle.linalg.qr(x, mode='reduced')
|
|
q3, r3 = paddle.linalg.qr(input=x)
|
|
r4 = paddle.linalg.qr(x, mode='r')
|
|
|
|
exe = paddle.static.Executor()
|
|
np_x = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]).astype(
|
|
"float64"
|
|
)
|
|
fetches = exe.run(
|
|
main,
|
|
feed={"x": np_x},
|
|
fetch_list=[q1, r1, q2, r2, q3, r3, r4],
|
|
)
|
|
# Verify all Q match
|
|
for i in range(0, 6, 2):
|
|
np.testing.assert_allclose(fetches[0], fetches[i])
|
|
# Verify all R match
|
|
for i in range(1, 6, 2):
|
|
np.testing.assert_allclose(fetches[1], fetches[i])
|
|
# Verify mode='r' gives R
|
|
np.testing.assert_allclose(fetches[1], fetches[6])
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|