pytorch api文档:nn.ModuleList() 存储多个nn.Module的有序列表容器

介绍

nn.ModuleList,是 nn.Module 的一个实用工具类,专门用来管理一组神经网络模块(比如多个卷积层、全连接层)

作用

nn.ModuleList 是 PyTorch 提供的 有序列表容器,用于存储多个 nn.Module 子类实例(比如 nn.Linear、nn.Conv2d)。它的核心作用是:

  • 让 PyTorch 能够识别并管理列表中的所有模块参数(这是普通 Python list 做不到的);
  • 提供有序的、可索引的模块访问方式,适合需要动态创建/管理多个层的场景。

简单来说:普通 list 装的层,PyTorch 不认(参数不会被收集);nn.ModuleList 装的层,PyTorch 能完整管理(参数可训练、可迁移设备)。

例子

基础使用场景(动态创建多层)

创建一个可配置层数的全连接网络,用 nn.ModuleList 就能灵活实现:

import torch
import torch.nn as nn

class DynamicNet(nn.Module):
    def __init__(self, input_size, hidden_sizes, output_size):
        super(DynamicNet, self).__init__()

        # 1. 初始化 nn.ModuleList(空列表)
        self.layers = nn.ModuleList()

        # 2. 动态添加层到 ModuleList 中
        prev_size = input_size
        for hidden_size in hidden_sizes:
            # 添加全连接层
            self.layers.append(nn.Linear(prev_size, hidden_size))
            # 添加激活函数
            self.layers.append(nn.ReLU())
            prev_size = hidden_size

        # 添加输出层
        self.layers.append(nn.Linear(prev_size, output_size))

    def forward(self, x):
        # 3. 遍历 ModuleList 执行前向传播
        for layer in self.layers:
            x = layer(x)
        return x

# ---------------------- 测试使用 ----------------------
# 创建模型:输入10维,隐藏层[20, 15],输出5维
model = DynamicNet(input_size=10, hidden_sizes=[20, 15], output_size=5)
print("模型结构:")
print(model)

# 查看参数(验证 ModuleList 中的层参数被正确收集)
print("\n模型所有可训练参数:")
for name, param in model.named_parameters():
    print(f"参数名:{name},形状:{param.shape}")

# 前向传播测试
input_data = torch.randn(2, 10)  # 2个样本,10维特征
output = model(input_data)
print("\n输入形状:", input_data.shape)
print("输出形状:", output.shape)

# 设备迁移(ModuleList 中的层会一起迁移)
model = model.to("cpu")  # 也可以用 "cuda"(如果有GPU)
print("\n模型设备:", next(model.parameters()).device)

nn.ModuleList vs 普通 Python list

用代码对比,直观看到差异:

import torch
import torch.nn as nn

class TestNet(nn.Module):
    def __init__(self):
        super(TestNet, self).__init__()

        # 用普通 list 存储层
        self.normal_list = [nn.Linear(10, 5), nn.ReLU()]
        # 用 ModuleList 存储层
        self.module_list = nn.ModuleList([nn.Linear(5, 2)])

    def forward(self, x):
        for layer in self.normal_list:
            x = layer(x)
        for layer in self.module_list:
            x = layer(x)
        return x

model = TestNet()

# 查看模型参数:只有 ModuleList 中的层参数被收集
print("模型参数列表:")
for name, param in model.named_parameters():
    print(name)  # 只输出 "module_list.0.weight" 和 "module_list.0.bias"

# 普通 list 中的层参数未被识别,无法参与训练!
print("\n普通 list 中的层是否在模型参数中?", "normal_list.0.weight" in [n for n, _ in model.named_parameters()])
# 输出:False

常用方法

nn.ModuleList 支持和普通 list 类似的操作,核心方法如下:

方法 作用
append(module) 向列表末尾添加一个模块(最常用)
extend(modules) 批量添加多个模块(如 module_list.extend([nn.ReLU(), nn.Dropout()]))
insert(idx, module) 在指定索引位置插入模块
__getitem__(idx) 通过索引访问模块(如 self.layers[0])
__len__() 获取列表长度(如 len(self.layers))

使用场景

适合场景

  • 动态创建多层(比如根据配置文件的参数决定层数/层维度);
  • 需要按索引访问特定层(比如 self.layers[2] 取出第3层);
  • 层的数量不固定,需要灵活增删。

不适合场景

  • 只需按固定顺序执行层:优先用 nn.Sequential(更简洁,如 nn.Sequential(nn.Linear(10,5), nn.ReLU()));
  • 层之间有复杂的分支/跳转逻辑:直接在 forward 中手动调用层更清晰。

注意事项

  • nn.ModuleList 只是容器,不会自动执行前向传播:必须在 forward 中手动遍历执行;
  • 必须在 __init__ 中初始化 nn.ModuleList 并添加模块:如果在 forward 中添加,参数不会被收集;
  • nn.ModuleList 中的模块会被 model.parameters() 收集,参与梯度更新,这是和普通 list 最核心的区别。

总结

  1. nn.ModuleList 是管理多个 nn.Module 的有序容器,核心作用是让 PyTorch 识别并管理列表内模块的参数;
  2. 它和普通 Python list 的关键区别:ModuleList 中的层参数会被收集、可训练,普通 list 不会;
  3. 适用场景:动态创建/管理多层、需要按索引访问层;不适用场景:固定顺序执行层(优先用 nn.Sequential)。

原文出处:/show_1GW2dCKk4ltl.html