最近,在发布了Falcon 🦅并将其添加到Open LLM Leaderboard之后,Twitter上引起了一场有趣的讨论,Open LLM Leaderboard是一个比较开放访问的大型语言模型的公共排行榜。
讨论的焦点是排行榜上显示的四个评估之一:用于测量大规模多任务语言理解的基准测试(简称MMLU)。
社区对于排行榜上当前顶尖模型LLaMA的MMLU评估数据与LLaMa论文中的数据明显相差很大感到惊讶。
因此,我们决定深入研究并弄清楚发生了什么以及如何修复🕳🐇。
在我们的探索过程中,我们与LLaMA评估合作的伟大的@javier-m以及Falcon团队的了不起的@slippylolo进行了讨论。话虽如此,下面的所有错误都应归因于我们而不是他们!
在这段与我们共同的旅程中,您将学到很多关于如何在单个评估中评估模型以及是否相信您在网上和论文中看到的数字的方法。
准备好了吗?系好安全带,我们要起飞了🚀。
什么是Open LLM Leaderboard?
首先,注意Open LLM Leaderboard实际上只是一个包装器,运行了Eleuther AI LM Evaluation Harness这个开源基准测试库,该库由EleutherAI非盈利人工智能研究实验室创建,该实验室以创建The Pile、训练GPT-J、GPT-Neo-X 20B和Pythia而闻名。这个团队在人工智能领域有着严肃的资质!
这个包装器在Hugging Face计算集群的空闲周期中使用Eleuther AI harness运行评估,并将结果存储在数据集中,然后在在线排行榜空间上显示。
对于LLaMA模型,使用Eleuther AI LM Evaluation Harness获得的MMLU数值与LLaMa论文中报告的MMLU数值存在显著差异。
为什么会出现这种情况?
MMLU的千变万化
事实证明,LLaMA团队采用了另一个在线可用的代码实现:由开发MMLU基准测试的UC Berkeley团队提供的评估代码,该代码可在https://github.com/hendrycks/test找到,我们在这里称之为”原始实现”。
在进一步研究中,我们发现了另一个有趣的用于对完全相同的MMLU数据集进行评估的实现:Stanford的CRFM提供的评估代码,该代码是非常全面的语言模型综合评估基准,我们在这里称之为”HELM实现”。
EleutherAI Harness和Stanford HELM基准测试都很有趣,因为它们在单个代码库中汇集了许多评估(包括MMLU),因此可以很好地展示模型的性能。这就是为什么Open LLM Leaderboard使用这种”整体”基准测试而不是为每个评估使用单独的代码库的原因。
为了解决这个问题,我们决定在一组模型上运行这三种可能的MMLU评估的实现,以根据这些结果对它们进行排序:
- Harness实现(提交e47e01b)
- HELM实现(提交cab5d89)
- 原始实现(由令人惊叹的@olmer在https://github.com/hendrycks/test/pull/13上与Hugging Face集成)
(请注意,Harness实现最近已进行了更新-关于此的更多信息请参见我们帖子的结尾)
结果令人惊讶:
您可以在帖子末尾找到完整的评估数值。
这些不同的实现给出了截然不同的基准测试结果,甚至改变了排行榜上模型的排序!
让我们试着了解这种差异的原因🕵️但首先,让我们简要了解如何在现代LLM世界中自动评估模型的行为。
在今天的LLM世界中如何自动评估模型
MMLU是一个多项选择题测试,所以与开放式问题相比,它是一个相当简单的基准测试,但正如我们将看到的,这仍然为实现细节和差异留下了很大的空间。该基准测试由包含四个可能答案的问题组成,涵盖了57个通识知识领域,分为粗粒度的类别: “人文科学”, “社会科学”, “STEM”等。
对于每个问题,只有一个提供的答案是正确的。以下是一个示例:
问题:葡萄糖是如何进入肌肉细胞的:
选项:
A. 通过称为GLUT4的蛋白质转运体。
B. 只有在胰岛素存在的情况下。
C. 通过己糖激酶。
D. 通过单碳酸转运体。
正确答案:A
注意:您可以在平台上的数据集查看器中非常容易地探索更多关于该数据集的内容。
大型语言模型是AI模型库中的简单模型。它们将一串文本作为输入(称为“提示”),将其切成标记(单词、子词或字符,取决于模型的构建方式)并输入模型。从此输入中,它们生成了下一个标记的概率分布,覆盖了它们所知道的所有标记(模型的“词汇表”):因此,您可以了解任何标记作为输入提示的延续有多“可能”。
我们可以利用这些概率来选择一个标记,例如最有可能的标记(或者我们可以通过抽样引入一些轻微的噪音,以避免出现“过于机械”的答案)。将我们选择的标记添加到提示中并将其馈送回模型,以生成另一个标记,以此类推,直到形成整个句子作为输入提示的延续:
这就是ChatGPT或Hugging Chat生成答案的方式。
总之,我们有两种主要方法来从模型中获取信息以进行评估:
- 获取某些特定标记组作为提示的延续的概率,并将这些概率进行比较,以获得我们预定义的可能选择;
- 从模型中获取文本生成(通过重复选择标记,如我们所见),并将这些文本生成与各种预定义的可能选择的文本进行比较。
掌握了这些知识,让我们深入研究MMLU的三种实现,以了解发送给模型的输入是什么,期望的输出是什么,以及如何比较这些输出。
MMLU有各种形状和尺寸:查看提示
让我们比较每个实现为相同的MMLU数据集示例发送给模型的提示示例:
它们之间的差异可能很小,你都注意到了吗?这里是:
- 第一句话,指令和主题:很少有差异。HELM添加了一个额外的空格,而Eleuther LM Harness不包括主题行
- 问题:HELM和LM Harness在问题前加了一个“问题:”前缀
- 选项:Eleuther LM Harness在它们之前添加了关键字“选项”
那么我们如何从这些提示中评估模型呢?
让我们从原始MMLU实现如何提取模型的预测开始。在原始实现中,我们仅比较模型对四个答案的预测概率:
在某些情况下,这对模型可能是有益的,例如,就像您在这里看到的:
在这种情况下,模型对将正确答案排在4个选项中的最高位置得到了+1的分数。但是,如果我们看一下完整的词汇表,它可能生成的是我们四个选项之外的一个词:“Zygote”(这更多是一个例子而不是一个真实的用例🙂)
我们如何确保模型尽可能少地出现这些类型的错误?
我们可以采用“少样本”方法,即在提示中提供一个或多个示例,以及预期的答案。具体如下:
在这种情况下,模型有一个预期行为的示例,因此不太可能预测超出预期答案范围之外的答案。
由于这种方法可以提高性能,我们在所有评估中通常使用5个示例(在每个提示前添加5个示例)对MMLU进行评估:原始实现、EleutherAI LM Harness和HELM。(注意:尽管使用相同的5个示例,但它们被引入模型的顺序可能会有所不同,这也是可能的差异来源,我们在这里不进行调查。您还必须注意避免在少样本示例中泄露一些答案…)
HELM:现在让我们转向HELM的实现。虽然少样本提示通常相似,但模型的评估方式与我们刚刚看到的原始实现有很大不同:我们使用模型的下一个标记输出概率来选择文本生成,并将其与预期答案的文本进行比较,如下所示:
在这种情况下,如果我们的“Zygote”标记代替了最高概率的标记(如上所示),那么模型的答案(“Zygote”)将是错误的,并且模型将不会为此问题得分:
Harness:现在我们终于转向EleutherAI Harness实现,截至2023年1月,它用于计算排行榜的第一组数据。正如我们将看到的,我们在完全相同的评估数据集上计算模型得分的方式又有所不同(请注意,此实现最近已更新-稍后会有更多介绍)。
在这种情况下,我们再次使用概率,但这次是完整答案序列的概率,其中包括字母和答案的文本,例如“C. 第二咽弓”。为了计算完整答案的概率,我们获取每个标记的概率(就像我们上面看到的那样),并将它们收集起来。为了数值稳定性,我们通过将概率的对数求和来收集它们,并且我们可以决定(或不决定)进行归一化,通过将总和除以标记数来避免给较长答案过多的优势(稍后会有更多介绍)。具体如下:
以下是提供和生成的答案的表格总结,以总结我们到目前为止所看到的内容:
我们已经涵盖了所有内容!
现在让我们比较模型在这三种可能的评估方式上的得分:
我们可以看到,对于相同的数据集,无论是绝对得分还是模型排名(请参见第一个图),都非常敏感于我们选择的评估方法。
假设你自己训练了一个完美的LLaMA 65B模型的复制品,并使用Harness进行评估(得分为0.488,如上所示)。现在你将它与发布的数字进行比较(在原始的MMLU实现中评估,得分为0.637)。由于得分相差30%,你可能会认为:“哦天啊,我训练得彻底失败了😱”。但事实并非如此,这只是一些数字,在很大程度上不可比较,即使它们都标记为“MMLU得分”(并在完全相同的MMLU数据集上评估)。
那么,在我们所看到的所有方法中,有没有“最佳评估方式”?这是一个棘手的问题。不同的模型在不同的评估方式下可能表现不同,就像我们在上面看到的排名变化一样。为了尽可能公平,我们可能会倾向于选择一个实现,其中对于所有测试模型的平均得分最高,以便从模型中“解锁”尽可能多的功能。在我们的情况下,这意味着使用原始实现的对数似然选项。但正如我们上面所看到的,使用对数似然在某种程度上也以某种方式向模型提供了一些指示,通过限制可能答案的范围,从而可能过度帮助那些能力较弱的模型。此外,对于开源模型来说,对数似然易于访问,但对于闭源API模型来说并不总是公开的。
而你,读者,你怎么想?这篇博客文章已经很长了,所以是时候开展讨论并邀请你的评论了。请通过以下Open LLM排行榜的讨论主题来讨论这个话题: https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard/discussions/82
结论
从我们的旅程中得出的一个重要教训是,评估与其实现密切相关,甚至关乎微小的细节,如提示和分词。仅仅指示“MMLU结果”并不能让你对如何将这些数字与在另一个库上评估的其他结果进行比较提供太多信息。
这就是为什么开放、标准化和可复现的基准测试如EleutherAI Eval Harness或Stanford HELM对社区来说是无价之宝。没有它们,跨模型和论文比较结果将是不可能的,阻碍了改进LLM的研究。
附言: 在Open LLM排行榜的情况下,我们决定继续使用社区维护的评估库。值得庆幸的是,在撰写本博客文章期间,围绕EleutherAI Harness的令人惊叹的社区,特别是ollmer,在Harness中更新了对MMLU的评估,使其与原始实现类似并匹配这些数字。
我们目前正在使用EleutherAI Eval Harness的更新版本更新完整的排行榜,所以在接下来的几周内可以看到来自Eleuther Harness v2的评分!(重新运行所有模型需要一些时间,请保持关注:hugs:)
致谢:
我们非常感谢LLaMA团队的Xavier Martinet、Aurélien Rodriguez和Sharan Narang在本博客文章中提供的有益建议,并回答了我们的所有问题。
可复现性哈希值:
以下是本博客文章中使用的各种代码实现的提交哈希值。
- EleutherAI LM harness实现提交哈希值e47e01b: https://github.com/EleutherAI/lm-evaluation-harness/tree/e47e01beea79cfe87421e2dac49e64d499c240b4
- HELM实现提交哈希值cab5d89: https://github.com/stanford-crfm/helm/tree/cab5d89fadbff86190f29ddfa497301958eaf2ec
- 原始MMLU实现(由令人惊叹的@olmer完成Hugging Face集成): https://github.com/hendrycks/test/pull/13