pytorch api文档:nn.ModuleList 与 nn.Sequential 比较

对比

维度 nn.Sequential nn.ModuleList
核心定位 带执行逻辑的“流水线”容器 仅存储层的“货架”容器
forward 方法 自带,按顺序执行所有层(黑盒执行) 无,需手动遍历/调用层(白盒控制)
参数注册 ✅ 自动注册内部层的参数 ✅ 自动注册内部层的参数
灵活性 低:仅支持线性顺序执行,无法中断/分支 高:支持跳层、分支、条件执行、快捷连接
层操作 ❌ 不支持动态 append/extend(需重新定义) ✅ 支持列表所有操作(append/extend/索引/删除)
层命名 ✅ 可通过 OrderedDict 给层命名(如 nn.Sequential(OrderedDict([('conv1', nn.Conv2d(...))]))) ❌ 无命名功能,仅能通过索引访问
适用场景 1. 简单线性网络(如 CNN 基础特征层)<br>2. 无分支/无快捷连接的子模块<br>3. 想简化代码的场景 1. 复杂网络(如残差块、多头注意力)<br>2. 动态创建层(如自定义层数的 MLP)<br>3. 需要快捷连接/分支逻辑的场景
代码简洁度 高(无需手动写 forward 遍历) 稍低(需手动控制层的执行)

关键共性

  1. 都能正确注册参数:这是两者最核心的共性,也是区别于普通 Python 列表的关键——存储在其中的层的 weight/bias 会被 PyTorch 识别,支持 model.parameters()、model.to(device) 等操作;
  2. 都继承自 nn.Module:都是合法的子模块,可作为网络的属性直接使用;
  3. 都支持迭代/索引:都能通过 for layer in container 遍历,或 container[idx] 访问指定层;
  4. 都支持嵌套:比如 nn.Sequential 里可以放 nn.ModuleList,nn.ModuleList 里也可以放 nn.Sequential(混合写法很常用)。

选择策略

  • 如果只需要 按顺序执行所有层,无任何分支/跳层 → 用 nn.Sequential(代码更短);

  • 如果需要 自定义执行逻辑(快捷连接/分支/条件) 或动态创建层 → 用 nn.ModuleList(灵活性更高);

  • 实际开发中可混合使用:用 Sequential 封装简单线性子模块,用 ModuleList 管理需要自定义逻辑的层。

例子

场景1:简单线性网络(优先用 Sequential)

# 用 Sequential 更简洁
class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(16, 32, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
    def forward(self, x):
        return self.features(x)  # 一行搞定,无需遍历

场景2:带快捷连接的残差块(必须用 ModuleList)

# 用 ModuleList 实现灵活的快捷连接
class ResBlock(nn.Module):
    def __init__(self, in_ch, out_ch):
        super().__init__()
        self.layers = nn.ModuleList([
            nn.Conv2d(in_ch, out_ch, 3, 1, 1),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(),
            nn.Conv2d(out_ch, out_ch, 3, 1, 1),
            nn.BatchNorm2d(out_ch)
        ])
        self.shortcut = nn.Sequential()  # 混合使用更简洁
        if in_ch != out_ch:
            self.shortcut = nn.Sequential(nn.Conv2d(in_ch, out_ch, 1))

    def forward(self, x):
        residual = self.shortcut(x)
        # 手动控制层的执行,实现快捷连接
        out = self.layers[0](x)
        out = self.layers[1](out)
        out = self.layers[2](out)
        out = self.layers[3](out)
        out = self.layers[4](out)
        out += residual  # 快捷连接核心逻辑
        return nn.ReLU()(out)

场景3:动态创建层(优先用 ModuleList)

# 根据参数动态生成多层感知机
class DynamicMLP(nn.Module):
    def __init__(self, in_dim, out_dim, hidden_dim, num_layers):
        super().__init__()
        self.layers = nn.ModuleList()
        self.layers.append(nn.Linear(in_dim, hidden_dim))
        # 动态追加 num_layers-2 个中间层
        for _ in range(num_layers - 2):
            self.layers.append(nn.Linear(hidden_dim, hidden_dim))
            self.layers.append(nn.ReLU())
        self.layers.append(nn.Linear(hidden_dim, out_dim))

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

# 一键创建 3 层/5 层 MLP
mlp_3 = DynamicMLP(10, 2, 32, 3)
mlp_5 = DynamicMLP(10, 2, 32, 5)

总结

  1. 核心差异:nn.Sequential 是“傻瓜式”顺序执行容器,简洁但不灵活;nn.ModuleList 是“手动控制”存储容器,灵活但需手动写执行逻辑;
  2. 核心共性:两者都能正确注册层的参数,区别于普通 Python 列表;
  3. 选择原则:看是否需要自定义层的执行逻辑——不需要用 Sequential,需要用 ModuleList。

原文出处:/show_1GW2eVtDraxi.html