☰
VLA 系统学习第 10 课:为什么训练 Loss 很低,模型仍然可能什么都没学会?
2026/10/8 13:22:25 网站建设 项目流程

第九课标准答案

上一课的核心其实只有一条链:

\[ \text{Action Representation} \rightarrow \text{Model Output} \rightarrow \text{Loss} \rightarrow \text{Gradient} \rightarrow \text{Parameter Update} \]

所以答案也沿这条链来收。

1. 为什么不能直接把正负误差相加?

假设两个维度的误差分别是:

\[ -2,\qquad +2 \]

如果直接相加:

\[ -2+2=0 \]

看起来好像模型完全没错。

但实际上两个维度都预测错了。

所以 Loss 必须避免“正负误差互相抵消”。

MSE 采用平方:

\[ (-2)^2+(2)^2=8 \]

L1 采用绝对值:

\[ |-2|+|2|=4 \]

都能避免这个问题。


2. MSE 中 Mean、Squared、Error 分别是什么意思?

MSE:

Mean Squared Error

对应:

\[ L= \frac{1}{N} \sum_{i=1}^{N} (\hat y_i-y_i)^2 \]

其中:

  • Error:预测和正确答案之间的误差

    \[ \hat y_i-y_i \]
  • Squared:把误差平方

    \[ (\hat y_i-y_i)^2 \]
  • Mean:把所有平方误差求平均

    \[ \frac1N\sum \]

所以中文就是:

均方误差。


3. 专家 Action 为

\[ a=[1,3] \]

预测:

\[ \hat a=[2,5] \]

求 MSE

两个误差:

\[ 2-1=1 \]\[ 5-3=2 \]

平方:

\[ 1^2=1 \]\[ 2^2=4 \]

求平均:

\[ MSE=\frac{1+4}{2} \]

所以:

\[ \boxed{MSE=2.5} \]


4. 为什么 MSE 比 L1 更容易受到异常大误差影响?

因为 MSE 会平方。

假设误差:

\[ e=10 \]

那么 L1:

\[ |e|=10 \]

而平方误差:

\[ e^2=100 \]

如果误差进一步变成:

\[ 20 \]

L1:

\[ 20 \]

平方误差:

\[ 400 \]

所以误差越大,MSE 的惩罚增长得越快。

因此极端异常值会对 MSE 产生更强影响。


5. 为什么连续 Action 通常属于 Regression?

因为连续 Action 的目标通常是预测一个连续数值。

例如:

\[ \Delta x=0.013 \]

模型预测:

\[ 0.012 \]

这时候我们关心:

预测值和真实值之间差多少?

这正是 Regression,回归问题。

例如:

\[ [\Delta x,\Delta y,\Delta z] \]

中的每一维都可能是连续值。


6. 为什么离散 Action 不能用“类别编号的数字距离”衡量?

假设:

0 → Left 1 → Right 2 → Open Gripper 3 → Close Gripper

类别编号只是为了方便编码。

不能因为:

\[ |0-3|=3 \]

就说:

Left 和 Close Gripper 的动作差距是 3。

这个数字没有真正的动作几何意义。

所以分类问题关心的是:

正确类别的概率是否足够高。

而不是:

类别编号之间差几个数字。


7.logits.shape = [32,10]中 32 和 10 是什么?

\[ 32 \]

表示:

Batch Size

一次有 32 个样本。

\[ 10 \]

表示:

Class Number

每个样本对 10 个类别分别产生一个原始分数。

所以单个样本:

\[ logits:[10] \]

一个 Batch:

\[ logits:[32,10] \]


8. 为什么 Cross Entropy 可以理解成“提高正确类别概率”?

对于正确类别 \(y\),核心形式可以写成:

\[ L=-\log p_y \]

如果模型给正确类别概率:

\[ p_y=0.9 \]

Loss 很小。

如果:

\[ p_y=0.01 \]

Loss 很大。

所以为了降低 Loss,模型自然会被训练成:

\[ p_y\uparrow \]

也就是:

给正确类别更大的概率。


9. 为什么nn.CrossEntropyLoss()通常直接接 logits?

因为 PyTorch 的:

nn.CrossEntropyLoss()

内部已经组合了适合计算 Cross Entropy 的相关操作,并采用了数值更稳定的实现。

所以通常应该:

loss = loss_fn(logits, target)

而不是先:

prob = softmax(logits)loss = loss_fn(prob, target)

后者反而可能把接口用错。

因此看到:

nn.CrossEntropyLoss()

时应该先想到:

输入通常是原始 logits。


10. Action 一个维度范围[-0.05,0.05],另一个范围[-180,180],为什么直接 MSE 有问题?

因为数值尺度差距太大。

位置误差可能是:

\[ 0.01 \]

平方:

\[ 0.0001 \]

角度误差可能是:

\[ 10 \]

平方:

\[ 100 \]

于是总 Loss 几乎被角度维度控制。

模型训练时就会更关心:

把大数值尺度的那一维预测好。

而位置维度即使很重要,在 Loss 中也可能几乎没有存在感。


11. 为什么 Action Normalization 会直接影响训练?

因为它改变的不只是“数据长得好不好看”,而是改变每个维度进入 Loss 时的数值尺度。

例如:

\[ a'_i= \frac{a_i-\mu_i}{\sigma_i} \]

归一化以后,不同 Action Dimension 可能进入相近的范围。

于是:

\[ Action\ Scale \rightarrow Loss\ Contribution \rightarrow Gradient\ Magnitude \rightarrow Parameter\ Update \]

所以 Normalization 会真正改变模型训练过程。


12. 如何理解:

\[ Action\ Representation \rightarrow Model\ Output \rightarrow Loss \rightarrow Gradient \rightarrow Policy \]

如果 Action 是连续值:

\[ [\Delta x,\Delta y,\Delta z] \]

那么模型输出通常也是连续数值。

因此可能使用 Regression Loss。

如果 Action 是离散 Token:

\[ 0,1,2,\ldots,C-1 \]

那么模型可能输出:

\[ logits:[B,C] \]

再使用 Classification Loss。

Loss 决定“什么叫预测错误”。

Loss 再决定:

\[ \nabla_\theta L \]

也就是参数应该怎样变化。

参数变化以后,Policy 的行为发生变化。

所以:

\[ \boxed{ Action怎么定义 } \]

最终会一直影响到:

\[ \boxed{ Policy最后学成什么样 } \]

这也是以后读 VLA 时为什么一定先查 Action Representation。


VLA 系统学习第 10 课:为什么训练 Loss 很低,模型仍然可能什么都没学会?

到目前为止,我们已经完整建立了一条训练链:

\[ Dataset \rightarrow Batch \rightarrow Forward \rightarrow Loss \rightarrow Backward \rightarrow Optimizer \rightarrow Parameter\ Update \]

如果不断训练,通常会看到:

\[ Training\ Loss\downarrow \]

这时候很容易产生一个误解:

Loss 越低,模型就一定越好。

实际上完全不一定。

因为我们真正关心的并不是:

模型能不能把已经看过的数据做对。

而是:

面对没有参与训练的新情况,它还能不能做对。

这就自然引出了这一课最重要的概念:

\[ \boxed{Generalization} \]

泛化能力。


一、先看一个最极端的例子:把答案全背下来

假设我们有 100 个训练样本:

\[ (x_1,y_1), (x_2,y_2), \ldots, (x_{100},y_{100}) \]

模型非常复杂。

训练很久以后,它可能做到:

\[ x_1\rightarrow y_1 \]\[ x_2\rightarrow y_2 \]

一直到:

\[ x_{100}\rightarrow y_{100} \]

训练集上:

\[ Loss\approx0 \]

看起来非常厉害。

但现在给它一个从未见过:

\[ x_{101} \]

模型完全预测错误。

那么这个模型其实没有真正掌握规律。

它只是:

记住了训练样本。

这就是我们后面要说的:

Overfitting

过拟合。


二、什么叫 Generalization?

Generalization 可以理解成:

模型把训练数据里学到的规律,迁移到没见过的新数据上的能力。

例如训练时看到:

红色方块位于左侧 红色方块位于中间 红色方块位于右侧

测试时换成:

红色方块位于稍微不同的位置

模型仍然知道该怎么做。

这说明:

模型不是单纯记住某个固定像素或者固定状态,而是学到了某种更一般的 Observation → Action 关系。

因此真正希望得到的是:

\[ \boxed{ Training\ Performance好 + Unseen\ Data\ Performance也好 } \]


三、那怎么知道模型对“没见过的数据”表现怎么样?

最直接的方法就是:

不要把全部数据都拿去训练。

假设 Dataset 有:

\[ 10000 \]

个样本。

我们可以把它划分成:

\[ Train\ Set \]\[ Validation\ Set \]\[ Test\ Set \]

例如:

\[ 8000 \]

用于训练,

\[ 1000 \]

用于 Validation,

\[ 1000 \]

用于 Test。

这里具体比例没有统一规定,重点不是死记 80/10/10。

真正重要的是三者职责不同。


四、Train Set 是干什么的?

Train Set:

真正用来更新模型参数的数据。

也就是:

Train Batch ↓ Forward ↓ Loss ↓ Backward ↓ Optimizer.step()

模型参数:

\[ \theta \]

会直接从 Train Set 中学习。

所以:

\[ \boxed{ Train\ Set \rightarrow 更新Parameter } \]


五、Validation Set 又是什么?

Validation Set 用于:

训练过程中检查模型对未参与参数更新的数据表现如何。

假设每训练一段时间,我们在 Validation Set 上算:

\[ Validation\ Loss \]

但是:

Validation 数据通常不会拿来执行backward()和optimizer.step()。

也就是:

Validation Data ↓ Forward ↓ Validation Loss ↓ 观察结果

但不会:

Backward ↓ Update Parameter

六、那为什么还需要 Test Set?

你可能会想:

已经有 Validation Set 了,为什么还要 Test?

原因是:

我们训练过程中会不断根据 Validation 结果做决定。

例如发现:

Validation Loss太高

于是你可能:

  • 改 Learning Rate;
  • 改网络结构;
  • 改 Batch Size;
  • 改训练 Epoch;
  • 换 Optimizer;
  • 改数据处理。

然后再看 Validation。

这意味着虽然没有直接对 Validation 做 Backward,但是你这个“人”已经通过 Validation 结果不断调整模型设计。

于是模型开发过程实际上也间接利用了 Validation 信息。

所以最终还需要一份真正尽量没有参与开发决策的数据:

Test Set

用于最后评估。

因此可以理解:

\[ \boxed{ Train \rightarrow 模型学习 } \]\[ \boxed{ Validation \rightarrow 开发过程中选模型、调超参数 } \]\[ \boxed{ Test \rightarrow 最终评价 } \]


七、把整个训练流程写出来

现在一个更完整的机器学习过程是:

Dataset ↓ Split ├── Train Set ├── Validation Set └── Test Set

训练:

Train Set ↓ Forward ↓ Loss ↓ Backward ↓ Optimizer ↓ Update Parameters

一段时间后:

Validation Set ↓ Forward Only ↓ Validation Loss / Metric ↓ 判断模型是否真的在泛化

最终开发完成:

Test Set ↓ Final Evaluation

这才是完整的模型训练评估流程。


八、Overfitting 到底长什么样?

假设训练过程中:

EpochTrain LossValidation Loss
11.201.30
100.700.78
200.400.50
300.200.42
400.080.55
500.030.76

你会发现一开始:

\[ Train\ Loss\downarrow \]

同时:

\[ Validation\ Loss\downarrow \]

说明模型确实在学规律。

但是后面:

\[ Train\ Loss \]

继续下降,

而:

\[ Validation\ Loss \]

反而开始上升。

这就是一个非常典型的信号:

\[ \boxed{Overfitting} \]


九、为什么会发生 Overfitting?

可以把它理解成:

模型一开始学习:

数据里真正稳定的规律。

继续训练以后,模型越来越努力拟合 Train Set 的细枝末节。

例如:

  • 某些偶然噪声;
  • 某个相机角度下的特殊背景;
  • 某些示范者的操作习惯;
  • 某个固定物体位置;
  • 某一批数据里的特殊误差。

于是:

\[ Train\ Performance \]

越来越好。

但新数据没有这些偶然细节。

所以:

\[ Validation\ Performance \]

反而下降。


十、一个机器人例子会更直观

假设训练 Demonstration 中,物体总是在:

桌子中央偏左

背景总是:

同一个桌面

光照也完全一样。

模型可能学会:

某个固定像素区域出现红色,就执行某组 Action。

训练 Rollout 可能非常好。

但只要测试时把物体往右移动:

10 cm

模型就失败。

这说明模型并没有真正学会:

找到物体并根据物体位置控制动作。

而可能只是记住了:

训练数据中特定视觉模式。

这就是机器人任务中的 Overfitting。


十一、Underfitting 又是什么?

Overfitting 是:

Train 很好,但新数据差。

而 Underfitting:

欠拟合

是:

连 Train Set 自己都学不好。

例如:

EpochTrain LossValidation Loss
11.51.6
101.31.4
501.21.3

训练很久:

\[ Train\ Loss \]

仍然很高。

这可能意味着:

  • 模型能力太弱;
  • 训练时间不够;
  • Learning Rate 不合适;
  • 输入信息不足;
  • 数据质量差;
  • Loss 设计有问题。

所以:

\[ \boxed{ Underfitting = 训练数据本身都没学好 } \]


十二、用一张关系图理解三种情况

理想情况:

Train表现好 Validation表现也好 → Generalization较好

Underfitting:

Train差 Validation也差 → 模型连训练规律都没学会

Overfitting:

Train非常好 Validation变差 → 模型过度贴合训练数据

最重要的不是:

Train Loss 有多低。

而是:

\[ \boxed{ Train和Unseen Data之间的差距 } \]


十三、机器人 Dataset 有一个比普通分类更危险的问题:相邻 Frame 太像了

现在进入这一课对 Robot Learning 最重要的一点。

假设一个 Episode:

Frame 0 Frame 1 Frame 2 Frame 3 ... Frame 100

机器人控制频率比较高。

那么:

\[ Frame\ 50 \]

和:

\[ Frame\ 51 \]

通常非常相似。

相机可能只变化一点点:

Frame 50 夹爪位置 x = 0.312 Frame 51 夹爪位置 x = 0.314

图片几乎一样。


十四、如果我们随机按 Frame 划 Train/Test 会怎样?

假设我们把所有 Frame 混在一起:

random_split(all_frames)

可能出现:

Episode 7, Frame 50 → Train Episode 7, Frame 51 → Test Episode 7, Frame 52 → Train

这时候 Test Set 看起来没有直接参与训练。

但 Test Frame:

\[ 51 \]

和训练里的:

\[ 50,52 \]

几乎一模一样。

于是模型在 Test 上表现很好。

你可能得到:

\[ Test\ Loss \]

非常低。

但这个结果并不能真正说明:

模型对新的任务执行有很强泛化能力。

因为它几乎已经看过 Test 数据前后相邻的画面。

这叫:

Data Leakage

数据泄漏的一种典型形式。


十五、为什么机器人 Dataset 更应该按 Episode 划分?

一种更合理的思路是:

Episode 0~79 → Train Episode 80~89 → Validation Episode 90~99 → Test

这样整个:

\[ Episode\ 90 \]

从来没有出现在训练里。

测试时模型面对的是一整条真正没参与过训练的轨迹。

于是评估更接近:

面对一次新的任务执行,Policy 是否仍然能工作。

所以:

\[ \boxed{ Robot\ Dataset 通常更应该关注Episode-level split } \]

而不是把所有 Frame 完全随机混合后再切。


十六、但“按 Episode 切”也不自动等于真正泛化

这是更进一步的重要认识。

假设:

Train Episode 和 Test Episode

虽然是不同 Episode,

但所有 Episode 都有:

  • 同一个物体;
  • 同一个位置;
  • 同一个背景;
  • 同一个光照;
  • 同一种任务。

那么 Test 仍然很接近 Train。

所以你必须继续问:

我到底想测试哪种 Generalization?

这就涉及:

新初始位置? 新物体? 新背景? 新语言指令? 新任务? 新相机视角?

不同论文的 Generalization 定义可能完全不同。

以后看 Benchmark 时,必须查清楚。


十七、为什么 Robot Learning 最终还要做 Rollout Evaluation?

即使 Test Dataset 上:

\[ Loss \]

很好,仍然不能完全证明 Policy 能完成任务。

因为离线 Test Loss 仍然是在问:

给定 Dataset 中正确的 Observation,模型能不能预测正确 Action?

但真正 Rollout:

Observation ↓ Predicted Action ↓ Execute ↓ New Observation ↓ Predicted Action ↓ ...

模型自己的动作会改变后续 Observation。

因此最终必须测试:

连续闭环执行一整个任务,会不会成功?

于是常见最终指标可能是:

\[ Success\ Rate \]

例如:

\[ \text{Success Rate} = \frac{\text{Successful Rollouts}} {\text{Total Rollouts}} \]

假设测试 50 次:

\[ 37 \]

次成功,那么:

\[ \frac{37}{50}=0.74 \]

即:

\[ 74\% \]


十八、所以 Loss 和 Success Rate 在回答不同问题

Test Loss:

对离线专家数据,模型的 Action 预测有多准?

Success Rate:

模型真正闭环执行整个任务,最终完成了多少次?

这两者相关,但不是同一回事。

完全可能:

\[ Test\ Loss很低 \]

但是:

\[ Success\ Rate不高 \]

原因可能还是我们之前讲过的:

Distribution Shift

所以现在几章终于连上了:

\[ Training\ Loss \]

只是训练问题。

\[ Validation/Test \]

开始检查离线泛化。

\[ Rollout \]

进一步检查真实闭环行为。


十九、Validation 时为什么通常要model.eval()?

现在第一次自然遇到:

model.eval()

注意:

eval()不是“开始计算测试指标”的函数。

它的作用是:

把模型切换到 Evaluation Mode。

为什么需要这个模式?

因为有些层在训练和测试时行为不同,例如之后会学习的:

  • Dropout;
  • BatchNorm。

所以训练:

model.train()

Validation / Test:

model.eval()

告诉这些层:

现在不是训练阶段,请使用评估行为。

但:

model.eval()

不会自动关闭梯度计算。

这是另一个概念。


二十、为什么 Validation 还常出现torch.no_grad()?

因为 Validation 不需要:

\[ Backward \]

也不需要:

\[ Gradient \]

所以代码可能写:

model.eval()with torch.no_grad(): pred = model(obs) loss = loss_fn(pred, action)

这里:

torch.no_grad()

表示:

这段计算不需要构建用于梯度计算的 Autograd 图。

这样可以:

  • 减少显存占用;
  • 减少一些计算开销。

所以:

model.eval()

和:

torch.no_grad()

不是一回事。

前者:

改变某些 Module 的训练/评估行为。

后者:

关闭这段代码中的梯度跟踪。

这一点以后非常高频。


二十一、一个完整 Training + Validation Loop 开始成形

现在我们已经可以读懂这种结构:

for epoch in range(num_epochs): model.train() for batch in train_loader: obs = batch["observation"] action = batch["action"] optimizer.zero_grad() pred = model(obs) loss = loss_fn(pred, action) loss.backward() optimizer.step() model.eval() with torch.no_grad(): for batch in val_loader: obs = batch["observation"] action = batch["action"] pred = model(obs) val_loss = loss_fn(pred, action)

现在不要把它看成两段孤立代码。

它是:

Train Set ↓ Forward ↓ Backward ↓ 更新模型

然后:

Validation Set ↓ Forward ↓ 检查当前模型泛化 ↓ 不更新模型

二十二、为什么不能在 Validation 上optimizer.step()?

因为一旦这么做:

val_loss.backward()optimizer.step()

Validation Set 就参与了参数训练。

它就不再是:

未参与训练的数据。

于是它失去了验证泛化能力的意义。

所以最基本原则:

\[ \boxed{ Validation/Test 不用于普通Parameter Update } \]


二十三、Validation 会参与“模型选择”

假设训练 100 Epoch。

你发现:

EpochValidation Loss
200.30
400.20
600.15
800.19
1000.25

最好的 Validation 是:

\[ Epoch\ 60 \]

于是最终可能保存:

\[ Epoch\ 60 \]

的模型,而不是 Epoch 100。

这就是:

Model Selection

模型选择。

所以 Validation 虽然:

不直接通过 Backward 修改参数,

但会影响我们:

最终选择哪个模型。

这就是为什么 Test 还应该再独立出来。


二十四、Early Stopping 是怎么自然出现的?

刚才:

Epoch 60 Validation最好

之后 Validation 越来越差。

说明可能开始 Overfitting。

那么一种策略就是:

Validation 连续一段时间没有改善,就停止训练。

这叫:

Early Stopping

早停。

它的逻辑就是:

Train Loss继续下降 但Validation不再改善 ↓ 继续训练可能只是在过拟合 ↓ 停止

这不是所有训练都必须用,但概念上非常重要。


二十五、现在重新理解“一个模型训练成功了”

不能只说:

代码跑通了

也不能只说:

Training Loss降到了0.01

至少应该依次问:

\[ \boxed{ Training\ Loss怎么样? } \]

↓

\[ \boxed{ Validation/Test怎么样? } \]

↓

\[ \boxed{ Rollout怎么样? } \]

↓

\[ \boxed{ 真正任务Success Rate怎么样? } \]

这才逐渐接近:

Policy 真的有效。


二十六、第十课整章主线回看

从 Dataset 开始:

\[ \mathcal D \]

不能全部直接拿去训练并用同一批数据证明自己很好。

而应该建立:

\[ \mathcal D \rightarrow \{ D_{train}, D_{val}, D_{test} \} \]

其中:

\[ D_{train} \]

负责:

\[ \theta\text{更新} \]\[ D_{val} \]

负责:

开发过程中的模型选择与超参数判断。

\[ D_{test} \]

负责:

最终独立评估。

如果:

\[ Train\ Loss高 \]

可能是 Underfitting。

如果:

\[ Train\ Loss低 \]

而:

\[ Validation\ Loss高 \]

可能是 Overfitting。

而机器人数据还必须特别注意:

\[ \boxed{ 不要因为相邻Frame高度相似 而造成Train/Test数据泄漏 } \]

因此评估时经常应该考虑:

Episode-level split

最终还要通过:

\[ Rollout \]

检查闭环任务表现。


第十课自测

  1. Generalization 到底是什么意思?

  2. Train、Validation、Test 三者最核心的职责分别是什么?

  3. 为什么 Validation 没有参与backward(),却仍然不能完全替代 Test Set?

  4. 什么叫 Overfitting?它的 Train Loss 和 Validation Loss 通常会呈现怎样的关系?

  5. 什么叫 Underfitting?

  6. 为什么 Robot Dataset 如果随机按 Frame 划分 Train/Test,容易产生 Data Leakage?

  7. 为什么按照 Episode 划分通常比随机 Frame 划分更合理?

  8. 按 Episode 划分以后,为什么仍然不能直接宣称拥有很强的 Generalization?

  9. Test Loss 很低,为什么 Rollout Success Rate 仍然可能不高?

  10. model.eval()和torch.no_grad()有什么区别?

  11. 为什么 Validation 阶段不能执行普通的optimizer.step()?

  12. 如果 Epoch 60 的 Validation 最好,而 Epoch 100 的 Train Loss 更低,你更可能保存哪个 Checkpoint?为什么?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询