162 lines
5.6 KiB
Python
162 lines
5.6 KiB
Python
# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""
|
|
矩阵操作高级测试 / Advanced Matrix Operations Tests
|
|
|
|
测试目标 / Test Target:
|
|
paddle.linalg 矩阵运算
|
|
|
|
覆盖的模块 / Covered Modules:
|
|
- paddle.matmul: 矩阵乘法
|
|
- paddle.linalg.norm: 范数计算
|
|
- paddle.linalg.cond: 条件数
|
|
- paddle.linalg.multi_dot: 多矩阵点乘
|
|
|
|
作用 / Purpose:
|
|
补充矩阵运算API的测试,提升覆盖率。
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestMatMul(unittest.TestCase):
|
|
"""测试矩阵乘法 / Test matrix multiplication"""
|
|
|
|
def test_matmul_2d(self):
|
|
"""测试2D矩阵乘法 / Test 2D matrix multiplication"""
|
|
A = paddle.to_tensor([[1.0, 2.0], [3.0, 4.0]])
|
|
B = paddle.to_tensor([[5.0, 6.0], [7.0, 8.0]])
|
|
result = paddle.matmul(A, B)
|
|
expected = np.array(
|
|
[[1 * 5 + 2 * 7, 1 * 6 + 2 * 8], [3 * 5 + 4 * 7, 3 * 6 + 4 * 8]],
|
|
dtype=np.float32,
|
|
)
|
|
np.testing.assert_allclose(result.numpy(), expected)
|
|
|
|
def test_matmul_batch(self):
|
|
"""测试批量矩阵乘法 / Test batched matrix multiplication"""
|
|
A = paddle.randn([4, 3, 4])
|
|
B = paddle.randn([4, 4, 5])
|
|
result = paddle.matmul(A, B)
|
|
self.assertEqual(result.shape, [4, 3, 5])
|
|
|
|
def test_matmul_transpose(self):
|
|
"""测试带转置的矩阵乘法 / Test matmul with transpose"""
|
|
A = paddle.randn([4, 3])
|
|
B = paddle.randn([4, 3])
|
|
result = paddle.matmul(A, B, transpose_y=True)
|
|
self.assertEqual(result.shape, [4, 4])
|
|
|
|
|
|
class TestNorms(unittest.TestCase):
|
|
"""测试范数计算 / Test norm computation"""
|
|
|
|
def test_vector_l2_norm(self):
|
|
"""测试向量L2范数 / Test vector L2 norm"""
|
|
x = paddle.to_tensor([3.0, 4.0])
|
|
result = paddle.linalg.norm(x)
|
|
self.assertAlmostEqual(float(result.numpy()), 5.0, places=5)
|
|
|
|
def test_matrix_frobenius_norm(self):
|
|
"""测试矩阵Frobenius范数 / Test matrix Frobenius norm"""
|
|
x = paddle.to_tensor([[1.0, 0.0], [0.0, 1.0]])
|
|
result = paddle.linalg.norm(x, p='fro')
|
|
self.assertAlmostEqual(float(result.numpy()), np.sqrt(2), places=5)
|
|
|
|
def test_vector_l1_norm(self):
|
|
"""测试向量L1范数 / Test vector L1 norm"""
|
|
x = paddle.to_tensor([-3.0, 4.0, -1.0])
|
|
result = paddle.linalg.norm(x, p=1)
|
|
self.assertAlmostEqual(float(result.numpy()), 8.0, places=5)
|
|
|
|
def test_norm_axis(self):
|
|
"""测试沿轴范数 / Test norm along axis"""
|
|
x = paddle.to_tensor([[3.0, 4.0], [0.0, 2.0]])
|
|
result = paddle.linalg.norm(x, axis=1)
|
|
np.testing.assert_allclose(result.numpy(), [5.0, 2.0], rtol=1e-5)
|
|
|
|
|
|
class TestLinalg(unittest.TestCase):
|
|
"""测试线性代数操作 / Test linear algebra operations"""
|
|
|
|
def test_multi_dot(self):
|
|
"""测试多矩阵连乘 / Test multi-dot product"""
|
|
A = paddle.randn([4, 8])
|
|
B = paddle.randn([8, 6])
|
|
C = paddle.randn([6, 2])
|
|
result = paddle.linalg.multi_dot([A, B, C])
|
|
self.assertEqual(result.shape, [4, 2])
|
|
|
|
def test_matrix_power(self):
|
|
"""测试矩阵幂 / Test matrix power"""
|
|
A = paddle.eye(3)
|
|
result = paddle.linalg.matrix_power(A, 3)
|
|
np.testing.assert_allclose(result.numpy(), np.eye(3))
|
|
|
|
def test_cross(self):
|
|
"""测试向量叉积 / Test vector cross product"""
|
|
x = paddle.to_tensor([[1.0, 0.0, 0.0]])
|
|
y = paddle.to_tensor([[0.0, 1.0, 0.0]])
|
|
result = paddle.cross(x, y)
|
|
np.testing.assert_allclose(result.numpy(), [[0.0, 0.0, 1.0]])
|
|
|
|
def test_dot(self):
|
|
"""测试向量点积 / Test dot product"""
|
|
x = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
y = paddle.to_tensor([4.0, 5.0, 6.0])
|
|
result = paddle.dot(x, y)
|
|
self.assertAlmostEqual(float(result.numpy()), 32.0, places=5)
|
|
|
|
def test_outer(self):
|
|
"""测试外积 / Test outer product"""
|
|
x = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
y = paddle.to_tensor([4.0, 5.0])
|
|
result = paddle.outer(x, y)
|
|
self.assertEqual(result.shape, [3, 2])
|
|
expected = np.outer([1.0, 2.0, 3.0], [4.0, 5.0])
|
|
np.testing.assert_allclose(result.numpy(), expected)
|
|
|
|
|
|
class TestSolveOperations(unittest.TestCase):
|
|
"""测试求解操作 / Test solve operations"""
|
|
|
|
def test_inv(self):
|
|
"""测试矩阵逆 / Test matrix inverse"""
|
|
A = paddle.to_tensor([[2.0, 1.0], [1.0, 1.0]])
|
|
A_inv = paddle.linalg.inv(A)
|
|
# A @ A_inv should be identity
|
|
identity = paddle.matmul(A, A_inv)
|
|
np.testing.assert_allclose(identity.numpy(), np.eye(2), atol=1e-5)
|
|
|
|
def test_qr_decomposition(self):
|
|
"""测试QR分解 / Test QR decomposition"""
|
|
A = paddle.randn([4, 3])
|
|
Q, R = paddle.linalg.qr(A)
|
|
self.assertEqual(Q.shape, [4, 3])
|
|
self.assertEqual(R.shape, [3, 3])
|
|
# Q should be orthogonal: Q^T @ Q = I
|
|
QtQ = paddle.matmul(Q.t(), Q)
|
|
np.testing.assert_allclose(QtQ.numpy(), np.eye(3), atol=1e-5)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|