任务级LLM评估:有效方法vs常见误区
教开发者如何科学评估LLM在具体业务上的表现,规避评估陷阱
教开发者如何科学评估LLM在具体业务上的表现,规避评估陷阱
如果你用过现成的评估工具来评测自己的任务,你可能会发现大多数都不好用。它们与特定应用的性能几乎没有关联,也不够可靠,无法在生产环境中使用。结果是,我们可能会花费数周的时间,却仍然没有得到能够可靠衡量任务性能的评估。
为了节省时间,我分享一些我发现有用的评估方法。目标是少花时间纠结评估本身,多花时间向用户交付产品。我们将专注于简单、常见的任务,比如分类/提取、摘要总结和翻译。(尽管分类评估看起来很基础,但深入理解能帮助我们解决元问题——如何评估评估本身。)我们还会讨论如何衡量版权内容重述和有害性。
分类:召回率、精确率、ROC-AUC、PR-AUC、分布分离
摘要:通过 NLI 的一致性、通过奖励模型的相关性、长度检查
翻译:通过 chrF、BLEURT、COMET、COMETKiwi 的质量衡量
版权:精确复述、近似复述
有害性:常规和有害提示上产生有害内容的比例
最后,我们会讨论人工评估的作用,以及如何校准评估标准以平衡潜在收益和风险,并缓解创新者困境。
注:我试图让这篇文章对没有数据科学或机器学习背景的人也能理解。因此,它从分类评估指标的基础开始。如果你已经熟悉某些部分,可以跳过。
顺便说一下,如果你想更多地了解评估,我的朋友 Hamel 和 Shreya 正在七月举办最后一期"面向工程师和产品经理的 AI 评估"课程。这里有 35% 的折扣码。
分类是将预定义的标签分配给文本的任务,比如情感(正面、负面)或主题(体育、政治)。提取类似,其中我们识别文本中的特定信息片段,比如名称、日期或位置。这是一个例子:
# 文本输入
"Alice loves her iPhone 13 mini that she bought on September 16, 2022."
# 分类和提取输出
{
"sentiment": "positive", # 情感分类
"topic": "electronics", # 主题分类
"toxicity_prob": "0.1", # 有害性分类
"names": [ # 名称提取
"Alice",
"iPhone 13 mini"
],
"dates": [ # 日期提取
"September 16, 2022"
]
}
虽然这些任务相对简单,LLM 可能在它们上表现良好,但我们仍然需要扎实的评估。例如,Voiceflow 用于意图分类的评估框架帮助他们发现了从已弃用的 gpt-3.5-turbo-0301 升级到更新的 gpt-3.5-turbo-1106 时性能下降了 10%。
我们可以通过提供文档并提示 LLM 预测情感或主题,或检查是否存在辱骂内容或垃圾邮件,来应用 LLM 进行分类。预期输出可以是分类标签("positive")或标签的概率("0.1")。类似地,LLM 可以通过提示它返回带有所需属性(如"names"和"dates")的 JSON,从文档中提取信息。
对于分类输出,我们可以计算总体统计量,比如召回率、精确率、假正例/假负例。这也适用于提取:提取了多少比例的真实属性(召回率)?提取的属性中有多少比例是正确的(精确率)?Wikipedia 页面是一个很好的参考。简而言之:
召回率:被正确识别的真正例所占的比例。如果我们的数据中有 100 个正例,模型识别了 80 个,则召回率 = 0.8
精确率:模型的正预测中正确的比例。如果模型预测正例 50 次,但其中只有 30 个真正正确,则精确率 = 0.6
假正例:模型预测正例但实际负例
假负例:模型预测负例但实际正例
在我看来,准确率作为指标太粗糙,用处不大。我们至少需要将其分离为召回率和精确率,理想情况下跨越多个阈值。
当我们的模型能输出概率而不仅仅是分类标签时(例如,语言分类器、奖励模型),事情变得有趣。现在我们可以使用 ROC-AUC 和 PR-AUC 等指标在不同的概率阈值上评估性能。
接收者操作特征(ROC)曲线在各个阈值处绘制真正例率与假正例率,可视化分类模型在所有分类阈值上的性能。ROC 曲线下的面积(ROC-AUC)是一个总体性能指标,范围从 0.0 到 1.0。比随机猜测好不了多少的模型会有 ROC-AUC = 0.5,而总是正确的模型有 ROC-AUC = 1.0。(Cramer 的 ROC-AUC < 0.5。)
ROC 曲线,ROC-AUC = 0.85
ROC-AUC 有一些优势。首先,它对类别不平衡具有鲁棒性,因为它专门衡量真正例率和假正例率。其次,它不需要选择阈值,因为它在所有阈值上评估性能。最后,它是尺度不变的,因此你的模型预测是否偏斜无关紧要。
精确率-召回率曲线绘制了跨所有阈值的精确率和召回率之间的权衡。当我们更新正预测的阈值时,精确率和召回率朝相反的方向变化。更高的阈值导致更高的精确率(更少的假正例)但更低的召回率(更多的假负例),反之亦然。该曲线下的面积 PR-AUC 总结了所有阈值上的性能。完美的分类器的 PR-AUC = 1.0,而随机分类器的 PR-AUC = 正标签的比例。
精确率-召回率曲线,PR-AUC = 0.87
标准 PR 曲线(左下)在同一直线上绘制精确率和召回率,从左上角(高精确率、低召回率)开始,向左下角(低精确率、高召回率)移动。我更喜欢一个变体(右下),其中精确率和召回率绘制为单独的线——这使得更容易理解精确率和召回率之间的权衡,因为它们都在 y 轴上。
另一个有用的诊断方法是绘制每个类别的预测概率分布。这可视化了模型分离类别的效果。理想情况下,我们会看到两个不同的峰值,一个在负类 0.0,一个在正类 1.0。这表明模型对其预测有信心,并能清晰地分离类别。另一方面,如果分布之间存在显著的重叠,这表明在生产中选择阈值可能很困难。
良好的分布分离(JS 散度 = 11.078)
为了量化分布分离,我们可以计算詹森-香农散度(JSD),这是 Kullback-Leibler(KL)散度的对称形式。具体来说,我们计算平均 KL 散度,从(i)分布 $P$ 到 $P$ 和 $Q$ 的平均值($M$),以及(ii)从分布 $Q$ 到 $P$ 和 $Q$ 的平均值($M$)。不过,我发现 JSD 很难解释,更喜欢直接看图。
检查分布的分离很有价值,因为模型可能有高 ROC-AUC 和 PR-AUC,但仍然不适合生产。例如,如果预测概率的一大部分落在 0.4 到 0.6 之间(如下所示),选择阈值会很困难——仅偏差 0.05 就可能导致精确率或召回率大幅下降。检查分布的分离让你了解到这一点。
分布分离不良(JS 散度 = 1.101)
上面的图表也说明了为什么 n-gram 和向量相似性评估/护栏不起作用。正负例的相似性分布太接近了。因此,它们不够可判别,无法用于切分阈值。
这些指标共同提供了一套扎实的工具箱,用于诊断分类性能和为生产选择好的阈值。
分类任务的诊断图表
现在我们已经掌握了评估分类任务的基础,我们可以讨论摘要评估,这(毫不奇怪)也可以简化为分类任务。
抽象摘要是生成简洁摘要的任务,这些摘要能够捕捉源文档中的关键思想。与从原文中截取整句的抽取式摘要不同,抽象摘要涉及改写和压缩信息,以创建更短的新版本。它需要理解内容、识别要点,并且不引入幻觉缺陷。
为了评估抽象摘要,Kryscinski 等人(2019)提出了四个关键维度:
流畅性:摘要中的句子是否结构完整、易于阅读?我们希望避免语法错误、随意使用大写等问题。
连贯性:摘要整体是否通顺合理?它应该结构清晰、逻辑严密,而不是杂乱的信息堆砌。
一致性:摘要是否准确反映了源文档的内容?我们需要确保没有加入新的信息或与原文矛盾的信息。
相关性:摘要是否聚焦于源文档中最重要的方面?它应该包含关键要点,并排除相关性较低的细节。
如今,大多数语言模型都能生成语法正确且易于阅读的句子,因此流畅性已不再是一个太需要担忧的问题。基于这一原因,最近的一项基准测试将流畅性排除在评估指标之外。连贯性也越来越不成问题,尤其是对于仅包含几句话甚至更短的摘要。因此,剩下的就是事实一致性和相关性,我们可以将它们表述为二元分类问题,并复用上文中的指标。
我几乎从未在表现尚可的 LLM 输出中见到语法错误或不连贯的文本(可能一万次里才有一次)。因此,没有必要投入资源评估流畅性和连贯性。
尽管 n-gram(ROUGE、METEOR)、相似度(BERTScore、MoverScore)和 LLM 评估(G-Eval)都很流行,但我发现它们并不可靠和/或缺乏实用性。因此,我们不会在这里讨论它们。更详细的批评请参阅附录。
为了衡量事实一致性,我们可以微调一个自然语言推理(NLI)模型,将其用作学习型指标。先回顾一下 NLI 任务:给定一个前提句和一个假设句,任务是预测该假设是由前提蕴含(即在逻辑上可从前提推出)、与前提中立,还是与前提矛盾。
自然语言推理任务中的前提与假设
我们也可以使用 NLI 模型评估摘要的事实一致性。关键思路是将源文档视为前提,将生成的摘要视为假设。如果摘要与源文档矛盾,那么该摘要在事实层面就是不一致的,也就是出现了幻觉。
自然语言推理任务中的文档与摘要
默认情况下,NLI 模型会返回蕴含、中立和矛盾的概率。为了得到事实不一致的概率,我们去掉中立维度,对剩余的蕴含和矛盾维度应用 softmax,然后取矛盾的概率。务必检查你的 NLI 模型中各维度所代表的含义——Google 的 T5 NLI 模型在 dim = 1 处表示蕴含,而 Meta 的 BART NLI 模型则在 dim = 2 处表示蕴含!
def get_prob_of_contradiction(logits: torch.Tensor) -> torch.Tensor:
"""
Returns probability of contradiction aka factual inconsistency.
Args:
logits (torch.Tensor): Tensor of shape (batch_size, 3). The second dimension
represents the probabilities of contradiction, neutral, and entailment.
Returns:
torch.Tensor: Tensor of shape (batch_size,) with probability of contradiction.
Note:
This function assumes the probability of contradiction is in index 0 of logits.
"""
# Drop neutral logit (index=1), softmax, and get prob of contradiction (index=0)
prob = F.softmax(logits[:, [0, 2]], dim=1)[:, 0]
return prob
只需几百个特定任务的样本,模型就能开始识别明显的事实不一致,并且很可能优于基于 n-gram、相似度和 LLM 的评估。样本达到一千个或更多时,它就能成为可靠的事实一致性评估器,甚至可以胜任幻觉护栏。为了减少数据标注需求,我们可以使用事实不一致性基准(Factual Inconsistency Benchmark,FIB)和统一摘要基准(Unified Summarization Benchmark,USB)等开源、许可宽松的数据进行自举。
下图展示了用于评估事实不一致性的 NLI 评估器在 FIB 上的表现。上方图表展示微调前的性能,下方图表则展示在 USB 和 FIB 上微调后的性能。尽管显然仍有改进空间,但这表明,只需在开源、许可宽松的数据上进行少量微调,就能将 ROC-AUC 从 0.56(实际上近乎随机)提升到 0.85!
微调前(上;ROC-AUC=0.56)和微调后(下;ROC-AUC=0.85)的事实不一致性评估结果
我认为,从投入产出比来看,很难找到比 NLI 方法更适合评估和/或检测事实不一致性的方案。如果你知道更好的方法,请私信我!
同样的范式也可以用于开发相关性的学习型指标。简而言之,我们可以收集人类对生成摘要相关性的判断,然后微调 NLI 模型来预测这些相关性评分。
另一种方案是根据人类偏好训练奖励模型。作为 InstructGPT 的前身,Stiennon 等人(2020)训练了一个奖励模型,用于评估 Reddit 帖子的生成式摘要。Wu 等人(2021)也针对虚构小说开展了类似的工作。
在 Stiennon 等人(2020)的研究中,他们修改了摘要语言模型,使其返回数值分数而不是文本摘要,从而将其转变为对摘要质量进行评分的奖励模型。具体做法是添加一个输出标量值的线性头。随后,使用成对的摘要偏好数据训练该模型,使其为更好的摘要给出更高的分数。对于每一对摘要 $y_0$ 和 $y_1$,他们最小化以下损失函数:
直观地说,这个损失函数会鼓励奖励模型为人类偏好的摘要给出更高的分数。sigmoid 函数 $\sigma$ 会将两个摘要之间的奖励差值压缩到 0.0 到 1.0 之间。训练完成后,他们对奖励模型的输出进行归一化,使数据集中的参考摘要平均得分为零。这为比较生成摘要的质量提供了一个基准。
一个相关任务是观点摘要。这类任务需要从一组观点(例如客户反馈、社交媒体内容或产品评论)中生成摘要,捕捉关键方面及其对应的情感。我们可以将一致性和相关性指标调整为:
情感一致性:对于每个关键方面,摘要是否准确反映了所表达的总体情感?例如,如果大多数评论称赞电池续航时间,却批评相机质量,那么摘要应该体现这一点。
方面相关性:摘要是否涵盖了所讨论的主要话题?如果许多评论都对电池续航时间和相机质量表示担忧,那么摘要中就应该包含这些要点。
OpinSummEval 论文探索了多种评估方法,并发现其中两种最有效:BARTScore 和基于问答(QA)的评估。该研究使用 Yelp 数据集的测试集,其中包含 100 个样本,每个样本由以下内容组成:(i)针对同一产品或服务的八条评论;(ii)一份人工撰写的评论摘要。
BARTScore 将评估视为一项文本生成任务。它使用预训练的 BART 计算给定评论 $x$ 时生成摘要 $y$ 的条件概率。这个分数本质上就是从评论生成摘要的对数似然。
$y_t$ 表示位置 $t$ 上的 token。权重 $w_t$ 可用于强调不同的 token,也可以将所有 token 的权重设为相同。
他们尝试了 BARTScore 的几种变体,发现 $\text{BARTScore}_{rev→hyp}$ 的表现最好。首先,他们通过编码器对评论($rev$)和摘要($hyp$)进行编码。然后,将编码后的评论作为源序列,将编码后的摘要作为解码器的目标序列。解码器会根据评论和此前生成的摘要 token,计算生成每个摘要 token 的概率。最后,将这些概率求和,并根据摘要长度进行归一化,得到最终分数。
基于 QA 的评估采用了更迂回的方法。其思路是针对评论生成问题,根据摘要回答这些问题,然后将答案与原始评论进行比较。这通常包括以下几个步骤:
从评论中选择关键短语或句子作为“答案”
根据这些答案和评论文本生成问题
通过 QA 模型,根据摘要回答问题
将 QA 模型给出的答案与原始答案进行比较
这里的直觉是,一份好的摘要应该包含回答有关评论的相关问题所需的信息。如果 QA 模型根据摘要得到的答案,与直接根据评论得到的答案相似,就说明该摘要正确捕捉了关键方面和情感。
尽管 QA 评估在 OpinSummEval 中表现出色,但在我看来,它们过于复杂。我们需要分别使用模型来选择答案、生成问题和回答问题,还需要一种方法来评估参考答案与生成答案之间的重合程度。相比之下,NLI 和 BARTScore 评估更简单,也更直接。
最后一个值得考虑的评估指标是长度遵循度。它衡量模型能否遵循指令和 n-shot 示例,生成满足字数或字符数限制的摘要。对于许多空间受限的实际应用(如推送通知或评论摘要片段),长度遵循度至关重要。评估这一点很简单——我们只需统计生成摘要中的单词数或字符数即可。
机器翻译是将文本从一种语言自动转换为另一种语言的任务。其目标是在生成流畅且符合目标语言语法的译文时,保留原文的含义和意图。
机器翻译的评估指标不胜枚举。为了缩小范围,我们可以参考每年举办的机器翻译研讨会(Workshop on Machine Translation,WMT)提供的指导。这里将重点介绍三个基于参考译文的评估指标(即将机器译文与人工编写的参考译文进行比较),以及一个无需参考译文的评估指标:
统计指标:chrF
学习型指标:BLEURT、COMET
学习型指标(无需参考译文):COMETKiwi
那么 BLEU(Bilingual Evaluation Understudy,双语评估替补)呢?虽然它是最常用的翻译评估指标,但在 WMT22 和 WMT23 的排行榜上都位居末尾。相比之下,上述评估指标表现更好,并已被 WMT 采用为基线。
chrF(character n-gram F-score,字符 n-gram F 分数)与 BLEU 类似,但它在字符层面而非词语层面运行。它是机器翻译领域第二流行的指标,相较于 BLEU 具有多项优势(稍后我们会谈到)。
chrF 背后的思路是计算机器译文(MT)与参考译文之间字符 n-gram 的精确率和召回率。精确率($chrP$)衡量 MT 中与参考译文匹配的字符 n-gram 所占的比例。召回率($chrR$)衡量参考译文中的字符 n-gram 被 MT 覆盖的比例。该计算会针对不同的 $n$ 值进行(通常最大为 6)。为了将 $chrP$ 和 $chrR$ 结合起来,我们使用调和平均数,其中参数 $\beta$ 用于控制精确率和召回率的相对重要性。当 $\beta = 1$ 时,精确率和召回率的权重相同。$\beta$ 的值越大,召回率的重要性越高。
chrF 的一个优点是,它直接在字符层面运行,因此不需要预先进行分词。这使其易于应用于形态复杂或书写形式不标准的语言。它的计算效率也很高,因为主要涉及可并行化并在 CPU 上运行的字符串匹配操作。此外,它与语言无关,可用于评估众多语言对之间的翻译。这一点优于 BLEURT 和 COMET 等学习型指标,后者需要针对每个语言对进行训练。因此,尽管 chrF 无法捕捉流畅度、连贯性和充分性等更高层次的翻译质量,但它仍然是一个可靠的起始评估指标。
sacreBLEU 提供了 chrF(以及其他指标)的标准化实现,可确保在不同系统和任务中获得一致的结果。
BLEURT 由 Google Research 于 2020 年提出,旨在改进 BLEU。它构建于广受欢迎的 BERT 模型之上,能够以更细致、更接近人类的方式评估翻译准确性。BLEURT-20 使用 WMT 2017 至 2019 年指标任务中的人工评分进行训练,并在 WMT20 上完成评估。它在 WMT21 中表现优异,此后被用作 WMT22 和 WMT23 的基线。
该模型通过两个步骤进行微调。在第一步中(遗憾的是,论文将其称为预训练),研究人员通过随机扰动来自 Wikipedia 的 180 万个句子,生成了 650 万个合成句子对。扰动分为三种形式:
掩码填充:在随机位置和序列中插入掩码,类似于 BERT 的掩码语言建模任务。这会教会模型填充缺失的单词。
回译:使用现有翻译模型将句子从英语翻译成另一种语言,再翻译回英语。目标是创建保留原始含义但表层形式不同的释义。
单词丢弃:从句子中随机删除单词。这会教会模型处理不完整或带有噪声的输入。
通过这些扰动,BLEURT 的第一个微调阶段让模型接触包含错误和变体的合成译文。随后,训练模型预测这些合成句子对在多个自动化指标(如下)上的组合结果。其直觉在于,通过学习多个指标,BLEURT 可以吸收它们的优点,同时规避其缺点。这一步成本高昂,因此通常会通过加载已完成该步骤的检查点来跳过。
BLEURT 第一个微调步骤使用的各种目标函数
在第二个微调步骤中,BLEURT 使用机器译文的人工评分进行微调。这使模型的预测结果与人类对质量的判断保持一致,而后者正是我们最终关心的评估标准。训练数据来自往年的 WMT 指标任务,其中人工标注者以 0 到 100 分的尺度对译文进行评分。
使用 BLEURT 时,我们需要提供候选译文和参考译文组成的句子对,模型会为每个句子对返回一个分数。Google Research 提供了一个采用 Apache-2.0 许可证的实现。应使用 BLEURT-20 检查点,它会生成 0 到 1 之间的分数,其中 0 表示随机输出,1 表示完美输出。
from bleurt import score
checkpoint = "bleurt/test_checkpoint"
references = ["Esta es la prueba."]
candidates = ["Esto es una prueba."]
scorer = score.BleurtScorer(checkpoint)
scores = scorer.score(references=references, candidates=candidates)
assert isinstance(scores, list) and len(scores) == 1
print(scores)
COMET 由 Unbabel AI 于 2020 年提出,采用了略有不同的方法:除了机器译文和参考译文,COMET 还会使用源句。这使模型能够结合输入语境评估翻译质量,而不仅仅是将输出与参考译文进行比较。在底层,COMET 基于 XLM-RoBERTa 编码器,它是广受欢迎的 RoBERTa 模型的多语言版本。尽管如此,该方法足够灵活,可以与