nn.Sequential 与nn.ModuleList 区别

nn.Sequential vs nn.ModuleList

为了帮你快速理解,我将它们的核心区别总结在下表中:

特性 nn.Sequential nn.ModuleList
核心定位 一个可执行的、有序的容器,本身是一个"模型"。 一个存储子模块的Python列表,是"模型部件的集合"。
可调用性 可直接调用,输入会按顺序通过所有子模块。 不可直接调用,只是一个列表,需要手动遍历或索引访问。
前向传播 自动定义。只需调用容器本身,内部顺序即前向逻辑。 手动定义 。你需在forward中明确写出如何使用每个模块。
主要用途 构建简单、线性的模型流水线(如 CNN 的 conv->relu->pool 堆叠)。 组织和管理一组模块 ,以实现灵活、非顺序的连接(如循环、分支、共享层)。
顺序重要性 至关重要,顺序决定了数据流向。 不重要 ,存储顺序不影响模型逻辑,取决于你在forward中如何使用它们。

错误示例

复制代码
from torch import nn
import os

class ASimpleNet(nn.Module):
    def __init__(self, layers=3):
        super(ASimpleNet, self).__init__()
        # 使用 Sequential 替代 ModuleList
        self.linears = nn.Sequential(
            *[nn.Linear(3, 3, bias=False) for _ in range(layers)]
        )
    
    def forward(self, x):
        print("forward batchsize is: {}".format(x.size()[0]))
        x = self.linears(x)  # 正确调用
        x = torch.relu(x)
        return x

[nn.Linear(3, 3, bias=False) for i in range(3)] 中,定义三个完全相同(输入输出均为3维)的线性层,通常有以下几种设计意图:

  1. 构建更深的网络(最常见意图):

    • 想法:通过增加网络深度(层数)来增强模型的表达能力,学习更复杂的特征变换。这是深度学习的基础理念。

    • 你代码中的问题 :纯线性层堆叠(Linear -> Linear -> Linear没有中间非线性激活函数 。根据线性代数,多个线性变换的复合等价于一个线性变换 (即 W3(W2(W1*x)) 等价于 (W3*W2*W1)*x),因此深度没有带来任何好处。

    • 正确做法 :应在每层线性层后加入非线性激活(如ReLU),形成 Linear -> ReLU -> Linear -> ReLU -> Linear 的结构,这样每层才能学习不同的非线性映射。

  2. 实现并行或分支结构

    • 想法:让同一输入同时被多个不同的线性层(可视为不同的"专家"或"视角")处理,然后将结果融合(相加、拼接等)。

    • 这需要 nn.ModuleList:因为你需要分别调用这三个层,然后手动组合它们的输出。

  3. 作为模块复用的示例

    • 想法 :教学演示如何用 nn.ModuleListnn.Sequential 来管理多个相同类型的层。

💡 如何正确使用它们?------ 实例对比

假设我们想构建一个网络,它先将输入投影到三个不同的3维子空间,然后将结果相加 。这必须 使用 nn.ModuleList

复制代码
class ParallelNet(nn.Module):
    def __init__(self):
        super().__init__()
        # 用 ModuleList 存储三个独立的层
        self.branches = nn.ModuleList([nn.Linear(3, 3) for _ in range(3)])
    
    def forward(self, x):
        branch_outputs = [branch(x) for branch in self.branches] # 分别计算
        x = torch.stack(branch_outputs).sum(dim=0) # 堆叠后求和
        return x
复制代码

如果只是想构建一个简单的深度网络,则使用 nn.Sequential 更清晰:

复制代码
class DeepNet(nn.Module):
    def __init__(self):
        super().__init__()
        # 用 Sequential 定义顺序执行的层
        self.net = nn.Sequential(
            nn.Linear(3, 3),
            nn.ReLU(),  # 关键!加入非线性
            nn.Linear(3, 3),
            nn.ReLU(),  # 关键!加入非线性
            nn.Linear(3, 3),
        )
    
    def forward(self, x):
        return self.net(x)  # 调用一次即可
复制代码

总结与选择建议

  1. 关于"三个层" :在层间没有非线性激活 的情况下,堆叠多个Linear层是无效的。你需要明确目标:是构建深度网络 (加非线性,用Sequential),还是并行分支 (用ModuleList手动融合)。

  2. 关于容器选择

    • 当你的模型是 层A -> 层B -> 层C 这种简单、严格的顺序 时,毫不犹豫地选择 nn.Sequential

    • 当你的模型需要循环 (如RNN)、条件判断分支处理自定义连接方式 时,选择 nn.ModuleList 来存储模块,然后在 forward 中实现你的逻辑。

简单记:Sequential 用于"自动流水线",ModuleList 用于"手动装配线"

相关推荐
阿杰学AI6 小时前
AI核心知识44——大语言模型之Reward Hacking(简洁且通俗易懂版)
人工智能·ai·语言模型·aigc·ai安全·奖励欺骗·reward hacking
海森大数据9 小时前
用最通用的语言模型,解决最专业的几何问题:Token-Mol的“反直觉”革命
人工智能·语言模型·自然语言处理
kebijuelun10 小时前
DeepSeek-V3.2: Pushing the Frontier of Open Large Language Models
人工智能·语言模型·自然语言处理
Elastic 中国社区官方博客10 小时前
Jina-VLM:小型多语言视觉语言模型
数据库·人工智能·elasticsearch·搜索引擎·ai·语言模型·jina
Sherlock Ma11 小时前
OpenAI新论文!GPT-5-Thinking新训练方法
人工智能·gpt·深度学习·语言模型·自然语言处理·chatgpt·openai
Bruce-XIAO14 小时前
MOE-混合专家架构论文阅读
人工智能·语言模型·moe
Sherlock Ma14 小时前
DeepSeek-Math-V2:自验证数学推理大模型(论文详解)
人工智能·深度学习·语言模型·自然语言处理·数学推理·deepseek
java1234_小锋14 小时前
Transformer 大语言模型(LLM)基石 - Transformer架构详解 - 位置编码(Positional Encoding)详解与算法实现
深度学习·语言模型·transformer
桃子叔叔14 小时前
论文翻译:CONSISTENCY-GUIDED PROMPT LEARNING FOR VISION-LANGUAGE MODELS
机器学习·语言模型·prompt