开源LLM排行榜出了什么问题?
最近,在发布了Falcon 🦅 并将其添加到开源LLM排行榜(一个比较开源大型语言模型的公共排行榜)之后,Twitter上出现了一场有趣的讨论。
讨论围绕排行榜上显示的四项评估之一展开:一项用于衡量大规模多任务语言理解(简称:MMLU)的基准。
社区惊讶地发现,排行榜上当前排名最高的模型——LLaMA模型 🦙 的MMLU评估结果远低于已发布的LLaMa论文中的数据。
因此,我们决定深入研究这个问题,以了解发生了什么以及如何解决它 🕳🐇
在我们的探索中,我们与在LLaMA评估中合作的优秀@javier-m以及Falcon团队出色的@slippylolo进行了讨论。话虽如此,下面所有的错误当然都应该归咎于我们,而不是他们!
在这次旅程中,您将学到很多关于如何在一个评估上评估模型,以及是否应该相信您在网上和论文中看到的数据。
准备好了吗?系好安全带,我们起飞了 🚀。
开源LLM排行榜是什么?
首先,请注意开源LLM排行榜实际上只是一个运行开源基准测试库Eleuther AI LM Evaluation Harness的包装器。这个库是由EleutherAI非营利AI研究实验室创建的,该实验室以创建The Pile并训练GPT-J、GPT-Neo-X 20B和Pythia而闻名。这是一个在AI领域拥有强大实力的团队!
这个包装器利用Hugging Face计算集群的空闲周期运行Eleuther AI harness的评估,并将结果存储在hub上的数据集中,然后显示在在线排行榜空间上。
对于LLaMA模型,使用Eleuther AI LM Evaluation Harness获得的MMLU数字与LLaMa论文中报告的MMLU数字显著不同。
为什么会出现这种情况?
1001种MMLU风味
事实证明,LLaMA团队采用了另一种在线代码实现:由开发MMLU基准的原始加州大学伯克利分校团队提出的评估代码,可在https://github.com/hendrycks/test获取,我们在这里称之为“原始实现”。
深入研究后,我们发现了另一个有趣的实现在同一个MMLU数据集上进行评估:斯坦福大学CRFM非常全面的评估基准语言模型整体评估中提供的评估代码,我们在这里称之为HELM实现。
EleutherAI Harness 和 Stanford HELM 基准都很有趣,因为它们将许多评估(包括 MMLU)收集在一个代码库中,从而全面了解模型的性能。这就是 Open LLM Leaderboard 包装这些“整体”基准而不是为每个评估使用单独代码库的原因。
为了解决这个问题,我们决定在一些模型上运行这三种可能的MMLU评估实现,并根据这些结果对它们进行排名。
- Harness实现(commit e47e01b)
- HELM实现(commit cab5d89)
- 原始实现(由出色的@olmer在https://github.com/hendrycks/test/pull/13处集成了Hugging Face)
(请注意,Harness 实现最近已更新 - 更多内容请参阅我们文章的末尾)
结果令人惊讶
您可以在文章末尾找到完整的评估数据。
同一基准的这些不同实现给出了截然不同的数字,甚至改变了排行榜上模型的排名顺序!
让我们试着找出这种差异的来源🕵️但首先,让我们简要了解一下我们如何在现代LLM中自动评估行为。
在当今LLM世界中我们如何自动评估模型
MMLU 是一个多项选择题测试,因此是一个相对简单的基准(相对于开放式问题),但正如我们将看到的,这仍然为实现细节和差异留下了很大的空间。该基准由包含四个可能答案的问题组成,涵盖 57 个常识领域,这些领域被分为粗粒度类别:“人文学科”、“社会科学”、“STEM”等。
每个问题只有一个正确答案。以下是一个示例
Question: Glucose is transported into the muscle cell:
Choices:
A. via protein transporters called GLUT4.
B. only in the presence of insulin.
C. via hexokinase.
D. via monocarbylic acid transporters.
Correct answer: A
注意:您可以在hub上的数据集查看器中非常轻松地探索更多此数据集。
大型语言模型在AI模型库中是简单的模型。它们将一段**文本字符串**作为输入(称为“提示”),该文本被切分成标记(单词、子词或字符,取决于模型的构建方式)并馈送给模型。模型根据此输入,为其已知的所有标记(称为模型的“词汇表”)生成下一个标记的概率分布:因此,您可以获得任何标记作为输入提示延续的“可能性”。
我们可以使用这些概率来选择一个标记,例如最有可能的标记(或者我们可以通过采样引入一些微小的噪声,以避免出现“过于机械”的答案)。将我们选择的标记添加到提示中并将其反馈给模型,可以生成另一个标记,依此类推,直到生成完整的句子作为输入提示的延续。
这就是 ChatGPT 或 Hugging Chat 生成答案的方式。
总而言之,我们有两种主要方式从模型中获取信息以对其进行评估:
- 获取某些特定词元组作为提示延续的概率——并比较这些概率以确定我们预定义的可能选择;
- 从模型中获取文本生成(通过我们已经看到的方式重复选择词元)——并将这些文本生成与各种预定义可能选项的文本进行比较。
有了这些知识,我们深入研究了MMLU的三个实现,以找出发送给模型的输入是什么,期望的输出是什么,以及如何比较这些输出。
MMLU各种形态:查看提示
让我们比较一下每个基准针对同一 MMLU 数据集示例发送给模型的提示示例
原始实现Ollmer PR | HELM commit cab5d89 | AI Harness commit e47e01b |
以下是关于美国外交政策的多项选择题(附答案)。 2008年金融危机如何影响了美国的国际声誉? A. 损害了对美国政治经济和资本主义模式的支持 B. 引起了对美国夸大危机的愤怒 C. 增加了对奥巴马总统领导下美国全球领导力的支持 D. 减少了美元在全球范围内的使用 回答 |
以下是关于美国外交政策的多项选择题(附答案)。 问题:2008年金融危机如何影响了美国的国际声誉? A. 损害了对美国政治经济和资本主义模式的支持 B. 引起了对美国夸大危机的愤怒 C. 增加了对奥巴马总统领导下美国全球领导力的支持 D. 减少了美元在全球范围内的使用 回答 |
问题:2008年金融危机如何影响了美国的国际声誉? 选择 A. 损害了对美国政治经济和资本主义模式的支持 B. 引起了对美国夸大危机的愤怒 C. 增加了对奥巴马总统领导下美国全球领导力的支持 D. 减少了美元在全球范围内的使用 回答 |
它们之间的差异可能很小,你都发现了吗?它们是:
- 第一句话、指令和主题:差异很小。HELM额外添加了一个空格,而Eleuther LM Harness没有包含主题行。
- 问题:HELM和LM Harness添加了“问题:”前缀。
- 选项:Eleuther LM Harness 在选项前加上了关键词“Choices”
现在我们如何从这些提示中评估模型?
让我们从原始MMLU实现如何提取模型预测开始。在原始实现中,我们仅比较模型对四个答案的预测概率。
这在某些情况下对模型有利,例如,您可以在这里看到:
在这种情况下,模型将正确答案排在4个选项中的最高位,获得了+1分。但是,如果我们查看完整的词汇表,它反而会生成一个不在我们四个选项范围内的词:“Zygote”(这更多是一个例子而非实际用例 🙂)。
我们如何才能确保模型尽可能少地犯这类错误?
我们可以使用“少量样本”方法,即我们在提示中提供一个或多个示例,以及它们的预期答案。示例如下:
在这里,模型有一个预期行为的例子,因此不太可能预测超出预期答案范围的答案。
由于这能提高性能,因此在所有评估中(包括原始实现、EleutherAI LM Harness 和 HELM),MMLU 通常以 5 次少样本(在每个提示前加上 5 个示例)进行评估。(注意:在不同的基准测试中,虽然使用相同的 5 个示例,但它们引入模型的顺序可能不同,这也是一个可能的差异来源,我们在此不作深入探讨。您也显然必须注意避免在少样本示例中泄露某些答案……)
HELM:现在我们来看看HELM 实现。虽然少数样本提示通常相似,但模型评估的方式与我们刚才看到的原始实现截然不同:我们使用模型输出的下一个词元概率来选择文本生成,并将其与此处显示的预期答案文本进行比较。
在这种情况下,如果我们的“受精卵”标记具有最高概率(如我们上面所见),则模型答案(“受精卵”)将是错误的,模型在该问题上将不得分。
Harness:现在我们最终转向——截至2023年1月的EleutherAI Harness实现,该实现用于计算排行榜的第一个数据。正如我们将看到的,我们在这里又获得了一种在同一个评估数据集上计算模型得分的方式(请注意,此实现最近已更新——更多内容请见文章末尾)。
在这种情况下,我们再次使用概率,但这次是完整答案序列的概率,包括字母和答案文本,例如“C. 第二咽弓”。为了计算完整答案的概率,我们获取每个词元的概率(如上所述)并将其收集起来。为了数值稳定性,我们通过对概率的对数求和来收集它们,并且我们可以决定是否计算一个归一化,其中我们将总和除以词元数量,以避免对较长答案给予太多优势(稍后会详细介绍)。示例如下:
以下是模型提供和生成的答案的汇总表,总结了我们目前所看到的内容:
原始实现 | HELM | AI Harness(截至2023年1月) |
我们比较以下字母答案的概率 | 模型预期生成以下字母答案文本 | 我们比较以下完整答案的概率 |
A B C D |
A | A. 损害了对美国政治经济和资本主义模式的支持 B. 引起了对美国夸大危机的愤怒 C. 增加了对奥巴马总统领导下美国全球领导力的支持 D. 减少了美元在全球范围内的使用 |
我们已经涵盖了所有!
现在让我们比较一下模型在这三种可能的评估方式上的得分
MMLU(HELM) | MMLU(Harness) | MMLU(原始) | |
---|---|---|---|
llama-65b | 0.637 | 0.488 | 0.636 |
tiiuae/falcon-40b | 0.571 | 0.527 | 0.558 |
llama-30b | 0.583 | 0.457 | 0.584 |
EleutherAI/gpt-neox-20b | 0.256 | 0.333 | 0.262 |
llama-13b | 0.471 | 0.377 | 0.47 |
llama-7b | 0.339 | 0.342 | 0.351 |
tiiuae/falcon-7b | 0.278 | 0.35 | 0.254 |
togethercomputer/RedPajama-INCITE-7B-Base | 0.275 | 0.34 | 0.269 |
我们可以看到,对于同一数据集,绝对分数和模型排名(参见第一个图)都对我们决定使用的评估方法非常敏感。
假设您已经完美复刻了LLaMA 65B模型并使用Harness对其进行了评估(得分0.488,见上文)。现在您将其与已发布的数据(在原始MMLU实现上评估,得分0.637)进行比较。分数相差30%,您可能会想:“天哪,我的训练彻底搞砸了😱”。但事实远非如此,这些数字根本不可比较,即使它们都被标记为“MMLU分数”(并且在同一个MMLU数据集上进行评估)。
那么,在我们所见的所有评估方法中,是否存在一种“最佳方式”来评估模型呢?这是一个棘手的问题。正如我们上面看到的排名变化所示,不同的模型在不同的评估方式下表现可能不同。为了尽可能公平,人们可能会倾向于选择一种所有测试模型的平均得分最高的实现,这样我们就可以“解锁”模型尽可能多的能力。在我们的案例中,这意味着使用原始实现的对数似然选项。但正如我们上面所看到的,使用对数似然在某种程度上也通过限制可能答案的范围向模型提供了指示,因此可能对较弱的模型帮助过大。此外,对数似然对于开源模型来说很容易访问,但对于闭源API模型来说并不总是公开的。
那么,读者您怎么看?这篇博文已经很长了,是时候展开讨论并邀请您的评论了。请在开源LLM排行榜的以下讨论串中讨论此话题:https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard/discussions/82
结论
我们旅程的一个关键收获是,评估与其实现密切相关——甚至细致到提示和分词等细节。仅仅一句“MMLU结果”几乎不能提供任何信息,让您将其与在另一个库中评估的数字进行比较。
这就是为什么像EleutherAI Eval Harness或Stanford HELM这样的开放、标准化和可复现的基准对社区来说是无价之宝。没有它们,模型和论文之间的结果比较将是不可能的,这将阻碍LLM改进的研究。
后记:在开源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