> 放宽了计数口径,就必须在同一次改动里重算阈值——否则每个被测对象都会静默地"落在区间内"

Research Tools Intermediate 2026-10-12 06:18 2026-10-12
#calibration #thresholds #metrics #measurement #regression #controls

一个工具用"参照语料的区间"做判定:9 篇高引论文量出 第一人称断言密度 1.20–3.22 / 千词,被测对象低于下限就提示看一眼。

// TABLE_OF_CONTENTS

结论先行

一个工具用"参照语料的区间"做判定:9 篇高引论文量出 第一人称断言密度 1.20–3.22 / 千词,被测对象低于下限就提示看一眼。

计数的正则有缺陷(只认现在时),修好之后分子变大了。 修的人拿新口径的计数(1.37)去比旧口径算出的区间(1.20–3.22), 得出"落在区间内"。

两侧同时重算之后,区间变成约 1.65–5.01,而那篇的相对位置几乎没动 (从下限的 0.38× 变成 0.42×)。结论从"合格"翻回"偏低",被测对象一个字没改。

分子(计数) 分母(区间下限) 判定
只改分子 1.37(新) 1.20(旧) 合格 ✗
同时重算 1.37(新) 1.65(新) 偏低 ✓

偏差是单向的:放宽计数让每一个被测对象的数字变大, 而旧区间原地不动,于是所有人同时变合格。 一个判定规则同时给所有对象放行,这件事本身就该触发怀疑。

为什么

区间不是一个常数,它是用某个具体的计数函数在某个具体语料上算出来的量。 换了计数函数,旧区间描述的是一个已经不存在的测量。

这件事在代码里很难看出来,因为两者的距离很远:正则在 final_reviewer.py 顶部,区间在 calibration.json 里, 中间隔着一个要联网拉 arXiv 包的重标定脚本。改一个很便宜,重算另一个很贵, 而贵的那一步不做,结果依然会打印出来并且看起来正常。 所以这条必须写成硬约束,不是建议 —— 这个项目把它写进了正则定义旁边的注释: 改了正则就必须在同一次改动里重跑标定。

重标定成功的那次顺手带了一个很漂亮的正向对照: 新正则在构造上是旧正则的超集,所以每篇的计数只能升不能降。 9 篇全部上升或持平(ResNet 19→22 … CoT 9→11),没有一篇下降。 如果有一篇降了,说明"超集"这个前提假了 —— 比如某个旧动词在重写时丢了。 一次重标定本身需要一个廉价的、不依赖人工判断的自检,而单调性常常就是现成的那个。

与此相对,这个项目也记下了一条更早、更隐蔽的版本: 早期几个"更夸张"的数字(16 倍差距、某篇第一页断言为 0)来自 "数正则命中 + 更宽的动词表",而那个数法最后没有出厂。 工具的阈值必须来自工具自己数的东西,否则报告里给出的理由是假的 —— 那和"一条从没跑过的检查报了通过"是同一类错误。

怎么用

让阈值文件记住它是用哪个口径算的。 最小做法:标定产物里存 tool_version 和计数函数的指纹,判定时比对;不一致就拒绝判定, 只输出原始计数。这比提醒人记得重跑可靠,因为它在使用的时候报错, 而不是在修改的时候。

改分子的 PR 必须带上重算后的分母。 判断标准很简单: 这次改动之后,被测对象的数字是不是普遍朝一个方向动了? 如果是,阈值一定也要动;只有一个也没动的时候,才可能不需要重算。

给重标定找一个单调性或守恒量当对照。 超集 → 计数不降、 去重 → 总数不增、加一类样本 → 分母不减。这类对照不需要知道正确答案, 但能抓住"我以为是放宽,其实顺手改坏了一处"。参考 覆盖率这类比值能抓到不抛异常的缺陷——而"每页小节数"抓不到:同一个思路用在数据缺陷上。

警惕"所有对象同时变好"。 这是口径漂移最可靠的指纹。真实的改进 会让一部分对象变好、一部分不变;全体朝一个方向移动,通常是尺子动了。

出处

~/Tools/final-reviewer:final_reviewer.py:80-125(三层修法与 "改了正则必须同一次改动里重跑标定"的注释)、 CALIBRATION.md 2026-10-04 的「差一点发生的事:只放宽分子不重算区间」、 「重标定本身也出了一次"没检查却报干净"」与「丢掉的两条规则」三节、 fixtures/calibrate.py、calibration.json(tool_version 2026-10-04.1,n=12)。