第 2 章 监督学习的最小闭环¶
学习式方法的第一个动作都是同一个:把"想要的行为"变成一组输入输出对,再用优化把参数调到让误差最小。这条闭环在监督学习里最干净——没有时间、没有探索,只有函数拟合。把它写清楚,后面强化学习的每处复杂度才有比较的基准。
1. 假设类与损失¶
监督学习选一个参数化的假设类 \(f_\theta:\mathcal X\to\mathcal Y\),用数据估计 \(\theta\)。假设类决定能表达什么:线性模型只表达线性关系,多层感知机表达连续映射,卷积网络利用平移结构,Transformer 利用注意力做变长依赖。机器人上常见的是后三者的组合——本体感受走多层感知机,图像走卷积或视觉主干,序列走注意力或循环结构。
损失函数不是随意挑的,它对应一个噪声模型。若目标是连续量且误差近似高斯,负对数似然化简为均方误差:
若目标是类别,负对数似然就是交叉熵:
两条式子来自同一个原则:最小化负对数似然,等于最大化数据在模型下的概率。选损失就是选"误差长什么样"——MSE 假设误差对称且尾部轻,交叉熵假设输出是概率分布。机器人回归任务里还要注意量的几何:位置误差可以直接取欧氏距离,姿态误差要在旋转空间里量,直接对四元数四个分量取 MSE 会把"同一姿态的两种符号表示"当成两个不同答案(约定见 control-note 第 7 章「姿态与坐标表达」)。
2. 经验风险与优化¶
真正想最小化的是数据分布上的期望损失(风险),手上只有有限样本,于是最小化经验风险——训练集上的平均损失。批量梯度下降每步用全量数据算梯度,代价太大;随机梯度下降(stochastic gradient descent, SGD)每步只取一个小批量 \(B\):
小批量梯度是全量梯度的有噪估计,噪声反而帮助跳出尖锐的局部结构。学习率 \(\eta\) 是整套训练里最敏感的超参:太大直接发散,太小则在预算内走不到。
自适应方法把每个参数的步长按历史梯度缩放。Adam 维护梯度的一阶矩与二阶矩估计,按 \(\hat m_t/(\sqrt{\hat v_t}+\epsilon)\) 归一化,对尺度差异大的参数(偏置与权重、不同量纲的输入)更宽容。它省掉了逐层调学习率的工作,代价是多出两个状态量与一组默认值——默认值对大多数任务够用,但换任务时仍应把它当作待验参数,而不是常量。
训练闭环的连接关系:
flowchart LR
data["训练集<br/>输入 x、标签 y"] --> batch["小批量 B"]
batch --> fwd["前向 f_θ(x)"]
fwd --> loss["损失 L_B"]
loss --> bwd["反向传播"]
bwd --> opt["优化器<br/>SGD / Adam"]
opt -->|"更新 θ"| fwd
fwd --> val["验证集评估"]
val -->|"泛化不升"| stop["早停 / 调参"]
3. 过拟合、正则与数据量¶
模型在训练集上误差持续下降、在验证集上先降后升,就是过拟合:模型记住了样本而非规律。诊断靠两条曲线的分叉,不靠单点数值。缓解手段各有代价:
- L2 正则:在损失上加 \(\lambda\lVert\theta\rVert^2\),压小权重,等价于假设"参数不该太大"。实现最简单,但会与批归一化等尺度处理互相干扰。
- Dropout:训练时随机置零一部分激活,迫使表示冗余;推理时要按保留概率缩放或使用对应的评估模式。
- 数据增强:对输入做保持标签不变的变换(图像裁剪与色彩抖动、状态加小噪声)。增强方式必须匹配任务的不变性——把左右翻转用在"左右手装配"上就改变了标签。
- 早停:验证指标不再改善就停止,用训练轮数当正则。
最有效的正则始终是数据量与多样性。机器人数据的稀缺是结构性的:一次真机示范要占用设备与人力,失败样本还带安全风险。常见做法是用大规模预训练表征降低对标注量的需求,再用小样本微调;这条路线把成本从前移到预训练,是否划算取决于下游任务的分布与预训练分布的接近程度(感知侧的做法见 camera-note 第 7 章「图像深度学习感知」)。
4. 划分、泄漏与指标¶
数据要分成训练、验证、测试三份:训练拟合参数,验证选超参与早停,测试只用一次、用来报告结论。机器人数据有个容易忽略的划分问题——同一回合的相邻帧高度相关。若按帧随机划分,验证集里会出现与训练集几乎一样的帧,指标虚高。正确做法是按回合分组划分:同一次示范的所有帧只能落在同一侧。
归一化统计量同样属于训练集:均值与方差只能在训练集上算,再原样用到验证、测试与部署。用全量数据算统计量是最常见的泄漏形式,它让指标好看一点,也让部署时的输入尺度与训练不一致。
指标要跟任务判据对齐:
| 任务类型 | 常用指标 | 判读要点 |
|---|---|---|
| 回归(位姿、力) | RMSE、MAE、分位数误差 | 误差分布比均值更能说明尾部失败 |
| 分类(检测、分割) | 精确率、召回率、F1、混淆矩阵 | 类别不平衡时准确率会骗人 |
| 机器人任务 | 阈值内成功率、平均完成步数 | 阈值与初始状态分布必须一起写明 |
成功率是最容易被含糊处理的指标:阈值取多少、初始状态怎么分布、评估多少次,三者不写清楚,数字之间不可比。第 10 章「训练工程、评测与迁移」会把口径补齐。
5. 张量形状与批维¶
实现层面最常见的错误不在算法,而在形状。约定一套固定顺序能省掉大量调试:批维放最前,其后按数据类型展开。
| 数据 | 形状 | 说明 |
|---|---|---|
| 状态向量 | (B, obs_dim) |
本体感受拼接后的定长向量 |
| 图像 | (B, C, H, W) |
通道在前,与 PyTorch 卷积约定一致 |
| 动作 | (B, act_dim) |
关节目标或末端增量 |
| 序列观测 | (B, T, obs_dim) |
帧堆叠或历史窗口,T 为长度 |
| 动作块 | (B, K, act_dim) |
一次预测 K 步,见第 8 章 |
观测与动作的归一化在训练与部署两侧必须用同一组统计量。把统计量随策略一起保存,是部署链路里最省事也最容易漏掉的一步:
# 数据归一化的最小实现:统计量只在训练集上估计,随策略一起保存
import torch
class Normalizer:
def __init__(self, x: torch.Tensor, eps: float = 1e-6):
self.mean = x.mean(dim=0) # (D,)
self.std = x.std(dim=0).clamp_min(eps) # (D,),防止常量维度除零
def __call__(self, x: torch.Tensor) -> torch.Tensor:
return (x - self.mean) / self.std
def state_dict(self) -> dict:
return {"mean": self.mean, "std": self.std} # 与策略 checkpoint 同存
一个最小训练循环把上面的环节串起来:取批、前向、算损失、反向、更新,每若干步在验证集上评估。
model = PolicyNet(obs_dim, act_dim)
opt = torch.optim.Adam(model.parameters(), lr=3e-4)
for epoch in range(num_epochs):
for x, y in train_loader: # x: (B, obs_dim), y: (B, act_dim)
pred = model(x)
loss = torch.nn.functional.mse_loss(pred, y)
opt.zero_grad()
loss.backward() # 反向传播填充 .grad
opt.step() # 按 Adam 规则更新参数
if epoch % eval_every == 0:
model.eval() # 关闭 dropout、固定归一化统计量
with torch.no_grad():
val_loss = evaluate(model, val_loader)
model.train()
坑:model.train() 与 model.eval() 不只是开关梯度
Dropout 与批归一化在两种模式下的行为不同。评估时忘了 eval() 会得到偏乐观或偏悲观的指标;训练时忘了切回 train() 则会让后续训练退化。
6. 一个静态映射为何不够¶
监督学习假设"给定输入有唯一正确答案"。机器人的序贯决策不满足这条假设:
- 动作改变下一状态。预测错一步,下一步的输入就偏离训练分布;误差沿回合累积,不会自己回到轨道。
- 没有标注的最优动作。自由空间里到达同一个位姿可以有无数条轨迹,示范只给了其中一条;把示范当唯一标签,模型会把"另一条同样好的路"也算成错误。
- 评价是延迟的。单个动作看不出好坏,好坏由整段回合的回报决定;这与逐帧标签的性质不同。
第一条是分布偏移问题,第 3 章「数据、表示与分布偏移」讲它的成因与判据;第二条与第三条是强化学习要解决的,第 4 章「马尔可夫决策过程与价值」给出形式。监督闭环本身没有失效,它变成更大闭环里的组件:感知头、价值网络、策略网络的最后一层都用它训练。
7. 要点¶
- 损失函数对应噪声模型,MSE 与交叉熵都来自负对数似然;姿态误差要在旋转空间里量。
- 学习率是最敏感的超参;Adam 的默认值是起点,不是结论。
- 过拟合看两条曲线分叉;最有效的正则仍然是数据量与多样性,其次是 L2、Dropout、增强与早停。
- 机器人数据要按回合分组划分,归一化统计量只在训练集上估计并随策略保存。
- 指标要与任务判据对齐;成功率必须同时写明阈值、初始状态分布与评估次数。
- 批维固定放最前;
model.train()/model.eval()影响 Dropout 与批归一化行为。 - 静态映射不足以描述序贯决策:动作改变状态分布、最优动作不唯一、评价延迟——这三点引出后续两章。
参考文献与延伸阅读¶
- Goodfellow, I., Bengio, Y., & Courville, A. Deep Learning. MIT Press, 2016. 书籍主页
- Bishop, C. M. Pattern Recognition and Machine Learning. Springer, 2006. DOI
- Kingma, D. P., & Ba, J. Adam: A Method for Stochastic Optimization. ICLR, 2015. arXiv
- Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I., & Salakhutdinov, R. Dropout: A Simple Way to Prevent Neural Networks from Overfitting. JMLR, 2014. JMLR
- PyTorch. torch.nn 文档. 文档