机器学习论文复现,这五大问题你需要注意

论文复现一直是机器学习领域的难题,虽然最近多个学术会议提倡大家提交代码,但解决论文复现问题仍然任重而道远。在试图复现机器学习论文时,我们经常遇到哪些问题呢?新加坡机器学习工程师 Derek Chia 对此进行了总结。

我最初接触机器学习时,花费了大量时间来阅读论文,并尝试实现。当然,我不是天才。实现它意味着要执行 git clone 并尝试运行论文作者的代码。对于我感兴趣的概念,我可能还手动输入一些代码并进行注释,以便更好地理解论文和项目。

这样的学习方法令人沮丧。尝试复现论文的流程大致如下:
  • 一些达到新 SOTA 的论文在新闻媒体中引起关注;

  • 读者深入研究或快速浏览论文内容;

  • 读者对论文中的实验结果印象深刻,并产生复现的兴趣。

接下来就是疯狂搜索项目代码,并尝试在作者所用的数据集上运行代码。这时,你需要祈祷该项目具备以下要素:运行说明(README.md)、代码、参数、数据集、数据集路径、软件环境、所需依赖项以及硬件条件。了解这些,才能顺利复现论文中的 SOTA 结果。

而在这个过程中,你可能会遇到很多常见问题(参见下文)。遇到问题之前先了解它们是很有帮助的,毕竟,没人喜欢空手而归。

复现机器学习论文时的常见问题

复现过程中的常见问题如下所示:
  • README 文件不完整或缺失;

  • 未定义依赖项、代码存在 bug、缺少预训练模型;

  • 未公开参数;

  • 私有数据集或缺少预处理步骤;

  • 对 GPU 资源的需求不切实际。

README 文件不完整或缺失

如果一篇论文在发表时开源了代码,那么 README 就是你着手开始复现项目的文档之一。好的 README 文件通常具备以下几个组成部分:依赖项列表、训练脚本、评估脚本、预训练模型以及运行脚本得到的结果。

实际上,这些内容已经在 Papers with Code 发布的《机器学习代码完整性自查清单》中列出(该清单已成为 NeurIPS 2020 代码提交流程的一部分)。该清单受到麦吉尔大学副教授、Facebook 蒙特利尔 FAIR 实验室负责人 Joelle Pineau 的启发。

Papers with Code 提供的 README 样例参见:https://github.com/paperswithcode/releasing-research-code

不完整的 README 文件对运行代码而言是一个坏的开端。

一个需要注意的信号是示例 notebook 或示例代码。notebook 的用途是演示代码的使用。理想情况下,除了点击「Run all」以外,不需要任何其他调整就能够运行 notebook。预填充参数和数据路径的命令行也能够实现同样的效果。

还有一些次要但有用的信息,比如作者的联系方式或展示模型架构或数据转换流程的 gif 图片等,这些都是完备的 README 文件应该包含的。如果代码库托管在 GitHub 上,请检查 Issue 区域的问题是否得到了积极回复,以及 pull request 是否定期被查看。这些事项均能证明库得到精心维护,确保后续复现工作得到有效支持。当然会有例外,但请慎重考虑以上各项出现缺失的情况。
Joelle Pineau 发布的机器学习可复现性检查清单(图源:https://www.cs.mcgill.ca/~jpineau/ReproducibilityChecklist.pdf

未定义依赖项、代码存在 bug、缺少预训练模型

当你对示例 notebook 觉得满意后,你或许想尝试用不同的参数在自己的数据集上试用模型。在这一阶段,你或许会调用示例 notebook 中未用到的函数,或者在自己的数据集上尝试预训练模型,这时可能会遇到问题。

例如,你可能注意到 requirements.txt 缺失,或者软件包版本未固定(如 tensorflow==2.2)想象一下当你发现 TensorFlow 版本是 1.15 而不是 2.2,原因只是作者没有指定版本时的爆炸心态吧。

假设你检查过了依赖项,然而现在却发现预训练模型失踪了!这种情况下,你要么 debug 代码,要么提交 bug 报告,要么忽略代码。请谨慎选择第一个选项,因为你可能会在这上面花费好几个小时。当然有的 bug 很容易解决,如果我能修复的话,我会提交 pull request。但并不是每次都那么好运,这些随手可及的果子有时候很难摘。

预训练模型缺失是一个危险信号,但这其实并不罕见。毕竟,论文作者没有义务发布模型。那么,另一个替代方法是使用公开的参数训练模型进行复现。不过参数也不总是公开……

未公开参数

根据模型情况来看,超参数对于实现 SOTA 结果是非常重要的。下图展示了不同参数产生不同的 f1 分数(范围从 0.5 到 1.0)。模型中的参数通常是学习率(learning rate)、嵌入尺寸(embedding size)、层数、dropout 量、批处理大小、训练 epoch 数量等。

因此,如果作者没有提供他们使用的确切参数,你可能必须自己进行所有实验才能复现 SOTA 结果。
顺便说一句,Facebook 的 HiPlot 是一个很好的工具,帮助你在使用不同参数组合时将模型结果可视化。

HiPlot 地址:https://github.com/facebookresearch/hiplot

私有数据集或缺少预处理步骤

从很多方面来说,我们很幸运地拥有世界各地研究者提供的开源数据集。事实就是如此,数据的收集绝非易事,而清理这些数据并将其格式化以供研究使用,就更加麻烦一些。在此需感谢学术机构和 Kaggle 免费托管这些开源数据集,因为带宽和存储成本是很高的。

然而想使用私有数据集,并非易事。数据集可能包含受版权保护的信息,比如 ImageNet。通常你需要填写一份申请表,版权所有者将自行决定是否批准。

某些时候这个过程会很麻烦,如果你所需的数据集不可用,在申请行动之前要先认真考虑一下。或者你可以从其他渠道搜索或者下载数据,比如 Academic Torrents:https://academictorrents.com/。

对 GPU 资源的需求不切实际

近期出现了一股趋势:模型越大性能越好。一些论文使用了整个数据中心的算力才达到 SOTA 结果,这些论文复现起来当然很难。例如,2019 年 10 月谷歌发表论文《Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer》,尝试通过将参数扩展到 110 亿来探索 Transformer 模型架构的局限性。然而几个月后微软用 170 亿参数创建了 Turning-NLG,不久 OpenAI 放出 1750 亿参数的预训练语言模型 GPT-3……

要想训练数十亿参数的模型,你需要使用分布式训练方法以及某种形式的高性能计算(HPC)或 GPU 集群。具备 110 亿和 170 亿参数的模型分别需要约 44GB 和 68GB 的内存,因此这些模型无法仅使用一块 GPU 完成训练。

简而言之,尽早发现论文所用大模型是否超出你的个人能力。
微软训练 Turning-NLG。

总结

复现论文代码并非易事,不过越来越多的项目尝试标准化 SOTA 模型。我个人最喜欢的是 HuggingFace 的 Transformers,它为研究者和开发者提供了足够低的进入门槛。另外,TensorFlow 的 Model Garden 和 PyTorch 的 Model Zoo 也发展迅速(其中分别是 TensorFlow 和 PyTorch 团队构建的预训练模型)。

这些库旨在标准化预训练模型的使用,并为模型贡献和分发提供合适的条件。它们对代码质量提供了保障,并且具备不错的文档。我希望社区能从这些库中获益,并帮助复现 SOTA 结果,轻松地使用 SOTA 模型。

参考文献
  • Why Can’t I Reproduce Their Results (http://theorangeduck.com/page/reproduce-their-results)

  • Rules of Machine Learning: Best Practices for ML Engineering (https://developers.google.com/machine-learning/guides/rules-of-ml)

  • Curated list of awesome READMEs (https://github.com/matiassingers/awesome-readme)

  • How the AI community can get serious about reproducibility (https://ai.facebook.com/blog/how-the-ai-community-can-get-serious-about-reproducibility/)

  • ML Code Completeness Checklist (https://medium.com/paperswithcode/ml-code-completeness-checklist-e9127b168501)

  • Designing the Reproducibility Program for NeurIPS 2020 (https://medium.com/@NeurIPSConf/designing-the-reproducibility-program-for-neurips-2020-7fcccaa5c6ad)

  • Tips for Publishing Research Code (https://github.com/paperswithcode/releasing-research-code)