Lab 2 — 激活函数与 ReLU 非线性
实验概述
用 PyTorch 从零搭建一个带隐藏层的小型神经网络,拟合送货距离(英里)与时间(分钟)之间的非线性关系。核心是引入 ReLU 激活函数,让模型获得非线性拟合能力。
模型:Linear(1,3) → ReLU → Linear(3,1),共 10 个参数
数据:39 组(距离 1.0~20.0 英里,时间 6.96~92.98 分钟)
归一化:z-score(距离和时间各算各的)
训练:SGD lr=0.01,3000 epochs,manual_seed(27)
核心代码
模型定义与训练循环:
torch.manual_seed(27)
model = nn.Sequential(
nn.Linear(1, 3), # 隐藏层:1 输入 → 3 神经元
nn.ReLU(), # 激活函数:负数归零,正数不变
nn.Linear(3, 1), # 输出层:3 → 1
)
loss_function = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
for epoch in range(3000):
optimizer.zero_grad()
outputs = model(distances_norm)
loss = loss_function(outputs, times_norm)
loss.backward()
optimizer.step()
反归一化预测(从归一化值还原到真实分钟数):
predicted_time_norm = model(new_distance_norm)
predicted_time_actual = (predicted_time_norm * times_std) + times_mean
训练过程
6 个关键帧(epoch 1 / 50 / 200 / 600 / 1500 / 3000),展示模型如何从随机初始化逐步拟合数据:
Loss 曲线(对数尺度),3000 轮训练的收敛过程:
最终拟合(真实单位:英里 vs 分钟):
结果
归一化最终 loss (MSE):0.003144
真实单位 RMSE:1.566 分钟
5.1 英里预测:38.7 分钟 → use a car
关键理解
矩阵乘加偏置 = 机器人运动学仿射变换。Linear 层的本质就是 p' = W·p + b,和机器人运动学里的 p' = R·p + d 同构——权重矩阵 W 对应旋转 R,偏置 b 对应平移 d。这个类比让"全连接层在做什么"瞬间具体了。
ReLU 的几何意义。ReLU 把负数归零,相当于在空间里"折叠"——单个 ReLU 神经元是一个分段线性函数(斜率在 0 处突变)。3 个 ReLU 神经元组合起来,就能拟合曲线。
归一化不是可选项。如果不做 z-score 归一化,距离(1~20)和时间(7~93)的尺度差异会让 loss 地形极度狭长,SGD 几乎学不动。归一化后 loss 地形接近圆形,梯度下降才能高效收敛。
错误复盘
一个关键错误:最初误判 seed=27 是"差拟合"——根因是用 Python random 而非 torch.manual_seed 生成初始权重,导致结果对不上。改用严格 manual_seed(27) 后确认是好种子(RMSE 1.57)。教训:PyTorch 的随机性必须用 PyTorch 自己的 RNG 控制,混用 Python random 会产生不可复现的结果。