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

184 lines
6.1 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 Model Save/Load Tests
测试目标 / Test Target:
paddle 模型保存和加载功能
覆盖的模块 / Covered Modules:
- paddle.save/load: 张量和字典保存
- paddle.jit.save/load: JIT模型保存
- model.state_dict/set_state_dict: 模型状态
- paddle.Model.save/load: 高级模型API
作用 / Purpose:
补充模型持久化API的测试,提升覆盖率。
"""
import os
import tempfile
import unittest
import numpy as np
import paddle
from paddle import nn
paddle.disable_static()
class SimpleModel(nn.Layer):
"""简单测试模型 / Simple test model"""
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(4, 8)
self.fc2 = nn.Linear(8, 2)
def forward(self, x):
x = paddle.nn.functional.relu(self.fc1(x))
return self.fc2(x)
class TestModelStatDict(unittest.TestCase):
"""测试模型状态字典 / Test model state dict"""
def test_state_dict_keys(self):
"""测试状态字典键 / Test state dict keys"""
model = SimpleModel()
state_dict = model.state_dict()
self.assertIn('fc1.weight', state_dict)
self.assertIn('fc1.bias', state_dict)
self.assertIn('fc2.weight', state_dict)
self.assertIn('fc2.bias', state_dict)
def test_state_dict_shapes(self):
"""测试状态字典形状 / Test state dict shapes"""
model = SimpleModel()
state_dict = model.state_dict()
self.assertEqual(list(state_dict['fc1.weight'].shape), [4, 8])
self.assertEqual(list(state_dict['fc1.bias'].shape), [8])
def test_set_state_dict(self):
"""测试设置状态字典 / Test set state dict"""
model1 = SimpleModel()
model2 = SimpleModel()
# Copy weights from model1 to model2
state_dict = model1.state_dict()
model2.set_state_dict(state_dict)
# Verify weights are same
for key in state_dict:
np.testing.assert_allclose(
model1.state_dict()[key].numpy(),
model2.state_dict()[key].numpy(),
)
class TestSaveLoad(unittest.TestCase):
"""测试保存加载 / Test save and load"""
def test_save_load_tensor(self):
"""测试张量保存加载 / Test tensor save and load"""
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, 'tensor.pd')
x = paddle.randn([3, 4])
paddle.save(x, path)
loaded = paddle.load(path)
np.testing.assert_allclose(x.numpy(), loaded.numpy())
def test_save_load_dict(self):
"""测试字典保存加载 / Test dict save and load"""
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, 'data.pd')
data = {'weights': paddle.randn([4, 8]), 'bias': paddle.zeros([8])}
paddle.save(data, path)
loaded = paddle.load(path)
np.testing.assert_allclose(
data['weights'].numpy(), loaded['weights'].numpy()
)
np.testing.assert_allclose(
data['bias'].numpy(), loaded['bias'].numpy()
)
def test_save_load_model_weights(self):
"""测试模型权重保存加载 / Test model weights save and load"""
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, 'model.pd')
model = SimpleModel()
original_weights = {
k: v.numpy().copy() for k, v in model.state_dict().items()
}
paddle.save(model.state_dict(), path)
new_model = SimpleModel()
new_model.set_state_dict(paddle.load(path))
for key in original_weights:
np.testing.assert_allclose(
original_weights[key], new_model.state_dict()[key].numpy()
)
class TestJITSaveLoad(unittest.TestCase):
"""测试JIT保存加载 / Test JIT save and load"""
def test_jit_save_load(self):
"""测试JIT模型保存加载 / Test JIT model save and load"""
with tempfile.TemporaryDirectory() as tmpdir:
model = SimpleModel()
x = paddle.randn([2, 4])
# Save with JIT
save_path = os.path.join(tmpdir, 'model')
net = paddle.jit.to_static(
model,
input_spec=[
paddle.static.InputSpec(shape=[None, 4], dtype='float32')
],
)
paddle.jit.save(net, save_path)
# Load and run
loaded_model = paddle.jit.load(save_path)
result = loaded_model(x)
self.assertEqual(result.shape, [2, 2])
def test_jit_save_preserves_output(self):
"""测试JIT保存保留输出 / Test JIT save preserves output"""
with tempfile.TemporaryDirectory() as tmpdir:
model = SimpleModel()
model.eval()
x = paddle.randn([3, 4])
original_output = model(x)
save_path = os.path.join(tmpdir, 'model')
net = paddle.jit.to_static(
model,
input_spec=[
paddle.static.InputSpec(shape=[None, 4], dtype='float32')
],
)
paddle.jit.save(net, save_path)
loaded_model = paddle.jit.load(save_path)
loaded_output = loaded_model(x)
np.testing.assert_allclose(
original_output.numpy(), loaded_output.numpy(), rtol=1e-5
)
if __name__ == '__main__':
unittest.main()