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

157 lines
5.4 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.
"""
神经网络实用工具测试 / Neural Network Utility Tests
测试目标 / Test Target:
paddle.nn.utils 神经网络工具函数
覆盖的模块 / Covered Modules:
- paddle.nn.utils.weight_norm: 权重归一化
- paddle.nn.utils.spectral_norm: 谱归一化
- paddle.nn.utils.remove_weight_norm: 移除权重归一化
- paddle.nn.utils.parameters_to_vector: 参数转向量
- paddle.nn.utils.vector_to_parameters: 向量转参数
作用 / Purpose:
补充神经网络工具函数的测试,提升覆盖率。
"""
import unittest
import numpy as np
import paddle
from paddle import nn
paddle.disable_static()
class TestWeightNorm(unittest.TestCase):
"""测试权重归一化 / Test weight normalization"""
def test_weight_norm_linear(self):
"""测试Linear层权重归一化 / Test weight norm on Linear layer"""
linear = nn.Linear(4, 8)
nn.utils.weight_norm(linear)
# After weight norm, layer has weight_g and weight_v
self.assertTrue(hasattr(linear, 'weight_g'))
self.assertTrue(hasattr(linear, 'weight_v'))
x = paddle.randn([2, 4])
y = linear(x)
self.assertEqual(y.shape, [2, 8])
def test_weight_norm_conv(self):
"""测试Conv层权重归一化 / Test weight norm on Conv layer"""
conv = nn.Conv2D(3, 8, 3)
nn.utils.weight_norm(conv)
x = paddle.randn([2, 3, 16, 16])
y = conv(x)
self.assertEqual(y.shape[0], 2)
def test_remove_weight_norm(self):
"""测试移除权重归一化 / Test remove weight norm"""
linear = nn.Linear(4, 8)
nn.utils.weight_norm(linear)
nn.utils.remove_weight_norm(linear)
# After removal, weight_g and weight_v should be gone
self.assertFalse(hasattr(linear, 'weight_g'))
class TestSpectralNorm(unittest.TestCase):
"""测试谱归一化 / Test spectral normalization"""
def test_spectral_norm_linear(self):
"""测试Linear层谱归一化 / Test spectral norm on Linear"""
linear = nn.Linear(4, 8)
nn.utils.spectral_norm(linear)
x = paddle.randn([2, 4])
y = linear(x)
self.assertEqual(y.shape, [2, 8])
def test_spectral_norm_conv(self):
"""测试Conv层谱归一化 / Test spectral norm on Conv"""
conv = nn.Conv2D(3, 8, 3)
nn.utils.spectral_norm(conv)
x = paddle.randn([2, 3, 16, 16])
y = conv(x)
self.assertEqual(y.shape[0], 2)
class TestParameterVector(unittest.TestCase):
"""测试参数向量转换 / Test parameter vector conversion"""
def test_parameters_to_vector(self):
"""测试参数转向量 / Test parameters to vector"""
model = nn.Sequential(nn.Linear(4, 8), nn.Linear(8, 2))
vec = nn.utils.parameters_to_vector(model.parameters())
# Total params = 4*8 + 8 + 8*2 + 2 = 32+8+16+2=58
self.assertEqual(vec.shape[0], 58)
def test_vector_to_parameters(self):
"""测试向量转参数 / Test vector to parameters"""
model = nn.Sequential(nn.Linear(4, 8), nn.Linear(8, 2))
# Create a new vector of the right size
total_params = sum(p.numel() for p in model.parameters())
vec = paddle.zeros([total_params])
nn.utils.vector_to_parameters(vec, model.parameters())
# All parameters should now be zero
for param in model.parameters():
np.testing.assert_allclose(
param.numpy(), np.zeros_like(param.numpy()), atol=1e-7
)
class TestClipGrad(unittest.TestCase):
"""测试梯度裁剪 / Test gradient clipping"""
def test_clip_grad_by_norm(self):
"""测试按范数裁剪梯度 / Test clip grad by norm"""
model = nn.Linear(4, 2)
x = paddle.randn([4, 4])
y = model(x)
loss = y.sum()
loss.backward()
# Get grads before clipping
grads_before = [
p.grad.numpy().copy()
for p in model.parameters()
if p.grad is not None
]
# Clip grads
paddle.nn.utils.clip_grad_norm_(model.parameters(), max_norm=0.1)
for p in model.parameters():
if p.grad is not None:
norm = np.linalg.norm(p.grad.numpy())
self.assertLessEqual(
norm, 0.11
) # slightly above due to float precision
def test_clip_grad_by_value(self):
"""测试按值裁剪梯度 / Test clip grad by value"""
model = nn.Linear(4, 2)
x = paddle.randn([4, 4])
y = model(x)
loss = y.sum()
loss.backward()
paddle.nn.utils.clip_grad_value_(model.parameters(), clip_value=0.5)
for p in model.parameters():
if p.grad is not None:
self.assertTrue(bool((p.grad.abs() <= 0.5001).all().numpy()))
if __name__ == '__main__':
unittest.main()