> 没屏蔽的 padding 会自己制造出"表征崩塌"——而那正是你要测的现象

Machine Learning Theory Intermediate 2026-10-12 04:23 2026-10-11
#training #padding #loss #measurement #artifacts #failure-modes

一次训练冒烟运行里,LM loss 用 labels=input_ids 算——也就是把 pad 位也算进去了。 两个后果都很严重:

// TABLE_OF_CONTENTS

结论先行

一次训练冒烟运行里,LM loss 用 labels=input_ids 算——也就是把 pad 位也算进去了。 两个后果都很严重:

一、探针的 held-out loss 被抬高了:8.40,而真值是 2.90(一个未改动的预训练检查点)。 于是那个本该用来区分"正常锐化"和"真崩塌"的下游探针信号, 根本不是在量困惑度。

二、训练时模型花容量去建模 padding 的结构,而这件事本身就驱动出一个退化表征。 同一个设置下,有效秩的变化:

修复前 修复后
高学习率下 r_eff 192 → 2.88 192 → 84

那个戏剧性的"崩塌",大部分是 padding 产物,不是被诱导出来的那个模式。

修法是一个 make_labels():pad 位置填 -100,并且探针批次和训练批次都要用。 修复前的所有数字作废。

为什么

这个 bug 的恶性程度来自一个巧合:它制造的伪影,和被研究的现象长得一模一样。

padding 位的隐状态彼此几乎相同(同一个 pad token、相似的位置上下文), 于是它们在表征空间里挤成一团:

  • 协方差被一个方向主导 → 有效秩塌向 1;
  • 方差比、k_95、RankMe 之类所有基于谱的指标同向移动;
  • 而序列越短、pad 越多,效应越强——它还会随数据分布系统性地变化。

所以你不会看到一个"坏掉"的信号,你会看到一个漂亮、单调、可复现的崩塌曲线。 这是最难发现的那一类错误:它不降低结果的质量,它提高结果的说服力。

同一个形状在别处的样子:

  • 把 -100 忘在某一侧(只在训练里屏蔽、评测里没屏蔽),两边的数不可比;
  • attention mask 对了但 label mask 没对(这一例);
  • 右 padding 与左 padding 混用,导致"最后一个 token"取到 pad 上。

怎么用

  1. 在任何表征/谱类测量之前,先在一个未改动的预训练检查点上量一遍。 如果健康模型就已经接近指标的下界,那你测的不是模型。
  2. 把 held-out loss 和一个已知基准对齐。 8.40 对 2.90 这个差距足以单独暴露问题—— 一个预训练模型在普通文本上的困惑度量级是已知的,拿它当哨兵。
  3. mask 要同时检查三处:attention mask、label mask(-100)、池化时的加权。 三处里漏一处,症状各不相同但都是静默的。
  4. 用"去掉 pad 之后结果变不变"做一次对照。 把 batch size 设成 1、不 padding 跑一遍,和 padded 批次比。 数字不一致,就是 mask 的问题。
  5. 伪影修掉之后,明确声明旧数字作废,不要让它们留在同一张表里。

出处