Daniel Holden 在角色动画和深度学习的领域做了很多出色的工作,我偶然看到他的一篇博文,很受启发。因为真的喜欢,所以我尝试翻译大体内容,分享他的经验之谈。
以下出自 Daniel Holden 的博文:Why Can't I Reproduce Their Results?
这是我希望自己在研究生时就明白的道理。
在我读博士的时候,关于阅读最新进展的论文,并试图复现论文结果的体验,我记得很清楚。
这种体验说怎么糟糕都不为过,我一如既往地得到相同的结果:效果不好。无论我怎么尝试,我就是不能复现他们的结果,即使我怎么变换技巧、调参炼丹,得到的都是更糟糕的结果,始终如一。
一直以来,我也确实看到一种怀疑的论调,摧毁了我很多朋友和同事们的积极性。我也开始怀疑他们所说的真实性:
- “都是学术上的官僚主义。”
- “作者有意隐藏了细节,让他的研究成果看起来很牛逼。”
- “论文展示的都是最好的结果。”
- “除了一堆数学术语,啥有用的东西都没有。”
没错,在某些程度上,可能的确是这样。
但是,当我在研究生时,我还没有意识到:“复现论文其实是学术界上的死记硬背。”你感觉到痛苦,因为你在做机械式学习。从伪造到制造的学习方法的目的,并不是要真的成功。它的目的是增强你对该领域的熟悉程度,以便你在尝试解决问题的时候,不会感到太害怕,也不会因为不自信而退缩。
不过,作为研究生,这种痛苦和沮丧是真实存在的。如果时光回溯,我可以给自己一些建议的话,我希望自己可以明白:
- 为什么这些方法不管用?
- 为什么我复现的结果更糟?
- 为什么那些符号又难又不准确?
- 为什么论文使用不一致的术语?
- 我该如何赶上其他人?
- 作者怎么选取参数 X 的值?
- 为什么没有源码和数据?
- 为什么其他人的结果这么亮眼?
- 为什么我的审稿人又懒又不公?
- 为什么其他人懂的那么多?
为什么这些方法不管用?
比起学术界的阴谋论,有时会出现更让你难以置信的事实:你的代码有 bug。
我不知道是具体是哪个 bug,因为它可能是成千上万种可能中的一种:从最基础到最高级的。可能你有 typo?可能变量名用错了?可能调用函数的顺序错了?可能调用的函数错了?可能误解了某个函数的作用?可能数组索引搞错了?可能数据预处理搞错了?可能数据一开始就污染了?可能有异常值、无效值?可能可视化搞错了?可能需要对矩阵进行转置?可能文件路径搞错了?可能有数值问题?可能你需要在方程加上一个小的阈值?这个清单可以有无限长...
要调试科研代码是非常难的,这需要不同的思维方式,对细节的把控超越你的想象。对于科研代码,特别是数值和数据驱动的代码,bug 不会以崩溃的方式显现;这些 bug 通常正常运行,但是会产生破坏性的后果。你有责任验证每一行代码都是正确的。有时,这需要用最麻烦的方式做事:亲手检查数据,逐行检查每一行代码,直到发现问题所在。
为什么我复现的结果更糟?
吸引很多人进入学术界的一件事是,人们认为这是一个仅仅靠想法(idea)就能成功的领域。我们都希望自己工作的领域,可以靠着一个好的想法,靠一种做事情、解决问题、思考问题的好的方式,就能够获得认可。
但实际上我们也在计算机科学领域工作,这意味着我们不仅需要想法,还需要有验证,我们希望想法能够用代码来实现,还要有实验、评估和比较。
于是问题就来了,由于编程无疑是一项需要实践和提高的技术,因此,如果不能用编程很好地实现,再好的想法也不会得到好的结果。经验同样也很重要。你对问题的理解和经验,对于想法的实现都会产生很大的影响。
事实上,在计算机科学中的大多数研究,并不是我们所想象的思想的精英主义。一个实现得好的普通想法,与一个实现得差的好想法,前者往往会得到更好的结果。因此很遗憾,我必须得说,这就是你的结果更差的主要原因——原文作者在该研究中,比你做了更多的实践,并且比你更有经验。就是这样而已。
因此,随着你的经验和实践的提高,你的结果也会变好,最终你可以做足准备拥抱好的想法——准备好一个完美灌篮。
为什么那些符号又难又不准确?
你是否阅读过在数学符号还没有发明之前的数学论文?看一看 1575 年的一篇数学论文的引用,它讨论等号的使用:
我们很容易忘记,曾经数学的讨论也是在散文里面,没有符号的,就像大声喊出来的感觉一样。你可以想象一篇 13 页的 SIGGRAPH 在这种情况下会像什么……
在这种情况下,历史是比较重要的,因为大多数研究生在数学符号上容易犯的错误是,他们认为符号的主要目的是精确。并不是,数学符号首先是为了简洁和方便理解。精确和计算(precision and computation)是次要的。
与此同时,现代计算机科学论文提出的大多数系统,是非常复杂并且难以理解的——它们构建在无数其他的系统、决策和假设之上。你在论文中看到的只是冰山一角。作者当然也知道这一点,但写论文需要在确保所有细节到位和避免繁琐导致无法阅读的两者之间,做出微妙的平衡。这意味着,在描述算法和代码时,作者常常面临一个艰难的选择:
- 用一种更精确、但也更复杂、冗长且难以理解的方式来描述实现。
- 用一种不太精确、但更简单、更短且更易于读者理解的方式来描述实现。
在这种双输局面,我相信大多数研究员(包括我自己)都会倾向于第二种选择(也许会让很多研究生感到失望)。这里面的道理是,读者能够很好地理解概念,他们有望靠自己填补那些不那么重要的细节。
所以请记住这一点:数学也曾经是散文,仅仅因为现在它已经符号化,并不意味着你可以将它看成代码一样的东西。尽管很难,但也要尝试运用你的直觉。研究符号约定和相关工作。尽可能多地研究数学及其历史,这会让你代码编写更加容易。
为什么论文使用不一致的术语?
优秀、流畅、易于阅读的散文的最基本原则之一,是不要太频繁地重复单词。这在学术论文中也差不多,许多学者在潜意识里会切换术语,以避免过多的重复,让读者打瞌睡。这在论文的摘要和介绍部分尤其如此,这些部分希望通过一种易于阅读的方式来引入主题。
但是对于研究生来说,他们很可能不熟悉同一概念的不同命名,这种术语的频繁切换会使得他们需要进行繁琐的交叉引用、查阅维基百科,才能够读完论文。
而我会尽量忘记精确的定义、交叉引用和 Wikipedia。尽量从上下文中推断出尽可能多的内容。随着实现一些工作时,你会有更精确的理解,要知道,学术界中的许多术语,多多少少都会有一些模糊不清和繁杂。论文通常会在方法论部分围绕术语的使用,这里可以重点关注。
我该如何赶上其他人?
你是否曾经尝试实现一篇论文,结果发现一行这样的话: "We start from [Smith et al. 2020]",然后又发现, [Smith et al. 2020] 实际上是一串论文工作中的最新论文,这一串论文又是由一名博士生完成的五年工作,包含着大量未公开的代码?
是的……真的令人沮丧。但是根据定义,研究处于人类知识的边缘,不幸的是,这意味着通常它不能在几个月内就搞定,放在一个独立可访问的包中。
坏消息是,还不知道他们的研究中有投入了多少工程化的工作,这个因素也会导致没有代码和数据,难以复现论文结果。
好消息是,你有机会重复他们所做的工作,有了前人无所畏惧的工作,随着五年来该领域的新发展,并且获得很多后见之明,你可能最终能做得更好……
作者怎么选取参数 X 的值?
大多数尝试学习神经网络的人,面对选择相关参数的方式,都会面临不可避免的迷思。从隐藏单元数到层数,学习率,优化器,卷积核大小,损失函数等,有数百种选择。
因此,深度学习通常又称为炼丹,许多人说缺乏严谨性,会影响理解和复现。他们说这是一个金钱、计算和工程师主导的领域,只是优化得到一个好看的结果。
但是,如果做出这样的结论,你将面对一个奇怪的局面:一方面,深度学习不断产生令人印象深刻的结果,难道这真的是由一群不明白自己在搞什么的人完成的吗?
可能这些人只是面向评价指标编程?慢慢调整参数,直到得到满意结果,其实不了解每个参数的作用?作为一名研究生,这个答案可能令人欣慰,因为它解释了为什么别人搞得定,自己搞不定。“啊!我的工作搞不定的唯一原因是,其他人都花了很长时间来调整他们的神奇数字!我是唯一关注实际科学的人!”
好吧,其实这些参数有许多都无关紧要。
如果作者没有关注论文中的参数,那么可能是他们不理解这些参数,因此需要更为详细的科学调查;有可能这是针对特定任务的,需要领域知识来设置;更简单地是,有可能它们根本无关紧要。这并不是说你不会把这个数搞错,你可能会设置错。这也并不是说作者没有花时间调这个参数,获得 1% 或 2% 的性能提升。而是说,这些参数设置的确切值,可能并不影响系统的整体功能性。
因此,面对一个你不理解的参数,你通常只有几个选择。要么看看其他人怎么说,做出一个有根据的猜测,然后忘记它就不管了;要么花时间真正了解该参数的作用。
为什么没有源码和数据?
在图形学中,我们很幸运能与行业保持如此紧密的联系。人们确实关注我们的研究,资金支持很充足,研究取得的进展也是显而易见的。但是,这也会使得代码和数据的发布变得几乎不可能。
然而,当涉及到学术界的代码和数据时,人们的口头禅是:无论你的代码多么吓人、不整洁、丢人,有代码总比没有的好。这听起来好像不错,但是你们是否因为发布的科研代码太糟糕,导致其他人被赶出国去了吗?我就有过。
有一次,一位学生曾与我联系,他一直以来使用我的一些科研代码,用来完成他的硕士项目。通过 hack 我的一些代码,他得到了一些早期结果,但是改过后的代码变得难以维护,于是他陷入困局,项目也陷入混乱。显然他无法完成工作,但是他也没有时间从头开始重构,完成项目。在给我的电子邮件中,他感到愤怒、鸭梨山大、困惑和羞愤。尽管我可以回答一些问题,但是对我而言,明显感到他对这些东西的理解很差,要消除他的困局已经超出了电子邮件所能给予的帮助。后来他停止向我发送消息,不久之后,我发现,他在修其他课程也变得很有压力,导致他作出了非常糟糕的决定,即在考试中作弊。他被抓了,被大学开除,签证吊销,最终被赶出国门。
我仍然偶尔会看到我的代码出现在其他学术项目中,并且都是比我发布时的代码状况更糟。各种怪异的 hack,各种 bug 和错误仍然不可避免地出现,没有得到解决,这无疑会让大量可怜的学生望而生畏。毫无疑问,让这些人从头开始写代码可能会更好。
拥有可用代码的关键问题是,它给人一种错觉,“只是做一点小小的实验 X 就很容易了”,而实际上,如果代码很糟糕,你还不如从新写代码更轻松。
不要误会我的意思,代码非常有价值,无论对于重现明确的结果,或者作为精确的细节参考,都非常重要。在几乎所有情形下,发布它都是好主意。但是你们研究生应该小心应对,因为有时候,既有代码可能不利于理解概念,甚至不利于你的实现。除了你自己动手做,别无他法。
为什么其他人的结果这么亮眼?
在评审过程中,大多数图形学会议都是单盲或双盲的,然而,当你看到 Pixar,Disney 或 Dreamworks 的角色时,你可能可以确定这些作者在哪家公司工作。其他小组会在不同出版物中,重用相同的渲染环境和字符。因此,作为审阅者,你永远无法完全确定作者是谁,但是通常不难得到一个有根据的猜测。
在研究生的时候,我一直想知道有多少是故意这样做的。想 Disney Research 这样的组织,在研究方面享有很高的声誉,那么他们怎么不会让这显而易见呢?我记得有一次我很高兴看到,我们论文中使用的角色看起来很卡通:评审者会认为我们的论文是 Disney 的吗?
但是,在研究生期间我没有搞明白的是,使用 Disney 的角色,并不是让 Disney Research 的论文享有良好声誉的原因,出色的 presentation 才是(当然其他知名团体也有类似很好的声誉,我并不是有意挑 Disney Research!)。
好的 presentation 对于研究很重要。对于大多数审稿人而言,对于 presentation 的关注不亚于对于方法论的关注。为什么不呢?如果你的渲染粗糙,有很多视觉上的 artifact,听人困惑的图形,糟糕的可视化,或者糟糕的图表,谁有敢说你在数学上没有犯同样的错误?
也许在一个完美世界中,每个人都仅仅根据他们的贡献进行评估,而不是因为他们在渲染中有柔和的阴影和反射。但是学术研究是发生在现实生活中的过程,论文不仅仅会根据他们的贡献进行评判,而是根据论文所包含的整体元素。事实上人们都希望对图形学的研究感到兴奋,而漂亮的 presentation 是令该领域从事起来很舒适的途径之一——因此不要低估了它。
为什么我的审稿人又懒又不公?
看吧,总是会有一个 Reviewer 2,而关于 Reviewer 2 的秘密是,所有阅读你论文的人,又有一部分人比 Reviewer 2 更***钻、懒惰、愚蠢和不公。人们阅读你的论文,可能会想的没那么好,会有愚蠢的想法,甚至会完全误解它。如果你真的希望每个人都喜欢你的论文,那么照顾到 Reviewer 2 只是这条道路上的第一步。
Reviewer 2 可能在看你的论文之前,已经审阅了另外七篇论文了。在他们的第三杯咖啡上,他们浏览了摘要,开始阅读介绍,然后判断他们并不喜欢这个主题,然后在方法论找到可以拒绝的技术细节。
计算你完成的评论数是一个很好的练习。如果你是评审的接受者,可能很难理解像 Reviewer 2 这样的人,在拒绝论文而不给与公正的评价时,背后的心态。只有当你成为给审阅的人的时候,你才开始了解一个人是怎么变成那样的。
因此,我给那些把 Reviewer 2 当敌人的研究生的建议是:在某些时候,成为你最恨的 Reviewer 2。在撰写论文时,仿佛你的耐心为 0,仿佛缺少引文都会把你逼疯一样。你写的论文,就仿佛是要给那种因为你写论文而愤怒的人看的。要让 Reviewer 2 在审阅中无话可说,留下不满的哼哼声。
为什么其他人懂的那么多?
四年是很长的时间。曼哈顿项目耗时四年。我敢打赌,刚开始,他们对于如何制造原子弹并不十分明白。但是,你知道什么东西会让曼哈顿项目上的工作无法忍受吗?被未来四年的人所包围,他们知道所有关于原子弹的一切,并且使用很多你不理解的单词和术语快速地说话,并且他们忙于自己的项目,也无法给予你什么帮助。
听起来很熟悉吗?攻读博士学位意味着不断被其他非常聪明的人所包围,他们在研究上可能领先你很多年。只需要记住,当攻读博士学位时,没人会感觉自己知道一切。没有人理解所有其他人谈论的单词和术语,每个人都是点头称是,当问题直接的问题的时候才会惊慌失措。
但是同样,所有人都会在某个时间开始明白这些东西,而在不知不觉间,你也会说话快速,术语乱窜,就是若干年前你所讨厌的那种人。所以说吧,给它一点时间,保持动力,努力工作,你将会做的很好。