弗格森模型的代码回顾

2020-05-07 03:20:29

帝国能源最终发布了弗格森代码的派生版本。我想我应该回顾一下,然后把我注意到的一些东西寄给你。我不知道你的背景,所以很抱歉,如果其中的一些投放在错误的水平上。

我的背景。我写软件已经有30年了。2006年至2014年,我在谷歌工作,是一名高级软件工程师,从事地图、Gmail和账户安全方面的工作。在过去的五年里,我一直在一家美国/英国的公司工作,在那里我设计了公司的数据库产品,以及其他工作和项目。我也做了几年的独立顾问。显然,我只是给出我自己的专业观点,而不是代表我现在的雇主发言。

密码。这不是弗格森在制作他著名的报告9时运行的代码。GitHub上发布的是经过微软和其他公司一个多月的团队升级一个多月后,经过大量修改的衍生品。例如,为了便于阅读,这个代码库被分成多个文件,并用C++编写,而原来的程序是“一个已经工作了十年的15000行文件”(这被认为是极其糟糕的实践)。8天前有人提出了索要原始代码的请求,但被忽视了,可能需要某种法律强制才能迫使他们释放它。显然,帝国政府对它的状态太尴尬了,以至于他们永远不会自愿发布它,这是不可接受的,因为它是由纳税人支付的,属于他们自己。

这个模型。它所做的最好的描述是没有图形的模拟城市(SimCity)。它试图模拟家庭、学校、办公室、人和他们的行动等。我不会像在其他地方很好地探索的那样,进一步深入到潜在的假设中。

不确定的输出。由于错误,在相同的输入下,代码可能会产生非常不同的结果。他们例行公事地表现得好像这件事无关紧要。

这个问题使得代码不能用于科学目的,因为科学方法的一个关键部分是能够复制结果。如果没有复制,这些发现可能根本就不是真的,因为心理学领域一直在付出代价才能找到答案。即使他们的原始代码被公布,很明显,与报告9中相同的数字可能也不会出来。

非确定性的输出可能需要一些解释,因为这不是以前任何人都认为可能的事情。

文档说,“这个模型是随机的。应该用不同的种子进行多次奔跑,以观察平均行为。“

随机只是一个科学发音的词,意思是随机。如果随机性是故意的伪随机性,也就是说,随机性是从开始的“种子”导出的,迭代该种子以产生随机数,这不是问题。蒙特卡罗技术中经常使用这种随机性。这是安全的,因为将来可以记录种子并从中产生相同的(伪)随机数。任何玩过“我的世界”的孩子都熟悉伪随机性,因为“我的世界”给了你用来生成随机世界的种子,所以通过分享种子,你可以分享世界。

显然,文档希望我们认为,在给定起始种子的情况下,模型将始终产生相同的结果。

调查揭示了真相-即使对于相同的起始种子和参数,代码也会产生截然不同的结果。

我将用几个错误来说明。在第116期中,爱丁堡大学(Edinburgh University)的一个英国“红色团队”报告称,他们试图使用一种以更高效的格式存储数据表的模式,以加快加载速度,结果令他们惊讶的是,80天后的预测结果相差约8万人:

该模式不会改变正在模拟的世界的任何内容,所以这显然是一个错误。

帝国理工学院团队的回应是,这无关紧要:他们“意识到了一些小的非决定论”,但“由于模型的一般随机性,这在历史上被认为是可以接受的”。注意这里的措辞-帝国理工学院知道他们的代码有这样的错误,但他们的行为就像是宇宙中固有的随机性,而不是业余编码的结果。显然,在流行病学中,死亡人数相差8万人是“一种小小的非决定论”。

Imperial建议爱丁堡,如果你像他们一样在单线程模式下运行,这个问题就解决了,这意味着他们建议只使用一个CPU内核,而不是任何视频游戏都会成功使用的许多内核。对于一个国家的模拟来说,只使用一个CPU核心显然是一个可怕的问题-这离你能得到的超级计算还差得远。尽管如此,Imperial就是这样使用代码的:他们知道,当他们试图更快地运行代码时,代码就会崩溃。从阅读代码可以清楚地看出,2014年帝国理工学院试图让代码使用多个CPU来加速,但从未让它可靠地工作。众所周知,这种编程很困难,通常需要经验丰富的高级工程师才能获得好的结果。运行之间随机更改的结果是线程安全错误或更通俗地说,Heisenbug的常见后果。

但爱丁堡回来后报告说,即使在单线程模式下,他们仍然看到了问题,所以Imperial对这个问题的理解是错误的。最后,Imperial通过引用他们所做的代码更改来修复它,承认存在漏洞。给出的解释是“从历史上看,似乎在这一点上使用了第二对种子,以使运行完全相同,无论网络是如何构建的,但当实施种子重置时,这一点已经改变了”。换句话说,在改变模式的过程中,他们使其不可复制,并且从未注意到。

他们为什么没注意到呢?因为他们的代码充斥着类似的错误,而且他们非常努力地修复这些错误,以至于他们养成了简单地平均多次运行的结果来掩盖…的习惯。最终,这种行为在团队内部变得常态化。

在第30期中,有人报告说,该模型根据其运行在哪种计算机上会产生不同的输出(与CPU数量无关)。同样的解释是,尽管这个新问题“只会增加问题”,…。“这不是完全运行模型的问题,因为它无论如何都是随机的”。

尽管这些帖子的学者不是尼尔·弗格森,但他很清楚代码中充满了会产生随机结果的错误。在更改#107中,他评论道:“它包括对InitModel的修复,以确保确定性运行时启用了假期”。在更改#158中,他仅将更改描述为“许多小更改,其中一些对确定性至关重要”。

帝国理工学院正试图既吃蛋糕又吃蛋糕。他们对随机结果的报道不屑一顾,他们的回应是“这不是问题,只需多次运行并取平均值”,但与此同时,当他们发现这些漏洞时,他们会修复这些漏洞。他们知道他们的代码经不起审查,所以在专业人士有机会修复它之前一直隐藏着它,但十多年来业余爱好编程造成的损害是如此之大,甚至连微软都无法让它正确运行。

没有测试。在讨论修复第一个bug Imperial state时,该位置的代码过去是确定性的,但他们在更改代码时没有注意到它被破坏了。

在处理复杂的软件时,这样的回归很常见,这就是为什么工业软件工程团队编写自动化回归测试的原因。这些程序用不同的输入运行程序,然后检查输出是否符合预期。每个建议的更改都针对每个测试运行,如果任何测试失败,则可能无法进行更改。

帝国代码似乎没有有效的回归测试。他们尝试了,但代码中随机行为的程度让他们失败了。4月4日,他们表示:“然而,我们还没有时间想出一种可扩展和可维护的方式来运行回归测试,这种方式允许少量的变化,但不会让数字随着时间的推移而漂移。”

除了这个特定代码库的明显不可挽回的性质之外,测试模型预测还面临一个基本问题,即作者直到事后很久才知道“正确”答案是什么,而且到那时代码无论如何都已经再次更改,从而更改了其中的错误集。所以现在还不清楚回归测试对于这样的模型到底意味着什么,即使他们有一些有效的模型。

没有记录的方程式。大部分代码由没有指定用途的公式组成。John Carmack(一位传奇的视频游戏程序员)推测,其中一些代码可能是几年前从FORTRAN自动翻译过来的。

例如,在SetupModel.cpp的第510行上,有一个遍历模拟已知的所有“位置”的循环。此代码似乎正在尝试计算“位置”的R0。酒店在此通行证期间被排除在外,没有任何解释。

这段代码突出了Caswell Bligh在您的站点评论中讨论的一个问题:R0不是病毒的真正特征。R0既是这些模型的输入,也是这些模型的输出,并根据不同的环境和情况进行例行调整。将自己的产出作为投入消耗的模型是私营部门众所周知的问题-这可能导致迅速的分歧和错误的预测。Google论文的第2.2节讨论了这个问题,“机器学习:技术债务的高息信用卡”。

持续发展。尽管知道他们的代码中存在“没有时间”修复的严重问题,但帝国理工学院的团队仍在继续添加新功能,例如,该模型试图模拟数字联系人追踪应用程序的影响。

在存在如此多质量问题的代码库中添加新功能只会使它们变得更加复杂,并使它们变得更糟。如果我在我正在咨询的公司中看到这种情况,我会立即建议他们停止新功能开发,直到全面的回归测试到位,代码质量得到改善。

结论:所有基于此规范的论文应立即撤回。帝国理工学院的建模工作应该重新组建一个新的团队,这个团队不在弗格森教授的领导之下,并且承诺从第一天起就用发布的代码来实现可复制的结果。

在个人层面上,我实际上会走得更远,并建议取消对所有流行病学学术的资助。这类工作最好由保险界来做。保险公司聘请建模师和数据科学家,但也聘请管理人员,他们的工作是确定模型是否足够准确,可供现实世界使用,并聘请专业软件工程师,以确保模型软件经过适当测试,可理解等。学术努力没有这些人,结果不言而喻。