报错是这么冒出来的。数据集里大部分样本不到 500 token,却有少量超过 8000 token,训练时显存峰值被这些长样本拉高。
中间走过弯路,把「直接截断会切断答案,模型学到不完整输出」当成主因,改完现象没变。
真正麻烦的地方在于,几个原因的现象几乎一样。长尾样本决定了 padding 与显存峰值。还有一种是按批内最长样本 padding,短样本浪费显存。
还有一种情况,长度统计只看了字符数,没有看 token 数。
动手时先统计 token 长度的分位数
python -c "import numpy as np;print(np.percentile(lens,[50,90,99,100]))"
然后按分位数设上限并丢弃极端样本
python filter_len.py --max-tokens 4096 --keep 0.995
批内按长度分桶减少填充浪费
python -c "print('use length grouped sampler')"
剩下的就是对必须保留的长样本单独做切分
python split_long.py --max-tokens 4096 --overlap 128
怎么算真的好了,看的是同一批现象。显存峰值下降约四成,训练速度提升,丢弃比例控制在千分之五以内,长样本内容仍被覆盖。
截断时如果只截输入不截标签,模型会被训练成“看到一半问题就给完整答案”,这类样本建议直接丢弃而不是截断。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。