除了产生不正确的结果外,科学编程中最担心的问题之一是无法重现您生成的结果。哪些最佳实践有助于确保您的分析具有可重复性?
8 回答
- 在线发布原始原始数据并免费下载。
- 使代码库开源并可在线下载。
- 如果在优化中使用随机化,则重复优化几次,选择结果的最佳值或使用固定的随机种子,以便重复相同的结果。
- 在执行分析之前,您应该将数据拆分为“训练/分析”数据集和“测试/验证”数据集。对“训练”数据集执行分析,并确保您获得的结果仍然保留在“验证”数据集上,以确保您的分析实际上是可推广的,而不是简单地记住相关数据集的特性。
前两点非常重要,因为提供数据集可以让其他人对相同的数据执行自己的分析,从而提高您对自己分析有效性的信心水平。此外,使数据集在线可用 - 特别是如果您使用链接数据格式 - 使得爬虫可以将您的数据集与其他数据集聚合,从而能够使用更大的数据集进行分析......在许多类型的研究中,样本量有时太小以至于无法对结果真正有信心......但是共享您的数据集可以构建非常大的数据集。或者,有人可以使用您的数据集来验证他们对其他数据集执行的分析。
此外,使您的代码开源可以让您的同行审查代码和过程。通常,此类审查会导致发现缺陷或发现额外优化和改进的可能性。最重要的是,它允许其他研究人员改进您的方法,而无需实施您从头开始所做的一切。当研究可以专注于改进而不是重新发明轮子时,它会极大地加快研究步伐。
至于随机化......许多算法依靠随机化来实现其结果。随机和蒙特卡洛方法很常见,虽然它们已被证明在某些情况下收敛,但仍有可能得到不同的结果。确保您获得相同结果的方法是在您的代码中有一个循环调用计算一些固定次数,并选择最佳结果。如果你使用足够多的重复,你可以期望找到全局或接近全局的最优值,而不是陷入局部最优值。另一种可能性是使用预先确定的种子,尽管这不是,恕我直言,这是一种很好的方法,因为您可以选择一个导致您陷入局部最优的种子。此外,不能保证不同平台上的随机数生成器会为该种子值生成相同的结果。
我是一名嵌入地球物理学家研究团队的软件工程师,我们目前(一如既往)致力于提高我们根据需要重现结果的能力。以下是从我们的经验中收集到的一些建议:
- 将所有内容置于版本控制之下:源代码、输入数据集、makefile 等
- 构建可执行文件时:我们将编译器指令嵌入到可执行文件本身中,我们使用 UUID 标记构建日志并使用相同的 UUID 标记可执行文件,计算可执行文件的校验和,自动构建所有内容并自动更新数据库(好吧,这只是一个平面文件真的)与构建细节等
- 我们使用 Subversion 的关键字在每个源代码中包含修订号(等),并将这些写入生成的任何输出文件中。
- 我们进行了大量(半)自动化回归测试,以确保新版本的代码或新的构建变体产生相同(或足够相似)的结果,我正在开发一堆程序来量化所做的更改发生。
- 我的地球物理学家同事确实分析了程序对输入变化的敏感性。我分析了他们(代码,而不是地理)对编译器设置、平台等的敏感性。
我们目前正在开发一个工作流系统,该系统将记录每个作业运行的详细信息:输入数据集(包括版本)、输出数据集、使用的程序(包括版本和变体)、参数等——通常称为出处。一旦启动并运行,发布结果的唯一方法就是使用工作流系统。任何输出数据集都将包含其自身出处的详细信息,尽管我们尚未完成详细设计。
对于将数字结果复制到最低有效数字,我们非常(也许也)很放松。我们工作的基础科学,以及我们基本数据集测量中固有的错误,不支持我们任何超过 2 或 3 sf 的数值结果的有效性
我们当然不会发布代码或数据以供同行评审,我们从事石油行业。
已经有很多好的建议了。我会补充(都来自痛苦的经历——在出版之前,谢天谢地!),
1) 检查结果的稳定性:
- 尝试几个不同的数据子集
- 重新输入输入
- 重新组合输出
- 调整网格间距
- 尝试几个随机种子(如果适用)
如果它不稳定,你还没有完成。
发布上述测试的结果(或至少保留证据并提及您做到了)。
2) 抽查中间结果
是的,您可能会在一个小样本上开发该方法,然后研究整个混乱。在磨削过程中,高峰进入中间几次。更好的是,在可能的情况下收集中间步骤的统计数据并寻找其中的异常迹象。
再一次,任何惊喜,你必须回去再做一次。
并且,再次保留和/或发布此内容。
我喜欢的已经提到的事情包括
- 源代码控制——无论如何你都需要它。
- 构建环境的日志记录。同样的出版很好。
- 计划使代码和数据可用。
另一个没有人提到的:
3) 记录代码
是的,您正在忙着编写它,并且可能正在忙着设计它。但我的意思并不是一份详细的文件,而是对所有意外情况的一个很好的解释。无论如何你都需要把这些写下来,所以把它想象成在纸上抢占先机。而且您可以将文档保存在源代码管理中,以便您可以随意丢弃不再适用的块——如果您需要它们,它们会在那里。
用构建说明和“如何运行”简介构建一个小的 README 不会有什么坏处。如果您要使代码可用,人们会询问这些东西......另外,对我来说,检查它可以帮助我保持正轨。
发布程序代码,使其可供审查。
这绝不是针对您,但这是我的咆哮:
如果您从事纳税人资助的工作,如果您在同行评审期刊上发表结果,请提供源代码,在开源许可下或在公共领域。我厌倦了阅读有人提出的这个伟大的算法,他们声称它确实 x,但没有提供验证/检查源代码的方法。如果我看不到代码,我无法验证你的结果,因为算法实现可能会有非常大的差异。
在我看来,将纳税人支付的工作放在研究人员无法接触到的地方是不道德的。推动论文在可用工作方面没有给公众带来切实的好处是违反科学的。
我认为很多以前的答案都错过了您问题的“科学计算”部分,并回答了适用于任何科学的非常笼统的东西(公开数据和方法,专门用于 CS)。
他们缺少的是你必须更加专业:你必须具体说明你使用了哪个版本的编译器,编译时使用了哪些开关,你使用了哪个版本的操作系统,你使用的所有库的版本链接,您正在使用什么硬件,同时在您的机器上运行什么,等等。那里有已发表的论文,其中每一个因素都以非平凡的方式影响了结果。
例如(在 Intel 硬件上)您可能正在使用使用 FPU 的 80 位浮点数的库,进行 O/S 升级,现在该库现在可能只使用 64 位双精度数,如果您的结果可能会发生巨大变化问题至少是病态的。
编译器升级可能会改变默认的舍入行为,或者单个优化可能会按照 2 条指令完成的顺序翻转,并且对于病态系统,繁荣,不同的结果。
哎呀,有一些关于次优算法在实际测试中显示“最佳”的有趣故事,因为它们是在笔记本电脑上进行的测试,当它过热时会自动减慢 CPU(这是最优算法所做的)。
从源代码或数据中看不到这些东西。
在 Internet 上发布代码、数据和结果。把网址写在纸上。
此外,将您的代码提交给“竞赛”。例如,在音乐信息检索中,有MIREX。
以某种方式记录配置参数(例如,如果您可以将某个变量设置为某个值)。这可能在数据输出中,或在版本控制中。
如果您一直在更改程序(我是!),请确保记录您正在使用的程序版本。
也许这有点偏离主题,但要遵循@Jacques Carette 关于科学计算细节的领先,对于一些特定问题,特别是那些模糊可重复性和正确性之间界限的问题,查阅验证和验证(“V&V”)文献可能会有所帮助。现在,云计算越来越成为大型模拟问题的一种选择,随机 CPU 的随机分类之间的可重复性将更加令人担忧。此外,我不知道是否可以将结果的“正确性”与“再现性”完全分开,因为您的结果源于您的计算模型。即使您的模型似乎适用于计算集群 A 但不适用于集群 B,您需要遵循一些指导方针,以确保您制作此模型的工作过程是合理的。具体到再现性,V&V 社区有一些讨论将再现性误差纳入整体模型不确定性(我将让读者自己调查)。
For example, for computational fluid dynamics (CFD) work, the gold standard is the ASME V&V guide. For the applied multiphysics modeling and simulation people especially (with its general concepts applicable to the greater scientific computing community), this is an important standard to internalize.