nn 模块
学习目标
- 理解为什么 PyTorch 要用
nn.Module组织模型 - 掌握
nn.Linear、nn.ReLU、nn.Sequential - 能自己写一个最简单的自定义网络
- 明白
forward()、parameters()、train()、eval()的作用
先建立一张地图
这节最重要的不是记住多少类名,而是看清:
所以这一节真正解决的是:
- 模型结构怎么被组织成一个“可训练对象”
这节和前后内容是怎么接上的
- 前一节
autograd已经解决“梯度怎么来” - 这一节开始解决“这些参数到底被装在哪、怎么统一管理”
- 下一节
DataLoader会解决“数据怎么一批批送进来”
所以这一节其实是在给训练循环准备“模型这一半”。
一、为什么需要 nn.Module?
如果说张量是“数据盒子”,那 nn.Module 就是“模型盒子”。
它帮你把一堆东西组织起来:
- 网络层
- 参数
- 前向计算逻辑
- 训练 / 评估模式切换
类比一下:
| 组件 | 类比 |
|---|---|
Tensor | 一块砖 |
nn.Linear | 一个标准零件 |
nn.Module | 一个可组合的机器 |
如果没有 nn.Module,你也可以手写网络,但会非常乱。
有了它,模型就像乐高积木,可以一层层拼起来。
1.1 一个更适合新人的直觉:nn.Module 就是“模型容器”
你可以先把它理解成一个统一的模型盒子,里面会装:
- 网络层
- 参数
- 前向逻辑
- 训练 / 评估模式
这就是为什么后面很多地方都只传一个 model 对象,就能完成:
- 前向计算
- 参数更新
- 保存和加载
二、最常见的层:nn.Linear
线性层做的事情就是:
y = xW + b
import torch
from torch import nn
layer = nn.Linear(in_features=3, out_features=2)
x = torch.tensor([[1.0, 2.0, 3.0]])
y = layer(x)
print("输出:", y)
print("weight shape:", layer.weight.shape)
print("bias shape:", layer.bias.shape)
这里的形状要读懂:
- 输入是
[1, 3],表示 1 个样本、每个样本 3 个特征 - 输出是
[1, 2],表示映射到 2 个输出值
2.1 看到 nn.Linear(in, out) 时,脑子里最该立刻跳出什么?
最值得先跳出来的是:
- 这不是在“神秘变换”
- 而是在把每个样本从
in维表示映射到out维表示
所以一个线性层最实用的理解方式通常是:
- 输入空间被重新编码成了新的特征空间
三、用 nn.Sequential 快速搭网络
如果模型比较简单,可以直接把层按顺序串起来:
import torch
from torch import nn
model = nn.Sequential(
nn.Linear(2, 4),
nn.ReLU(),
nn.Linear(4, 1)
)
x = torch.tensor([[1.0, 2.0]])
pred = model(x)
print(pred)
这段代码表示:
- 输入 2 个特征
- 先映射到 4 维隐藏层
- 经过
ReLU激活 - 再输出 1 个值
这就已经是一个最小版多层感知机了。
四、自己定义一个模型类
当模型稍微复杂一点,推荐继承 nn.Module。
import torch
from torch import nn
class ScorePredictor(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(2, 8),
nn.ReLU(),
nn.Linear(8, 1)
)
def forward(self, x):
return self.net(x)
model = ScorePredictor()
x = torch.tensor([
[3.0, 4.0], # 学习时长、作业完成数
[5.0, 8.0]
])
print(model(x))
__init__() 和 forward() 分别做什么?
| 方法 | 职责 |
|---|---|
__init__() | 定义层和子模块 |
forward() | 定义“数据怎么流过去” |
一句话记忆:
__init__负责“搭机器”forward负责“机器怎么工作”