# 消融实现 本轮被采纳的改法由几个因子组成。研究者想知道每个因子各撑了多少分,办法是从完整代码出发,一次只关掉一个因子、其余照旧,再跑一次正式实验——这样的一次叫一格。分派给你的是其中一格:材料"这一格"一节写明要关哪个因子、关掉时换成什么。第一次做这一格时,你的工作目录是完整代码(被采纳的那份)的副本;退回重做时,是你上一次交的这一格代码的副本(见下面"退回意见")。完整代码和本批基线的冻结目录都写在材料"完整代码(消融的起点)"一节。 ### 只关这一个因子 把指定的因子换回它关掉时的做法:因子里写了"关掉时换成"的,照写的做;没写的,回到本批基线在这件事上的做法——去基线的冻结目录里看它原来怎么写。关法是走这一条已有定义的做法,不为它新造第三种关法:新造关法,这一格测的就是"缺了这个因子"加上"你的关法"两件事。其余的因子、因子自带的设定值、保障都照完整代码保留,一处都不动。 指标的采集代码也照完整代码保留:这一格同样采集冻结协议登记的全部指标。被关掉的因子本身测不到的量(比如只有那个因子才会计数的次数),写 null,不写 0——这一格不会因为它缺失而作废,这是消融的本义。 材料里有完整代码那次实现交的因子位置表,照它找这个因子在哪几行。位置表只是线索:一个因子的代码可能散在几处,也可能跟别的因子共用一段;共用的那段里,先分清这段代码里哪些行为是这个因子带来的——关掉后消失的那些才是你的改动对象,其余原样,哪怕它们和这个因子的代码写在同一个函数里。 这一格之所以只关一个因子,是因为它要回答的问题是"少了这一个因子,分数少多少"。你多关了一处,测出来的就是两件事一起少掉的分;少关了一处,这个因子就还有一部分开着。两种都会让研究者对这个因子的判断建立在错的数上,而且从分数上看不出来。 ### 真的跑不起来时 只关这一个因子以后,代码有时真的跑不起来:比如别的因子要用一个只有这个因子才算出来的量。这时才考虑连带关掉别的因子——在 `alsoOff` 里写上还要一起关的因子,在代码里把它们也换回关闭做法,并在 `concerns` 里写清为什么离了这个因子它们跑不起来。连带关是为了绕开一个和本次测量无关的跑不起来,写到最小:只关离了它真的跑不起来的那些;为了让这一格更稳、更好看而多关,测到的就不再是这个因子。 "关掉以后效果会变差"不是跑不起来:消融要测的正是变差多少,照样只关指定的因子。也不要为了让它更好跑而改别的地方。 连一起关的办法也给不出,就交"这一格跑不起来",在 `cannotRun` 里写原因:这一格不启动、不扣运行次数,研究者会读到你写的原因。这是一个正常的结论。 材料里没有任何成绩和研究者的判断,这是有意的——你照因子清单做就行,不用知道哪个因子被认为更重要,也不需要知道关掉以后会得多少分。 材料"本任务要处理的东西"最前面有"退回意见"时,说明上一次交的这一格没通过消融核验:意见列出了关错的因子和核验员看到的位置。这时工作目录是你上一次交的这一格代码,从它接着改:照意见把关错的因子改对,其余照旧,仍然只关这一格要关的因子;核验员看错了的,在 `concerns` 里写清实际在哪几行。 交之前用 `diff -ru <完整代码冻结目录> .` 看一遍——参照物是完整代码,不是本次任务的工作目录(退回重做时工作目录是你上一次的提交,和它 diff 出来的只是这次又改了什么):改动应该只落在这个因子(和你写进一起关的因子)的位置上,加上把这个因子的指标改写成 null 的那几行。 关掉这个因子以后,你读代码看出某处会出问题,写进 `concerns`,说清是哪一处、为什么。值得专门想一想的一个形状是:没有了这个因子,某条保障或兜底路径被用上的频率会不会整个变样——变得每次都走,或者再也走不到。这不是要你避开它:保障变成每次都走,本身就是这一格量到的现象的一部分;写出来是为了让研究者读结果时知道,这一格量到的可能不只是"少了这个因子"。照常只关指定的因子,不因为担心就改别处。没有就写"无"。 ## 交什么 需要一起关的因子(`alsoOff`,只关指定的因子就交空数组);跑不起来时的原因(`cannotRun`,跑得起来写 `null`);实现时发现的问题(`concerns`,有一起关的因子时在这里写清为什么;没有写"无")。核验员会对着改动逐个因子看它是关着还是开着。