> 事先声明的偏差是限制,事后发现的偏差是借口
复现别人的工作时,你的环境一定会和官方配置有出入。 处理办法不是消除出入(做不到),而是在受影响的实验跑之前把它写下来:
// TABLE_OF_CONTENTS
结论先行¶
复现别人的工作时,你的环境一定会和官方配置有出入。 处理办法不是消除出入(做不到),而是在受影响的实验跑之前把它写下来:
事先记录的偏差是限制(limitation),事后发现的偏差是借口(excuse)。
配套的强规则让这份清单有牙齿:
没写在清单里的差异,都视为"这次运行应该和官方完全一致"; 对不上就是有 bug 要找,而不是"环境不一样嘛"。
没有这份清单,每一个对不上的数字都可以被"环境不同"解释掉, 于是没有任何结果能被证伪——复现就失去了全部意义。
为什么¶
一份实际的偏差文档长这样(每条都在受影响的运行之前写好):
D1 — attention 实现 官方: flash_attention_2 (flash-attn==2.6.3)
本机: 同上(已退役)
预期后果: attention 数值上的微小差异,与任何 kernel 变更同量级。
不应定性地移动任何指标。
⚠ 如果某个指标定性地变了,这条解释不了 —— 那是 bug。
三个值得单独记住的做法:
1. 每条偏差必须写"预期后果",而且要写出它解释不了什么。 "不应定性地移动指标"这半句才是有用的部分—— 它把偏差从万能挡箭牌变成了一个可以被违反的预测。
2. 偏差可以"退役",而且值得主动去退役。
D1 最初的理由是"pinned 版本必须从源码编译,本机 CUDA 版本不匹配所以编不出来"。
后来发现前提是错的:上游发布了预编译 wheel,
flash_attn-2.6.3+cu123torch2.4cxx11abiFALSE-cp311 正好匹配本机环境。
装上,偏差消失。
退役它的理由不是整洁,是:在退役之前,每一行结果都要重复解释同一个假象。 用 sdpa 时两次参考复现的不一致都是同一个形状(小 n、基于生成的 ROUGE 指标), 而且在第二个模型上复发。永远解释同一个假象,比消除它的成本高。
3. 原来的错误推理保留在文档里,标明"kept for the record"。 删掉它会让下一个人重新推一遍同样的错。
4. 「验证」是跑一次前向,不是 import 成功。
装完 flash-attn 后的验收标准是:_attn_implementation 报告
flash_attention_2,logits 形状正确且有限。
import flash_attn 不报错什么都不能证明——
和 最危险的工具故障是"静默少做"——技能在、后端不在 是同一类错误。
怎么用¶
偏差清单的最小模板(一条一节,放在 docs/02_DEVIATIONS.md):
## D<n> — <一句话标题> — [ACTIVE | RETIRED <日期>]
**官方:** 配置文件里原本是什么(给出文件路径和字段)
**本机:** 实际是什么
**为什么:** 不得不偏离的原因
**预期后果:** 会影响哪些指标、影响多大
**这条解释不了:** ← 最重要的一行
**如何退役:** 需要什么条件才能消除这条偏差
纪律:
- 清单写在跑实验之前,进版本库,有时间戳。
- 不得替换模型、数据划分、超参数。 不用 Qwen 代替 Llama, 不用"大致等价"的调度。整个复现阶段的价值就在于别人已经公布了这些数字该长什么样。
- 每次发现新偏差,先问"能不能退役",再问"要不要声明"。
- 定期回头看 RETIRED 的条目——它们记录着你曾经错在哪。
相关:复现契约——一个分数如果答不出这五个问题,它就不是结果(复现必须回答的五个问题)、 预先写下停止条件——不然你会一直重写一篇投错会的论文(同一种"事先写下来"的纪律用在投稿上)。
出处¶
~/RA-works/unlearning-reproduction/docs/02_DEVIATIONS.md- 上下文:TOFU unlearning(Llama-3.2-1B-Instruct)复现,2026-09