> 你的定理预测了一个退化情形——那就拿代码去测它,别等审稿人问
论文里有一条命题,大意是「在某类退化结构上,若干候选的得分会精确相等」。 证明是对的,陈述是干净的,审稿人也认可。
// TABLE_OF_CONTENTS
结论先行¶
论文里有一条命题,大意是「在某类退化结构上,若干候选的得分会精确相等」。 证明是对的,陈述是干净的,审稿人也认可。
然后没有任何人去问:代码在精确相等的时候做什么?
答案是 argmax 按插入顺序返回第一个——而那个顺序来自一串 UUID,
也就是说,在定理预测会出现平局的那一整类情形上,结果由对象创建顺序决定。
一条定理如果预测了某个退化情形,它同时就是一个针对你自己实现的、 已经写好的测试用例。不写那个测试,等于把定理最锋利的那部分留给审稿人去用。
为什么¶
这件事的结构值得拆开看,因为它不是"忘了写测试"那么简单。
定理和实现分属两套心智。 写证明时你在想"这类结构会导致得分相等", 这是一个关于数学对象的陈述;写代码时你在想"取最大的那个", 这是一个关于数组的操作。两边都正确,而它们在"相等"这个点上交汇时, 数学说"无法区分",代码说"返回下标最小的那个"。代码替数学做了一个它没授权的决定。
退化情形在随机测试里几乎抽不到。 浮点得分精确相等的概率接近零—— 除非结构保证它,而定理说的正是「这类结构保证它」。 所以:定理恰好指出了那些随机测试覆盖不到、而又必然发生的输入。
它通常不报错。 没有异常、没有警告,结果看起来完全正常, 只是在那一类输入上它测的是 UUID 而不是你的方法。
一条配套的、更难受的¶
同一次复盘里还有一条:论文规定要报置信区间,而论文自己的头条数字是点估计。
一篇讲报告规范的论文,会被用它自己的规范来要求——这是公平的, 而且审稿人会在发现任何技术缺陷之前就注意到这一点。
更一般的形式:你在论文里写下的每一条"应该怎么做", 都是一条读者会拿来量你自己的尺子。 清单、协议、检查项—— 写进去之前先在自己的产物上跑一遍,并且把结果写下来。
怎么用¶
定稿前,把定理当测试规格来读:
- 列出每一条定理/命题预测的退化情形。 典型的几类: 精确相等(tie)、空集、单元素、单类别、零方差、对称输入、 参数取到声明范围的端点。
- 每一条写一个断言测试。 不是"跑一下看看对不对",是 断言在那个输入上的行为是你想要的那个。 平局要么显式随机打破并固定种子,要么显式报错,要么文档写明规则—— 但不能是"碰巧按插入顺序"。
- 特别检查
argmax/max/sort/top-k。 这几个是平局规则的隐身处。Python 的max和np.argmax都返回第一个, 而"第一个"取决于你是怎么把元素放进去的。 - 把论文自己提出的清单,在论文自己的产物上跑一遍,并把结果写进附录。 跑了且干净,是一句很强的话;跑了且发现问题并修了,更强; 没跑而读者替你跑了,最弱。
- 摘要和引言里引用的每一个比较,都要带区间——尤其当论文本身主张要带区间时。
出处¶
自己一篇被拒论文的复盘。这里只保留可迁移的部分: 定理预测的退化情形未被实现测试、以及方法学论文被自身标准要求这两条。 不包含评审意见、评分、会场或该论文的贡献内容。 相关:一个写出来的界是可执行断言——拿它自己声明的参数范围去跑,我的界被我的反例推翻了、 用 any() 写的回归测试是假保证——它只要求最容易过的那个夹具通过、测不出失败的门禁比没有门禁更糟——它在制造信心、 自审的失效模式不是"没发现",是"发现了没执行"。