作用
torch.nn.Sequential() 是 PyTorch 中用于按顺序堆叠神经网络层的容器,它会把传入的层按顺序封装,前一层的输出会自动作为后一层的输入,无需手动定义前向传播(forward)函数,能极大简化简单网络的编写。
简单来说:Sequential 就是“搭积木”,按顺序把网络层拼起来,自动完成数据的前向传递。
语法
nn.Sequential() 本质是一个类构造函数,有 3种常用语法形式,覆盖不同使用场景:
| 语法形式 | 适用场景 | 示例代码片段 |
|---|---|---|
| 空构造 + 动态添加层 | 需动态生成层(如循环创建层) | model = nn.Sequential() <br> model.add_module('fc1', nn.Linear(10,20)) |
| 直接传入层对象(最常用) | 静态、简单的串行网络 | model = nn.Sequential(nn.Linear(10,20), nn.ReLU()) |
| 传入 OrderedDict | 需自定义层名称(方便调试/访问) | model = nn.Sequential(OrderedDict([('fc1', nn.Linear(10,20)), ('relu', nn.ReLU())])) |
空构造 + add_module(动态添加)
import torch.nn as nn
# 空Sequential
model = nn.Sequential()
# 动态添加层:add_module(层名称, 层对象)
model.add_module("fc1", nn.Linear(10, 20))
model.add_module("relu1", nn.ReLU())
model.add_module("fc2", nn.Linear(20, 5))
# 测试
x = torch.randn(2, 10)
print(model(x).shape) # torch.Size([2, 5])
直接传层对象(极简)
# 语法:nn.Sequential(层1, 层2, 层3, ...)
model = nn.Sequential(
nn.Conv2d(3, 16, 3), # 层1:卷积层
nn.BatchNorm2d(16), # 层2:归一化层
nn.MaxPool2d(2) # 层3:池化层
)
OrderedDict(自定义名称)
from collections import OrderedDict
# 语法:nn.Sequential(OrderedDict([(名称1, 层1), (名称2, 层2), ...]))
model = nn.Sequential(OrderedDict([
("conv1", nn.Conv2d(3, 16, 3)),
("bn1", nn.BatchNorm2d(16)),
("pool1", nn.MaxPool2d(2))
]))
# 可通过名称直接访问层
print(model.conv1) # 输出:Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1))
注意
传入的必须是 nn.Module 子类
Sequential 只能封装 PyTorch 内置的层(如 nn.Linear、nn.Conv2d、nn.ReLU)或自定义的 nn.Module 子类,不能传入普通函数/张量:
# 错误示例:传入普通函数(如torch.relu)会报错
model = nn.Sequential(
nn.Linear(10,20),
torch.relu # ❌ 不是nn.Module子类,应改用nn.ReLU()
)
# 正确示例:用nn.ReLU()(nn.Module子类)
model = nn.Sequential(
nn.Linear(10,20),
nn.ReLU() # ✅ 合法
)
层的维度必须连续匹配
前一层的输出维度必须等于后一层的输入维度,否则前向传播会报维度不匹配错误:
# 错误示例:Linear(10,20)输出20维,下一层却要求输入15维
model = nn.Sequential(
nn.Linear(10,20), # 输出20维
nn.Linear(15,5) # ❌ 输入要求15维,维度不匹配
)
# 正确示例:维度连续
model = nn.Sequential(
nn.Linear(10,20), # 输出20维
nn.Linear(20,5) # ✅ 输入20维,匹配
)
无分支/跳跃逻辑
Sequential 强制按“串行”执行,无法实现分支(如ResNet残差连接)、多输入/多输出,这类场景必须用自定义 nn.Module。
无自动维度调整
比如卷积层输出的4维张量(N,C,H,W)直接接全连接层会报错,需要先用 nn.Flatten() 展平;
与自定义 Module 的区别
Sequential是nn.Module的子类,具备train()、eval()、to(device)等所有Module的特性;- 自定义
nn.Module需要重写forward函数,灵活性更高,Sequential是简化版。
常用操作语法
| 操作 | 语法示例 | 说明 |
|---|---|---|
| 访问层 | model[0] / model.fc1 |
按索引(默认名)或自定义名称访问层 |
| 查看网络结构 | print(model) / model.named_parameters() |
打印层信息/查看参数名称+值 |
| 设备迁移 | model.to('cuda') / model.to(torch.device('cpu')) |
把整个Sequential移到GPU/CPU |
| 切换训练/评估模式 | model.train() / model.eval() |
对所有层生效(如BatchNorm、Dropout) |
基础使用方法
1. 最简洁的写法(按顺序传层)
适合层的名称无需自定义的场景,PyTorch 会自动给每层分配默认名称(如 0、1、2)。
import torch
import torch.nn as nn
# 定义一个简单的全连接网络:输入→线性层→ReLU→线性层→输出
model = nn.Sequential(
nn.Linear(10, 20), # 输入维度10,输出维度20
nn.ReLU(), # 激活函数
nn.Linear(20, 5) # 输出维度5
)
# 测试前向传播
x = torch.randn(3, 10) # 批量大小3,输入维度10
output = model(x)
print("输出形状:", output.shape) # 输出: torch.Size([3, 5])
2. 自定义层名称(OrderedDict 写法)
如果需要给每层起有意义的名字(方便调试/查看网络结构),可以用 OrderedDict 封装:
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
('fc1', nn.Linear(10, 20)), # 命名为fc1
('relu1', nn.ReLU()), # 命名为relu1
('fc2', nn.Linear(20, 5)) # 命名为fc2
]))
# 查看网络结构(能看到自定义名称)
print(model)
"""
输出:
Sequential(
(fc1): Linear(in_features=10, out_features=20, bias=True)
(relu1): ReLU()
(fc2): Linear(in_features=20, out_features=5, bias=True)
)
"""
# 通过名称访问特定层
print(model.fc1) # 输出: Linear(in_features=10, out_features=20, bias=True)
适用场景
1. 适用场景
- 简单线性网络:层与层之间是“串行”关系,无分支、无跳跃连接(如简单的全连接网络、基础CNN);
- 快速搭建原型:无需写
forward函数,几行代码就能完成网络定义; - 嵌套使用:可以把一组层封装成
Sequential,再作为一个模块放入更大的Sequential中(比如CNN的卷积块)。
2. 不适用场景
- 复杂网络:有分支(如ResNet的残差连接)、多输入/多输出、需要手动控制前向逻辑的网络(这类场景建议自定义
nn.Module类); - 需要在forward中加额外逻辑:比如中间层输出的复用、动态调整层的执行顺序等。
进阶用法:嵌套 Sequential
实际项目中常把重复的层(如CNN的卷积+激活+池化)封装成 Sequential,再组合成大网络:
# 定义一个CNN网络:卷积块 + 全连接块
cnn_model = nn.Sequential(
# 卷积块1:卷积→ReLU→池化
nn.Sequential(
nn.Conv2d(3, 16, kernel_size=3, padding=1), # 输入通道3,输出通道16
nn.ReLU(),
nn.MaxPool2d(2) # 池化后尺寸减半
),
# 卷积块2:卷积→ReLU→池化
nn.Sequential(
nn.Conv2d(16, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
),
# 展平+全连接
nn.Flatten(),
nn.Linear(32 * 8 * 8, 10) # 假设输入是3×32×32的图片,池化两次后是32×8×8
)
# 测试输入(批量大小2,3通道,32×32图片)
x = torch.randn(2, 3, 32, 32)
output = cnn_model(x)
print("CNN输出形状:", output.shape) # 输出: torch.Size([2, 10])
总结
nn.Sequential()是 PyTorch 中按顺序堆叠网络层的便捷容器,自动实现前向传播,无需手写forward;- 有两种写法:直接传层(简洁)、用
OrderedDict传层+名称(易调试); - 适合搭建线性串行的简单网络,复杂网络(有分支/多输入)建议用自定义
nn.Module; - 使用时核心要保证层的维度匹配,卷积转全连接需用
nn.Flatten()展平。