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

1619 lines
57 KiB
Python

# Copyright (c) 2018 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 unittest
from collections import OrderedDict
import paddle
from paddle import Tensor, nn
class Module(nn.Module):
# class Module(nn.Layer):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class SubModule(nn.Module):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.linear = nn.Linear(10, 5)
class SubModule1(nn.Module):
def __init__(self, input_size=10, output_size=5):
super().__init__()
self.linear = nn.Linear(input_size, output_size)
self.activation = nn.ReLU()
self.register_buffer('running_mean', paddle.zeros([output_size]))
def forward(self, x):
out = self.linear(x)
out = self.activation(out)
return out
class NestedModule(nn.Module):
def __init__(self):
super().__init__()
self.layer1 = SubModule1(10, 8)
self.layer2 = SubModule1(8, 6)
self.layer3 = SubModule1(6, 4)
self.final_layer = nn.Linear(4, 2)
class TestRegisterBuffer(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_register_buffer_basic(self):
buffer_tensor = paddle.to_tensor([1.0, 2.0, 3.0])
self.module.register_buffer('test_buffer', buffer_tensor)
self.assertTrue(hasattr(self.module, 'test_buffer'))
self.assertIn('test_buffer', self.module._buffers)
all_buffers = list(self.module.buffers(recurse=True))
self.assertTrue(len(all_buffers) > 0)
self.assertTrue(any(isinstance(b, paddle.Tensor) for b in all_buffers))
def test_register_buffer_persistent(self):
persistent_buffer = paddle.to_tensor([4.0, 5.0, 6.0])
self.module.register_buffer(
'persistent_buf', persistent_buffer, persistent=True
)
self.assertIn('persistent_buf', self.module._buffers)
self.assertNotIn(
'persistent_buf', self.module._non_persistent_buffers_set
)
def test_register_buffer_non_persistent(self):
non_persistent_buffer = paddle.to_tensor([7.0, 8.0, 9.0])
self.module.register_buffer(
'non_persistent_buf', non_persistent_buffer, persistent=False
)
self.assertIn('non_persistent_buf', self.module._buffers)
self.assertIn(
'non_persistent_buf', self.module._non_persistent_buffers_set
)
class TestRegisterParameter(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_register_parameter_basic(self):
param_tensor = paddle.to_tensor([1.0, 2.0, 3.0], stop_gradient=False)
param = nn.Parameter(param_tensor)
self.module.register_parameter('test_param', param)
self.assertTrue(hasattr(self.module, 'test_param'))
self.assertIn('test_param', self.module._parameters)
self.assertTrue(paddle.allclose(self.module.test_param, param))
self.assertTrue(self.module.test_param.trainable)
def test_register_parameter_none(self):
self.module.register_parameter('none_param', None)
self.assertTrue(hasattr(self.module, 'none_param'))
self.assertIn('none_param', self.module._parameters)
self.assertIsNone(self.module.none_param)
def test_register_parameter_with_tensor(self):
param_tensor = paddle.to_tensor([1.0, 2.0, 3.0], stop_gradient=False)
self.module.register_parameter('test_param', nn.Parameter(param_tensor))
self.assertIn('test_param', self.module._parameters)
self.assertIsInstance(self.module.test_param, nn.Parameter)
self.assertTrue(paddle.allclose(self.module.test_param, param_tensor))
class TestAddModule(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_add_module_basic(self):
submodule = nn.Linear(10, 5)
self.module.add_module('linear', submodule)
self.assertTrue(hasattr(self.module, 'linear'))
self.assertIn('linear', self.module._modules)
self.assertEqual(self.module.linear, submodule)
self.assertIsInstance(self.module.linear, nn.Linear)
def test_register_module_basic(self):
submodule = nn.Linear(10, 5)
self.module.register_module('linear', submodule)
self.assertTrue(hasattr(self.module, 'linear'))
self.assertIn('linear', self.module._modules)
self.assertEqual(self.module.linear, submodule)
self.assertIsInstance(self.module.linear, nn.Linear)
def test_add_module_none(self):
self.module.add_module('empty_module', None)
self.assertTrue(hasattr(self.module, 'empty_module'))
self.assertIn('empty_module', self.module._modules)
self.assertIsNone(self.module.empty_module)
def test_add_module_hierarchy(self):
child_module = SubModule()
self.module.add_module('child', child_module)
self.assertIn('child', self.module._modules)
self.assertIn('linear', child_module._modules)
self.assertIsInstance(child_module.linear, nn.Linear)
def test_module_forward(self):
submodule = nn.Linear(10, 5)
self.module.add_module('linear', submodule)
input_tensor = paddle.ones([2, 10])
output = self.module.linear(input_tensor)
self.assertEqual(output.shape, [2, 5])
self.assertIsInstance(output, Tensor)
class TestGetSubmodule(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_get_submodule_basic(self):
submodule = nn.Linear(10, 5)
self.module.add_module('linear', submodule)
retrieved_module = self.module.get_submodule('linear')
self.assertEqual(retrieved_module, submodule)
self.assertIsInstance(retrieved_module, nn.Linear)
def test_get_submodule_nested(self):
nested_module = NestedModule()
self.module.add_module('nested', nested_module)
test_cases = [
'nested',
'nested.layer1',
'nested.layer1.linear',
'nested.layer2.activation',
'nested.final_layer',
]
for target in test_cases:
with self.subTest(target=target):
module = self.module.get_submodule(target)
self.assertIsInstance(module, nn.Module)
def test_get_submodule_empty_target(self):
result = self.module.get_submodule('')
self.assertEqual(result, self.module)
def test_get_parameter_basic(self):
param_tensor = paddle.to_tensor([1.0, 2.0, 3.0], stop_gradient=False)
param = nn.Parameter(param_tensor)
self.module.register_parameter('test_param', param)
retrieved_param = self.module.get_parameter('test_param')
self.assertIs(retrieved_param, param)
self.assertIsInstance(retrieved_param, nn.Parameter)
self.assertTrue(paddle.allclose(retrieved_param, param_tensor))
def test_get_parameter_nested(self):
nested_module = NestedModule()
self.module.add_module('nested', nested_module)
test_cases = [
'nested.layer1.linear.weight',
'nested.layer1.linear.bias',
'nested.final_layer.weight',
'nested.final_layer.bias',
]
for target in test_cases:
with self.subTest(target=target):
param = self.module.get_parameter(target)
self.assertIsInstance(param, nn.Parameter)
self.assertTrue(param.trainable)
def test_get_parameter_vs_get_submodule(self):
nested_module = NestedModule()
self.module.add_module('nested', nested_module)
module = self.module.get_submodule('nested.layer1.linear')
self.assertIsInstance(module, nn.Linear)
weight_param = self.module.get_parameter('nested.layer1.linear.weight')
self.assertIsInstance(weight_param, nn.Parameter)
self.assertTrue(paddle.allclose(weight_param, module.weight))
def test_get_parameter_gradients(self):
nested_module = NestedModule()
self.module.add_module('nested', nested_module)
param = self.module.get_parameter('nested.layer1.linear.weight')
x = paddle.ones([1, 10])
y = nested_module.layer1.linear(x)
loss = y.sum()
loss.backward()
self.assertIsNotNone(param.grad)
self.assertEqual(param.grad.shape, param.shape)
def test_get_submodule_error(self):
with self.assertRaises(AttributeError):
self.module.get_submodule('invalid_name')
def test_get_parameter_reeor(self):
with self.assertRaises(AttributeError) as cm:
self.module.get_parameter("nonexistent_param")
self.assertIn("has no attribute `nonexistent_param`", str(cm.exception))
self.module.fake_attr = "I am not a parameter"
with self.assertRaises(AttributeError) as cm:
self.module.get_parameter("fake_attr")
self.assertIn("`fake_attr` is not an nn.Parameter", str(cm.exception))
self.module.register_buffer(
"fake_param", paddle.to_tensor([1.0, 2.0, 3.0])
)
with self.assertRaises(AttributeError) as cm:
self.module.get_parameter("fake_param")
self.assertIn("`fake_param` is not an nn.Parameter", str(cm.exception))
def test_get_extra_state_raises(self):
with self.assertRaises(RuntimeError) as cm:
self.module.get_extra_state()
class TestSetSubmodule(unittest.TestCase):
def setUp(self):
self.module = NestedModule()
def test_replace_top_level(self):
new_module = SubModule1(8, 6)
self.module.set_submodule("layer2", new_module)
self.assertIs(self.module.layer2, new_module)
def test_replace_nested_submodule(self):
new_linear = nn.Linear(6, 4)
self.module.set_submodule("layer3.linear", new_linear)
self.assertIs(self.module.layer3.linear, new_linear)
def test_add_new_non_strict(self):
new_mod = nn.Linear(10, 10)
self.module.set_submodule("extra", new_mod)
self.assertIs(self.module.extra, new_mod)
def test_strict_missing_attr_raises(self):
new_mod = nn.Linear(1, 1)
with self.assertRaises(AttributeError):
self.module.set_submodule("not_exist", new_mod, strict=True)
def test_non_module_input_raises(self):
with self.assertRaises(ValueError):
self.module.set_submodule("layer1", "not_a_module")
def test_empty_target_raises(self):
with self.assertRaises(ValueError):
self.module.set_submodule("", nn.Linear(1, 1))
def test_non_module_attr_raises(self):
self.module.some_value = 10
with self.assertRaises(AttributeError):
self.module.set_submodule("some_value", nn.Linear(1, 1))
class TestLoadStateDict(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_load_state_dict_basic(self):
self.module.register_parameter(
'custom_param', nn.Parameter(paddle.ones([3, 3]))
)
self.module.register_buffer('custom_buffer', paddle.zeros([2, 2]))
original_state = self.module.state_dict()
with paddle.no_grad():
self.module.custom_param.set_value(
self.module.custom_param * 2 + 1.0
)
self.module.custom_buffer.set_value(paddle.ones([2, 2]))
result = self.module.load_state_dict(original_state)
current_state = self.module.state_dict()
for key in original_state:
self.assertTrue(
paddle.allclose(original_state[key], current_state[key])
)
self.assertEqual(len(result.missing_keys), 0)
self.assertEqual(len(result.unexpected_keys), 0)
def test_load_state_dict_strict_mode(self):
self.module.register_parameter(
'test_param', nn.Parameter(paddle.ones([3]))
)
original_state = self.module.state_dict()
modified_state = original_state.copy()
modified_state['extra_param'] = paddle.ones([5])
modified_state.pop('test_param')
with self.assertRaises(RuntimeError) as context:
self.module.load_state_dict(modified_state, strict=True)
error_msg = str(context.exception)
self.assertIn("Missing key(s)", error_msg)
self.assertIn("Unexpected key(s)", error_msg)
def test_load_state_dict_non_strict_mode(self):
self.module.register_parameter('param1', nn.Parameter(paddle.ones([3])))
self.module.register_buffer('buffer1', paddle.zeros([2]))
original_state = self.module.state_dict()
modified_state = original_state.copy()
modified_state['extra_param'] = paddle.ones([5])
modified_state.pop('buffer1')
result = self.module.load_state_dict(modified_state, strict=False)
self.assertIn('buffer1', result.missing_keys)
self.assertIn('extra_param', result.unexpected_keys)
self.assertTrue(paddle.allclose(self.module.param1, paddle.ones([3])))
def test_load_state_dict_assign(self):
self.module.register_parameter('weight', nn.Parameter(paddle.ones([1])))
self.module.register_buffer('buffer', paddle.ones([1]))
old_weight = self.module.weight
old_buffer = self.module.buffer
self.module.weight.trainable = False
state_weight = nn.Parameter(paddle.full([1], 3.0))
state_dict = {
'weight': state_weight,
'buffer': paddle.full([1], 5.0),
}
result = self.module.load_state_dict(state_dict, assign=True)
self.assertIs(self.module.weight, state_weight)
self.assertIs(self.module.buffer, state_dict['buffer'])
self.assertTrue(
paddle.allclose(self.module.weight, state_dict['weight'])
)
self.assertTrue(
paddle.allclose(self.module.buffer, state_dict['buffer'])
)
self.assertFalse(self.module.weight.trainable)
self.assertIsNot(self.module.weight, old_weight)
self.assertIsNot(self.module.buffer, old_buffer)
self.assertEqual(len(result.missing_keys), 0)
self.assertEqual(len(result.unexpected_keys), 0)
class TestNamedParameters(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_named_parameters_basic(self):
param1 = paddle.create_parameter([3, 4], dtype='float32')
param2 = paddle.create_parameter([2, 2], dtype='float32')
self.module.register_parameter('weight', param1)
self.module.register_parameter('bias', param2)
named_params = dict(self.module.named_parameters())
self.assertIn('weight', named_params)
self.assertIn('bias', named_params)
self.assertEqual(len(named_params), 2)
self.assertTrue(paddle.allclose(named_params['weight'], param1))
self.assertTrue(paddle.allclose(named_params['bias'], param2))
def test_named_parameters_with_prefix(self):
param = paddle.create_parameter([5], dtype='float32')
self.module.register_parameter('test_param', param)
names_without_prefix = [
name for name, _ in self.module.named_parameters(prefix="")
]
self.assertEqual(names_without_prefix, ['test_param'])
names_with_prefix = [
name for name, _ in self.module.named_parameters(prefix="module")
]
self.assertEqual(names_with_prefix, ['module.test_param'])
def test_named_parameters_recurse_false(self):
sublayer = nn.Linear(10, 5)
self.module.add_sublayer('linear', sublayer)
main_param = paddle.create_parameter([3], dtype='float32')
self.module.register_parameter('main_param', main_param)
non_recurse_names = [
name for name, _ in self.module.named_parameters(recurse=False)
]
self.assertEqual(non_recurse_names, ['main_param'])
recurse_names = [
name for name, _ in self.module.named_parameters(recurse=True)
]
self.assertIn('main_param', recurse_names)
self.assertIn('linear.weight', recurse_names)
self.assertIn('linear.bias', recurse_names)
def test_named_parameters_remove_duplicate(self):
shared_param = paddle.create_parameter([4, 4], dtype='float32')
self.module.register_parameter('weight1', shared_param)
self.module.register_parameter('weight2', shared_param)
without_duplicate = list(
self.module.named_parameters(remove_duplicate=False)
)
names_no_dedup = [name for name, _ in without_duplicate]
self.assertEqual(len(names_no_dedup), 2)
self.assertIn('weight1', names_no_dedup)
self.assertIn('weight2', names_no_dedup)
param_dict = dict(without_duplicate)
self.assertIs(param_dict['weight1'], param_dict['weight2'])
with_duplicate = list(
self.module.named_parameters(remove_duplicate=True)
)
names_dedup = [name for name, _ in with_duplicate]
self.assertEqual(len(names_dedup), 1)
self.assertIn('weight1', names_dedup)
def test_named_parameters_empty_module(self):
named_params = list(self.module.named_parameters())
self.assertEqual(len(named_params), 0)
def test_named_parameters_complex_hierarchy(self):
child1 = nn.Linear(10, 8)
child2 = nn.Linear(8, 6)
child1.add_sublayer('child2', child2)
self.module.add_sublayer('child1', child1)
self.module.register_parameter(
'global_param', paddle.create_parameter([3], dtype='float32')
)
all_names = [name for name, _ in self.module.named_parameters()]
expected_names = [
'global_param',
'child1.weight',
'child1.bias',
'child1.child2.weight',
'child1.child2.bias',
]
self.assertEqual(set(all_names), set(expected_names))
self.assertEqual(len(all_names), len(expected_names))
def test_named_parameters_with_buffers(self):
param = paddle.create_parameter([5], dtype='float32')
buffer = paddle.to_tensor([1, 2, 3])
self.module.register_parameter('param', param)
self.module.register_buffer('buffer', buffer)
param_names = [name for name, _ in self.module.named_parameters()]
buffer_names = [name for name, _ in self.module.named_buffers()]
self.assertEqual(param_names, ['param'])
self.assertEqual(buffer_names, ['buffer'])
self.assertNotIn('buffer', param_names)
self.assertNotIn('param', buffer_names)
class TestNamedModules(unittest.TestCase):
def setUp(self):
self.module = Module()
def test_modules_basic(self):
child1 = SubModule()
child2 = nn.ReLU()
self.module.add_sublayer('submodule', child1)
self.module.add_sublayer('activation', child2)
modules = list(self.module.modules())
self.assertEqual(len(modules), 4)
def test_named_modules_basic(self):
child1 = SubModule()
child2 = nn.ReLU()
self.module.add_sublayer('submodule', child1)
self.module.add_sublayer('activation', child2)
named_modules = dict(self.module.named_modules())
self.assertIn('', named_modules)
self.assertIn('submodule', named_modules)
self.assertIn('activation', named_modules)
self.assertIn('submodule.linear', named_modules)
self.assertEqual(len(named_modules), 4)
self.assertIs(named_modules[''], self.module)
self.assertIs(named_modules['submodule'], child1)
self.assertIs(named_modules['activation'], child2)
self.assertIs(named_modules['submodule.linear'], child1.linear)
def test_named_modules_with_prefix(self):
child = SubModule()
self.module.add_sublayer('child', child)
names_without_prefix = [
name for name, _ in self.module.named_modules(prefix="")
]
self.assertIn('', names_without_prefix)
self.assertIn('child', names_without_prefix)
self.assertIn('child.linear', names_without_prefix)
names_with_prefix = [
name for name, _ in self.module.named_modules(prefix="model")
]
self.assertIn('model', names_with_prefix)
self.assertIn('model.child', names_with_prefix)
self.assertIn('model.child.linear', names_with_prefix)
self.assertNotIn('', names_with_prefix)
def test_named_modules_memo_parameter(self):
nested_module = NestedModule()
self.module.add_sublayer('nested', nested_module)
memo_set = set()
first_pass = list(self.module.named_modules(memo=memo_set))
self.assertIn(self.module, memo_set)
self.assertIn(nested_module, memo_set)
self.assertIn(nested_module.layer1, memo_set)
second_pass = list(self.module.named_modules(memo=memo_set))
self.assertEqual(len(second_pass), 0)
def test_named_modules_remove_duplicate(self):
shared_module = nn.Dropout(0.5)
self.module.add_sublayer('dropout1', shared_module)
self.module.add_sublayer('dropout2', shared_module)
without_dedup = list(self.module.named_modules(remove_duplicate=False))
names_no_dedup = [name for name, _ in without_dedup]
self.assertEqual(len(names_no_dedup), 3)
self.assertIn('dropout1', names_no_dedup)
self.assertIn('dropout2', names_no_dedup)
module_dict = dict(without_dedup)
self.assertIs(module_dict['dropout1'], module_dict['dropout2'])
with_dedup = list(self.module.named_modules(remove_duplicate=True))
names_dedup = [name for name, _ in with_dedup]
self.assertEqual(len(names_dedup), 2)
dropout_names = [name for name in names_dedup if 'dropout' in name]
self.assertEqual(len(dropout_names), 1)
def test_named_modules_complex_hierarchy(self):
nested_module = NestedModule()
self.module.add_sublayer('complex', nested_module)
all_modules = dict(self.module.named_modules())
expected_paths = {
'',
'complex',
'complex.layer1',
'complex.layer2',
'complex.layer3',
'complex.final_layer',
'complex.layer1.linear',
'complex.layer1.activation',
'complex.layer2.linear',
'complex.layer2.activation',
'complex.layer3.linear',
'complex.layer3.activation',
}
self.assertEqual(set(all_modules.keys()), expected_paths)
self.assertIs(all_modules[''], self.module)
self.assertIs(all_modules['complex'], nested_module)
self.assertIs(all_modules['complex.layer1'], nested_module.layer1)
self.assertIs(
all_modules['complex.layer1.linear'], nested_module.layer1.linear
)
self.assertIs(
all_modules['complex.final_layer'], nested_module.final_layer
)
def test_named_modules_empty_module(self):
named_modules = list(self.module.named_modules())
self.assertEqual(len(named_modules), 1)
self.assertEqual(named_modules[0][0], '')
self.assertIs(named_modules[0][1], self.module)
class TestGetBuffer(unittest.TestCase):
def setUp(self):
self.model = NestedModule()
def test_get_existing_buffer(self):
buf = self.model.get_buffer("layer1.running_mean")
self.assertIsInstance(buf, paddle.Tensor)
self.assertTrue(paddle.allclose(buf, paddle.zeros([8])))
def test_get_nested_buffer(self):
buf = self.model.get_buffer("layer2.running_mean")
self.assertEqual(buf.shape[0], 6)
def test_get_final_layer_error(self):
with self.assertRaises(AttributeError):
_ = self.model.get_buffer("final_layer.bias")
def test_nonexistent_layer_error(self):
with self.assertRaises(AttributeError):
_ = self.model.get_buffer("nonexistent.running_mean")
def test_nonexistent_buffer_error(self):
with self.assertRaises(AttributeError):
_ = self.model.get_buffer("layer1.not_a_buffer")
class TestModuleDeviceTransfer(unittest.TestCase):
def setUp(self):
self.model = NestedModule()
@unittest.skipIf(
not paddle.is_compiled_with_cuda(), "Paddle not compiled with CUDA"
)
def test_cuda(self):
model_gpu = self.model.cuda()
for name, p in model_gpu.named_parameters():
self.assertTrue(
p.place.is_gpu_place(), f"{name} not on GPU with device=None"
)
for name, b in model_gpu.named_buffers():
self.assertTrue(
b.place.is_gpu_place(),
f"{name} buffer not on GPU with device=None",
)
model_gpu = self.model.cuda(0)
for name, p in model_gpu.named_parameters():
self.assertTrue(
p.place.is_gpu_place(), f"{name} not on GPU when using index 0"
)
for name, b in model_gpu.named_buffers():
self.assertTrue(
b.place.is_gpu_place(), f"{name} buffer not on GPU with index 0"
)
cuda_place = paddle.CUDAPlace(0)
model_gpu = self.model.cuda(cuda_place)
for name, p in model_gpu.named_parameters():
self.assertTrue(
p.place.is_gpu_place(),
f"{name} not on GPU when using CUDAPlace",
)
for name, b in model_gpu.named_buffers():
self.assertTrue(
b.place.is_gpu_place(),
f"{name} buffer not on GPU when using CUDAPlace",
)
with self.assertRaises(TypeError):
self.model.cuda("gpu:0")
@unittest.skipIf(
not hasattr(paddle, "is_compiled_with_xpu")
or not paddle.is_compiled_with_xpu(),
"Paddle not built with XPU",
)
def test_xpu(self):
model_xpu = self.model.xpu()
for name, p in model_xpu.named_parameters():
self.assertTrue(
p.place.is_xpu_place(), f"{name} not moved to XPU (device=None)"
)
for name, b in model_xpu.named_buffers():
self.assertTrue(
b.place.is_xpu_place(),
f"{name} buffer not moved to XPU (device=None)",
)
model_xpu = self.model.xpu(0)
for name, p in model_xpu.named_parameters():
self.assertTrue(
p.place.is_xpu_place(), f"{name} not moved to XPU (device=0)"
)
for name, b in model_xpu.named_buffers():
self.assertTrue(
b.place.is_xpu_place(),
f"{name} buffer not moved to XPU (device=0)",
)
xpu_place = paddle.XPUPlace(0)
model_xpu = self.model.xpu(xpu_place)
for name, p in model_xpu.named_parameters():
self.assertTrue(
p.place.is_xpu_place(), f"{name} not moved to XPU (XPUPlace)"
)
for name, b in model_xpu.named_buffers():
self.assertTrue(
b.place.is_xpu_place(),
f"{name} buffer not moved to XPU (XPUPlace)",
)
with self.assertRaises(TypeError):
self.model.xpu("xpu:0")
def test_cpu(self):
model_cpu = self.model.cpu()
for name, p in model_cpu.named_parameters():
self.assertTrue(p.place.is_cpu_place(), f"{name} not on CPU")
for name, b in model_cpu.named_buffers():
self.assertTrue(b.place.is_cpu_place(), f"{name} buffer not on CPU")
class TestType(unittest.TestCase):
def setUp(self):
self.module = Module()
self.module.linear = nn.Linear(3, 2)
self.module.bn = nn.BatchNorm1D(2)
self.module.register_parameter(
'weight',
paddle.create_parameter(
shape=[5, 3],
dtype=paddle.float32,
default_initializer=nn.initializer.Constant(1.0),
),
)
self.module.register_buffer(
'buffer', paddle.ones([3, 2], dtype=paddle.float32)
)
def test_type(self):
self.module.type(paddle.float64)
self.assertEqual(self.module.weight.dtype, paddle.float64)
self.assertEqual(self.module.buffer.dtype, paddle.float64)
self.module.type('int8')
self.assertEqual(self.module.weight.dtype, paddle.int8)
self.assertEqual(self.module.buffer.dtype, paddle.int8)
for name, param in self.module.named_parameters():
self.assertEqual(param.dtype, paddle.int8)
for name, buf in self.module.named_buffers():
self.assertEqual(buf.dtype, paddle.int8)
def test_double(self):
self.module.double()
self.assertEqual(self.module.weight.dtype, paddle.float64)
self.assertEqual(self.module.buffer.dtype, paddle.float64)
def test_half(self):
self.module.half()
self.assertEqual(self.module.weight.dtype, paddle.float16)
self.assertEqual(self.module.buffer.dtype, paddle.float16)
def test_type_error(self):
with self.assertRaises(ValueError):
self.module.type("invalid_dtype")
class TestStateDict(unittest.TestCase):
def setUp(self):
self.model = NestedModule()
self.model1 = SubModule()
def test_state_dict_basic(self):
state = self.model.state_dict()
self.assertIsInstance(state, OrderedDict)
self.assertGreater(len(state), 0)
def test_state_dict_contains_buffers(self):
state = self.model.state_dict()
buffer_keys = [k for k in state.keys() if "running_mean" in k]
self.assertTrue(len(buffer_keys) > 0)
for k in buffer_keys:
self.assertIn("running_mean", k)
self.assertTrue(isinstance(state[k], paddle.Tensor))
def test_state_dict_prefix_structure(self):
state = self.model.state_dict()
expected_prefixes = [
"layer1.linear.weight",
"layer2.linear.weight",
"layer3.linear.weight",
"final_layer.weight",
]
for prefix in expected_prefixes:
match = [k for k in state.keys() if k.startswith(prefix)]
self.assertTrue(len(match) > 0, f"Missing prefix: {prefix}")
def test_state_dict_keep_vars(self):
state1 = self.model1.state_dict(keep_vars=True)
state2 = self.model1.state_dict(keep_vars=False)
for k in state1.keys():
if hasattr(state1[k], "stop_gradient"):
self.assertFalse(state1[k].stop_gradient)
self.assertTrue(state2[k].stop_gradient)
def test_state_dict_with_positional_args(self):
sd_default = self.model.state_dict()
self.assertIsInstance(sd_default, dict)
dest = {}
sd1 = self.model.state_dict(dest)
self.assertIsInstance(sd1, dict)
sd2 = self.model.state_dict({}, "wfs")
self.assertIsInstance(sd2, dict)
sd3 = self.model.state_dict({}, False, "wfs")
self.assertIsInstance(sd3, dict)
sd4 = self.model.state_dict({}, "wfs", False)
self.assertIsInstance(sd4, dict)
sd5 = self.model.state_dict({}, False, "wfs", False, False)
self.assertIsInstance(sd5, dict)
class TestTrain(unittest.TestCase):
def setUp(self):
self.model = NestedModule()
def test_train_sets_training_true(self):
self.model.train(True)
self.assertTrue(self.model.training)
for name, submodule in self.model.named_children():
self.assertTrue(submodule.training, f"{name} not in training mode")
def test_train_sets_training_false(self):
self.model.train(False)
self.assertFalse(self.model.training)
for name, submodule in self.model.named_children():
self.assertFalse(submodule.training, f"{name} not in eval mode")
def test_train_invalid_argument(self):
with self.assertRaises(ValueError):
self.model.train("True")
class TestGrad(unittest.TestCase):
def setUp(self):
self.model = SubModule1(10, 5)
def test_requires_grad(self):
for p in self.model.parameters():
self.assertFalse(p.stop_gradient)
self.model.requires_grad_(False)
for p in self.model.parameters():
self.assertTrue(p.stop_gradient)
self.model.requires_grad_(True)
for p in self.model.parameters():
self.assertFalse(p.stop_gradient)
def test_zero_grad(self):
x = paddle.randn([4, 10])
y = self.model(x).sum()
y.backward()
for p in self.model.parameters():
self.assertIsNotNone(p.grad)
self.model.zero_grad(set_to_none=False)
for p in self.model.parameters():
self.assertIsNotNone(p.grad)
self.assertTrue(paddle.allclose(p.grad, paddle.zeros_like(p.grad)))
self.model.zero_grad()
for p in self.model.parameters():
self.assertIsNone(p.grad)
# test ModuleList
class TestModuleListBasic(unittest.TestCase):
def test_initialization_empty(self):
module_list = nn.ModuleList()
self.assertEqual(len(module_list), 0)
self.assertEqual(list(module_list), [])
def test_initialization_with_modules(self):
modules = [nn.Linear(10, 5), nn.ReLU(), nn.Dropout(0.5)]
module_list = nn.ModuleList(modules)
self.assertEqual(len(module_list), 3)
self.assertIsInstance(module_list[0], nn.Linear)
self.assertIsInstance(module_list[1], nn.ReLU)
self.assertIsInstance(module_list[2], nn.Dropout)
def test_get_abs_string_index(self):
modules = [nn.Linear(10, 5), nn.ReLU(), nn.Dropout(0.5)]
module_list = nn.ModuleList(modules)
self.assertEqual(module_list._get_abs_string_index(0), "0")
self.assertEqual(module_list._get_abs_string_index(1), "1")
self.assertEqual(module_list._get_abs_string_index(-1), "2")
self.assertEqual(module_list._get_abs_string_index(-2), "1")
def test_get_abs_string_index_out_of_range(self):
module_list = nn.ModuleList([nn.Linear(10, 5)])
with self.assertRaises(IndexError):
module_list._get_abs_string_index(1)
with self.assertRaises(IndexError):
module_list._get_abs_string_index(-2)
class TestModuleListDir(unittest.TestCase):
def test_dir_filters_numeric_keys(self):
module_list = nn.ModuleList([nn.Linear(10, 5), nn.ReLU()])
module_list.extra = nn.Linear(5, 2)
d = dir(module_list)
self.assertIn("extra", d)
self.assertNotIn("0", d)
self.assertNotIn("1", d)
class TestModuleListIndexing(unittest.TestCase):
def setUp(self):
self.modules = [nn.Linear(10, 5), nn.ReLU(), nn.Dropout(0.5), nn.Tanh()]
self.module_list = nn.ModuleList(self.modules)
def test_getitem_int(self):
self.assertIs(self.module_list[0], self.modules[0])
self.assertIs(self.module_list[1], self.modules[1])
self.assertIs(self.module_list[-1], self.modules[3])
self.assertIs(self.module_list[-2], self.modules[2])
def test_getitem_slice(self):
# Test basic slicing
slice_result = self.module_list[1:3]
self.assertIsInstance(slice_result, nn.ModuleList)
self.assertEqual(len(slice_result), 2)
self.assertIs(slice_result[0], self.modules[1])
self.assertIs(slice_result[1], self.modules[2])
# Test step slicing
slice_step = self.module_list[::2]
self.assertEqual(len(slice_step), 2)
self.assertIs(slice_step[0], self.modules[0])
self.assertIs(slice_step[1], self.modules[2])
# Test negative slicing
slice_neg = self.module_list[-2:]
self.assertEqual(len(slice_neg), 2)
self.assertIs(slice_neg[0], self.modules[2])
self.assertIs(slice_neg[1], self.modules[3])
def test_setitem(self):
new_module = nn.Sigmoid()
self.module_list[1] = new_module
self.assertIs(self.module_list[1], new_module)
self.assertIsNot(self.module_list[1], self.modules[1])
def test_setitem_negative_index(self):
new_module = nn.ELU()
self.module_list[-1] = new_module
self.assertIs(self.module_list[3], new_module)
def test_delitem_int(self):
original_length = len(self.module_list)
del self.module_list[1]
self.assertEqual(len(self.module_list), original_length - 1)
self.assertIs(self.module_list[0], self.modules[0])
self.assertIs(self.module_list[1], self.modules[2])
self.assertIs(self.module_list[2], self.modules[3])
def test_delitem_slice(self):
# Delete middle slice
del self.module_list[1:3]
self.assertEqual(len(self.module_list), 2)
self.assertIs(self.module_list[0], self.modules[0])
self.assertIs(self.module_list[1], self.modules[3])
# Reset and test deleting from start
self.module_list = nn.ModuleList(self.modules)
del self.module_list[:2]
self.assertEqual(len(self.module_list), 2)
self.assertIs(self.module_list[0], self.modules[2])
self.assertIs(self.module_list[1], self.modules[3])
def test_delitem_negative_index(self):
original_length = len(self.module_list)
del self.module_list[-1]
self.assertEqual(len(self.module_list), original_length - 1)
self.assertIs(self.module_list[-1], self.modules[2])
class TestModuleListOperations(unittest.TestCase):
def setUp(self):
self.modules1 = [nn.Linear(10, 5), nn.ReLU()]
self.modules2 = [nn.Dropout(0.5), nn.Tanh()]
self.module_list1 = nn.ModuleList(self.modules1)
self.module_list2 = nn.ModuleList(self.modules2)
def test_len(self):
self.assertEqual(len(self.module_list1), 2)
self.assertEqual(len(self.module_list2), 2)
def test_iter(self):
modules_from_iter = list(iter(self.module_list1))
self.assertEqual(len(modules_from_iter), 2)
self.assertIs(modules_from_iter[0], self.modules1[0])
self.assertIs(modules_from_iter[1], self.modules1[1])
def test_iadd(self):
original_len = len(self.module_list1)
self.module_list1 += self.modules2
self.assertEqual(
len(self.module_list1), original_len + len(self.modules2)
)
self.assertIs(self.module_list1[0], self.modules1[0])
self.assertIs(self.module_list1[1], self.modules1[1])
self.assertIs(self.module_list1[2], self.modules2[0])
self.assertIs(self.module_list1[3], self.modules2[1])
def test_add(self):
combined = self.module_list1 + self.module_list2
self.assertIsInstance(combined, nn.ModuleList)
self.assertEqual(len(combined), 4)
self.assertIs(combined[0], self.modules1[0])
self.assertIs(combined[1], self.modules1[1])
self.assertIs(combined[2], self.modules2[0])
self.assertIs(combined[3], self.modules2[1])
# Original lists should be unchanged
self.assertEqual(len(self.module_list1), 2)
self.assertEqual(len(self.module_list2), 2)
def test_insert(self):
new_module = nn.Sigmoid()
self.module_list1.insert(1, module=new_module)
self.assertEqual(len(self.module_list1), 3)
self.assertIs(self.module_list1[0], self.modules1[0])
self.assertIs(self.module_list1[1], new_module)
self.assertIs(self.module_list1[2], self.modules1[1])
def test_insert_at_beginning(self):
new_module = nn.ELU()
self.module_list1.insert(0, new_module)
self.assertIs(self.module_list1[0], new_module)
self.assertIs(self.module_list1[1], self.modules1[0])
def test_insert_at_end(self):
new_module = nn.LeakyReLU()
self.module_list1.insert(2, new_module)
self.assertIs(self.module_list1[2], new_module)
def test_append(self):
new_module = nn.Softmax()
original_len = len(self.module_list1)
result = self.module_list1.append(module=new_module)
self.assertEqual(len(self.module_list1), original_len + 1)
self.assertIs(self.module_list1[-1], new_module)
self.assertIs(result, self.module_list1)
def test_pop_int(self):
popped = self.module_list1.pop(0)
self.assertIs(popped, self.modules1[0])
self.assertEqual(len(self.module_list1), 1)
self.assertIs(self.module_list1[0], self.modules1[1])
def test_pop_negative_index(self):
popped = self.module_list1.pop(-1)
self.assertIs(popped, self.modules1[1])
self.assertEqual(len(self.module_list1), 1)
def test_pop_slice(self):
modules = [nn.Linear(10, 5), nn.ReLU(), nn.Dropout(0.5), nn.Tanh()]
module_list = nn.ModuleList(modules)
popped = module_list.pop(slice(1, 3))
self.assertIsInstance(popped, nn.ModuleList)
self.assertEqual(len(popped), 2)
self.assertIs(popped[0], modules[1])
self.assertIs(popped[1], modules[2])
self.assertEqual(len(module_list), 2)
def test_extend(self):
additional_modules = [nn.Dropout(0.3), nn.Sigmoid()]
original_len = len(self.module_list1)
result = self.module_list1.extend(modules=additional_modules)
self.assertEqual(
len(self.module_list1), original_len + len(additional_modules)
)
self.assertIs(self.module_list1[2], additional_modules[0])
self.assertIs(self.module_list1[3], additional_modules[1])
self.assertIs(result, self.module_list1)
def test_extent_error(self):
with self.assertRaises(TypeError):
self.module_list1.extend(123)
class TestModuleListFunctionality(unittest.TestCase):
def test_module_list_parameters(self):
linear1 = nn.Linear(10, 5)
linear2 = nn.Linear(5, 2)
module_list = nn.ModuleList([linear1, linear2])
params = dict(module_list.named_parameters())
self.assertIn('0.weight', params)
self.assertIn('0.bias', params)
self.assertIn('1.weight', params)
self.assertIn('1.bias', params)
def test_module_list_forward(self):
class TestModule(nn.Layer):
def __init__(self):
super().__init__()
self.layers = nn.ModuleList(
[nn.Linear(10, 5), nn.ReLU(), nn.Linear(5, 2)]
)
def forward(self, x):
for layer in self.layers:
x = layer(x)
return x
model = TestModule()
x = paddle.ones([2, 10])
output = model(x)
self.assertEqual(output.shape, [2, 2])
self.assertIsInstance(output, paddle.Tensor)
def test_module_list_state_dict(self):
linear1 = nn.Linear(10, 5)
linear2 = nn.Linear(5, 2)
module_list = nn.ModuleList([linear1, linear2])
state_dict = module_list.state_dict()
expected_keys = {'0.weight', '0.bias', '1.weight', '1.bias'}
self.assertEqual(set(state_dict.keys()), expected_keys)
def test_module_list_gradients(self):
linear1 = nn.Linear(10, 5)
linear2 = nn.Linear(5, 1)
module_list = nn.ModuleList([linear1, linear2])
x = paddle.ones([1, 10])
y = module_list[1](module_list[0](x))
loss = y.sum()
loss.backward()
self.assertIsNotNone(module_list[0].weight.grad)
self.assertIsNotNone(module_list[1].weight.grad)
class TestModuleListEdgeCases(unittest.TestCase):
def test_empty_operations(self):
empty_list = nn.ModuleList()
self.assertEqual(len(empty_list), 0)
self.assertEqual(list(empty_list), [])
module = nn.Linear(5, 3)
empty_list.append(module)
self.assertEqual(len(empty_list), 1)
self.assertIs(empty_list[0], module)
def test_single_element_operations(self):
module = nn.ReLU()
single_list = nn.ModuleList([module])
self.assertEqual(len(single_list), 1)
self.assertIs(single_list[0], module)
del single_list[0]
self.assertEqual(len(single_list), 0)
def test_duplicate_modules(self):
shared_module = nn.Dropout(0.5)
module_list = nn.ModuleList([shared_module, shared_module])
self.assertEqual(len(module_list), 2)
self.assertIs(module_list[0], module_list[1])
def test_module_list_with_none(self):
module_list = nn.ModuleList([nn.Linear(5, 3), None, nn.ReLU()])
self.assertEqual(len(module_list), 3)
self.assertIsNone(module_list[1])
# test ModuleDict
class TestModuleDictBasic(unittest.TestCase):
def test_initialization_empty(self):
module_dict = nn.ModuleDict()
self.assertEqual(len(module_dict), 0)
self.assertEqual(list(module_dict), [])
def test_initialization_with_modules(self):
modules = {
'linear': nn.Linear(10, 5),
'activation': nn.ReLU(),
'dropout': nn.Dropout(0.5),
}
module_dict = nn.ModuleDict(modules)
self.assertEqual(len(module_dict), 3)
self.assertIsInstance(module_dict['linear'], nn.Linear)
self.assertIsInstance(module_dict['activation'], nn.ReLU)
self.assertIsInstance(module_dict['dropout'], nn.Dropout)
def test_initialization_with_ordered_dict(self):
modules = OrderedDict(
[
('conv', nn.Conv2D(3, 16, 3)),
('bn', nn.BatchNorm2D(16)),
('pool', nn.MaxPool2D(2)),
]
)
module_dict = nn.ModuleDict(modules)
self.assertEqual(len(module_dict), 3)
self.assertIsInstance(module_dict['conv'], nn.Conv2D)
self.assertIsInstance(module_dict['bn'], nn.BatchNorm2D)
self.assertIsInstance(module_dict['pool'], nn.MaxPool2D)
class TestModuleDictAccessMethods(unittest.TestCase):
def setUp(self):
self.modules = {
'linear1': nn.Linear(10, 5),
'relu': nn.ReLU(),
'linear2': nn.Linear(5, 2),
'sigmoid': nn.Sigmoid(),
}
self.module_dict = nn.ModuleDict(self.modules)
def test_getitem(self):
self.assertIs(self.module_dict['linear1'], self.modules['linear1'])
self.assertIs(self.module_dict['relu'], self.modules['relu'])
self.assertIs(self.module_dict['linear2'], self.modules['linear2'])
def test_getitem_key_error(self):
with self.assertRaises(KeyError):
_ = self.module_dict['nonexistent']
def test_setitem(self):
new_module = nn.Tanh()
self.module_dict['tanh'] = new_module
self.assertIs(self.module_dict['tanh'], new_module)
self.assertEqual(len(self.module_dict), 5)
def test_setitem_overwrite(self):
new_linear = nn.Linear(10, 8)
original_length = len(self.module_dict)
self.module_dict['linear1'] = new_linear
self.assertEqual(len(self.module_dict), original_length)
self.assertIs(self.module_dict['linear1'], new_linear)
self.assertIsNot(self.module_dict['linear1'], self.modules['linear1'])
def test_delitem(self):
original_length = len(self.module_dict)
del self.module_dict['relu']
self.assertEqual(len(self.module_dict), original_length - 1)
self.assertNotIn('relu', self.module_dict)
self.assertIn('linear1', self.module_dict)
self.assertIn('linear2', self.module_dict)
def test_delitem_key_error(self):
with self.assertRaises(KeyError):
del self.module_dict['nonexistent']
def test_contains(self):
self.assertIn('linear1', self.module_dict)
self.assertIn('relu', self.module_dict)
self.assertNotIn('nonexistent', self.module_dict)
def test_keys(self):
keys = list(self.module_dict.keys())
expected_keys = ['linear1', 'relu', 'linear2', 'sigmoid']
self.assertEqual(set(keys), set(expected_keys))
self.assertEqual(len(keys), len(expected_keys))
def test_values(self):
values = list(self.module_dict.values())
self.assertEqual(len(values), 4)
self.assertIn(self.modules['linear1'], values)
self.assertIn(self.modules['relu'], values)
self.assertIn(self.modules['linear2'], values)
def test_items(self):
items = list(self.module_dict.items())
self.assertEqual(len(items), 4)
keys, values = zip(*items)
self.assertEqual(set(keys), set(self.modules.keys()))
self.assertEqual(set(values), set(self.modules.values()))
def test_iter(self):
keys_from_iter = list(iter(self.module_dict))
expected_keys = ['linear1', 'relu', 'linear2', 'sigmoid']
self.assertEqual(set(keys_from_iter), set(expected_keys))
class TestModuleDictOperations(unittest.TestCase):
def setUp(self):
self.initial_modules = {'conv': nn.Conv2D(3, 16, 3), 'relu': nn.ReLU()}
self.module_dict = nn.ModuleDict(self.initial_modules)
def test_clear(self):
self.assertEqual(len(self.module_dict), 2)
self.module_dict.clear()
self.assertEqual(len(self.module_dict), 0)
self.assertEqual(list(self.module_dict.keys()), [])
def test_pop(self):
original_length = len(self.module_dict)
popped_module = self.module_dict.pop('conv')
self.assertEqual(len(self.module_dict), original_length - 1)
self.assertIs(popped_module, self.initial_modules['conv'])
self.assertNotIn('conv', self.module_dict)
self.assertIn('relu', self.module_dict)
def test_pop_key_error(self):
with self.assertRaises(KeyError):
self.module_dict.pop('nonexistent')
def test_update_with_dict(self):
new_modules = {'bn': nn.BatchNorm2D(16), 'pool': nn.MaxPool2D(2)}
self.module_dict.update(modules=new_modules)
self.assertEqual(len(self.module_dict), 4)
self.assertIn('conv', self.module_dict)
self.assertIn('relu', self.module_dict)
self.assertIn('bn', self.module_dict)
self.assertIn('pool', self.module_dict)
def test_update_with_ordered_dict(self):
new_modules = OrderedDict(
[('dropout', nn.Dropout(0.5)), ('linear', nn.Linear(16, 10))]
)
self.module_dict.update(new_modules)
self.assertEqual(len(self.module_dict), 4)
self.assertIn('dropout', self.module_dict)
self.assertIn('linear', self.module_dict)
def test_update_with_module_dict(self):
other_dict = nn.ModuleDict({'sigmoid': nn.Sigmoid(), 'tanh': nn.Tanh()})
self.module_dict.update(other_dict)
self.assertEqual(len(self.module_dict), 4)
self.assertIn('sigmoid', self.module_dict)
self.assertIn('tanh', self.module_dict)
def test_update_with_iterable(self):
new_modules = [('bn', nn.BatchNorm2D(16)), ('pool', nn.MaxPool2D(2))]
self.module_dict.update(new_modules)
self.assertEqual(len(self.module_dict), 4)
self.assertIn('bn', self.module_dict)
self.assertIn('pool', self.module_dict)
def test_update_overwrite_existing(self):
new_conv = nn.Conv2D(3, 32, 3)
self.module_dict.update({'conv': new_conv})
self.assertEqual(len(self.module_dict), 2)
self.assertIs(self.module_dict['conv'], new_conv)
self.assertIsNot(self.module_dict['conv'], self.initial_modules['conv'])
def test_update_invalid_iterable_element(self):
with self.assertRaises(TypeError):
self.module_dict.update([nn.Linear(5, 3)])
def test_update_invalid_pair_length(self):
with self.assertRaises(ValueError):
self.module_dict.update([('key', 'module', 'extra')])
def test_update_error(self):
with self.assertRaises(AssertionError):
self.module_dict.update(123)
class TestModuleDictFunctionality(unittest.TestCase):
def test_module_dict_parameters(self):
module_dict = nn.ModuleDict(
{'linear1': nn.Linear(10, 5), 'linear2': nn.Linear(5, 2)}
)
params = dict(module_dict.named_parameters())
self.assertIn('linear1.weight', params)
self.assertIn('linear1.bias', params)
self.assertIn('linear2.weight', params)
self.assertIn('linear2.bias', params)
def test_module_dict_forward(self):
class TestModel(nn.Layer):
def __init__(self):
super().__init__()
self.layers = nn.ModuleDict(
{
'linear1': nn.Linear(10, 5),
'activation': nn.ReLU(),
'linear2': nn.Linear(5, 2),
}
)
def forward(self, x):
x = self.layers['linear1'](x)
x = self.layers['activation'](x)
x = self.layers['linear2'](x)
return x
model = TestModel()
x = paddle.ones([2, 10])
output = model(x)
self.assertEqual(output.shape, [2, 2])
self.assertIsInstance(output, paddle.Tensor)
def test_module_dict_state_dict(self):
module_dict = nn.ModuleDict(
{'conv': nn.Conv2D(3, 16, 3), 'bn': nn.BatchNorm2D(16)}
)
state_dict = module_dict.state_dict()
expected_keys = {
'conv.weight',
'conv.bias',
'bn.weight',
'bn.bias',
'bn._mean',
'bn._variance',
}
actual_keys = set(state_dict.keys())
self.assertTrue(expected_keys.issubset(actual_keys))
def test_module_dict_gradients(self):
module_dict = nn.ModuleDict(
{'linear1': nn.Linear(10, 5), 'linear2': nn.Linear(5, 1)}
)
x = paddle.ones([1, 10])
y = module_dict['linear2'](module_dict['linear1'](x))
loss = y.sum()
loss.backward()
self.assertIsNotNone(module_dict['linear1'].weight.grad)
self.assertIsNotNone(module_dict['linear2'].weight.grad)
class TestModuleDictEdgeCases(unittest.TestCase):
def test_empty_operations(self):
empty_dict = nn.ModuleDict()
self.assertEqual(len(empty_dict), 0)
self.assertEqual(list(empty_dict.keys()), [])
self.assertEqual(list(empty_dict.values()), [])
module = nn.Linear(5, 3)
empty_dict['linear'] = module
self.assertEqual(len(empty_dict), 1)
self.assertIs(empty_dict['linear'], module)
def test_single_element_operations(self):
module = nn.ReLU()
single_dict = nn.ModuleDict({'activation': module})
self.assertEqual(len(single_dict), 1)
self.assertIs(single_dict['activation'], module)
del single_dict['activation']
self.assertEqual(len(single_dict), 0)
def test_duplicate_modules(self):
shared_module = nn.Dropout(0.5)
module_dict = nn.ModuleDict(
{'dropout1': shared_module, 'dropout2': shared_module}
)
self.assertEqual(len(module_dict), 2)
self.assertIs(module_dict['dropout1'], module_dict['dropout2'])
def test_special_key_names(self):
module_dict = nn.ModuleDict()
module_dict['key-with-dash'] = nn.Linear(5, 3)
module_dict['key_with_underscore'] = nn.ReLU()
module_dict['key.with.dots'] = nn.Sigmoid()
module_dict['123numeric'] = nn.Tanh()
self.assertEqual(len(module_dict), 4)
self.assertIn('key-with-dash', module_dict)
self.assertIn('key_with_underscore', module_dict)
self.assertIn('key.with.dots', module_dict)
self.assertIn('123numeric', module_dict)
def test_module_dict_with_none(self):
module_dict = nn.ModuleDict(
{
'linear': nn.Linear(5, 3),
'none_module': None,
'activation': nn.ReLU(),
}
)
self.assertEqual(len(module_dict), 3)
self.assertIsNone(module_dict['none_module'])
def test_key_ordering(self):
modules = OrderedDict(
[
('z_last', nn.Linear(5, 3)),
('a_first', nn.ReLU()),
('m_middle', nn.Sigmoid()),
]
)
module_dict = nn.ModuleDict(modules)
keys = list(module_dict.keys())
self.assertEqual(keys, ['z_last', 'a_first', 'm_middle'])
class TestModuleDictIntegration(unittest.TestCase):
def test_combined_with_module_list(self):
linear_layers = nn.ModuleList([nn.Linear(10, 5), nn.Linear(5, 2)])
activations = nn.ModuleDict(
{'relu': nn.ReLU(), 'sigmoid': nn.Sigmoid()}
)
class CombinedModel(nn.Layer):
def __init__(self):
super().__init__()
self.layers = linear_layers
self.activations = activations
def forward(self, x):
x = self.layers[0](x)
x = self.activations['relu'](x)
x = self.layers[1](x)
x = self.activations['sigmoid'](x)
return x
model = CombinedModel()
x = paddle.ones([2, 10])
output = model(x)
self.assertEqual(output.shape, [2, 2])
self.assertIsInstance(output, paddle.Tensor)
if __name__ == '__main__':
unittest.main()