LLM微调数据集的评估方法论
系统介绍如何设计和评估微调用的高质量数据集。对构建生产级LLM应用的开发者有直接指导价值。
系统介绍如何设计和评估微调用的高质量数据集。对构建生产级LLM应用的开发者有直接指导价值。
我之前试用过一些一键式 LLM 微调服务,现在正适合回到问题的核心:评估所有这些微调模型和实验的实际表现。我直觉上觉得自己的微调模型表现相当不错,但我们做的不是靠直觉判断的生意,所以我希望能拿出一些真实的数据,来证明或推翻这个假设。
如果你没有读过这个系列之前的文章,这里快速回顾一下:我正在构建一个模型,它可以接收这样一段新闻稿文本:
“2011-11-S-011 ISAF 联合司令部——阿富汗,立即发布。阿富汗喀布尔(2011 年 11 月 7 日)——阿富汗与联军安全部队在巴达赫尚省阿尔戈地区开展了一次行动,搜捕一名 Haqqani 协助者。该协助者与该地区的其他武装组织头目协调自杀式袭击。行动期间,一名当地男性在多次口头警告后仍拒绝服从,并对安全部队表现出敌意。安全部队向此人开火,导致其死亡。安全部队缴获了一支霰弹枪,以及能证明这名当地人与 Haqqani 网络有关联的情报。安全部队还在行动期间拘留了两名疑似武装分子。”
……然后将它转换成这样的结构化数据,也就是一个 JSON 对象:
{
'name': '1',
'start_date': '2011-11-07',
'event_type': ['captureandkill'],
'province': ['badakhshan'],
'target_group': ['haqqani'],
'min_killed': 1,
'min_captured': 2,
'killq': True,
'captureq': True,
'killcaptureraid': True,
'airstrike': False,
'noshotsfired': False,
'min_leaders_killed': 0,
'min_leaders_captured': 0
}
现在,我已经微调了多个模型,想了解它们究竟有多好。我之前展示过一些使用 OpenAI gpt-4-turbo 完成的初步基线评估,但现在我想让不同模型正面较量。
我也希望梳理出一些边缘情况,因为我知道自己作为人工标注员时,也曾在这些地方犯难。(我已经将这个项目的数据集公开发布到了 Hugging Face Hub,而且其中的每一条数据都是由我亲自标注的,所以我对这些数据非常熟悉。)我甚至可以考虑利用这些困难样本生成一些合成数据,以提升模型在这些边缘情况上的表现,不过那是很久以后才需要处理的任务。
这篇博客文章将以文字形式概述我正在加入测试套件的一些评估,以及为什么要加入它们。我从 Hamel Husain 的《Your AI Product Needs Evals》一文中学到了很多。如果你对此感兴趣,我建议先阅读那篇文章,然后真正动手落实他的建议。
最应该从中入手的衡量指标,就是单纯判断:“LLM 的预测到底对不对?”如果这些评估全部由我手动完成,那么以前面的样本为例,我会问自己:“博客文章中提到的事件开始日期,真的像模型预测的那样是 ‘2011-11-07’ 吗?”“事件是否发生在 Badakhshan 省?”以及“行动的目标组织是否是 Haqqani?”
逐项比较每个属性时,得出这些判断并不困难。然后,我可以对数据集测试切片中的每个样本重复这个过程。如果想得到一个汇总指标,就计算平均值;也可以分别得出日期、省份、目标组织等字段的指标,从而了解模型是否在预测的某个部分表现得尤其吃力。
ISAF 的任务已经结束,因此我不必太担心新数据,也不需要让模型适应一个持续变化的世界。不过,训练数据中可能没有充分覆盖某些规模较小的组织——例如在预测目标组织时——所以我想知道,模型面对从未见过的数据时表现如何。
我的 prompt 会传入数据 schema,并鼓励模型在响应中遵循这个 schema。但如果出现了一个新的组织,模型会把这个新组织加入 schema 吗?我可以编写一项评估来测试这一点。
另一个边缘情况是,新闻稿可能没有采用标准格式。我读过全部新闻稿,因此知道其中绝大多数都相当程式化;但有时会发生特殊事件或事故,导致新闻稿作者偏离标准模板。我希望确认模型能够:
即使新闻稿讲的是某个人的生日聚会,也不会为了产出某种 JSON 响应而凭空捏造内容。
更理想的是,在发生这种情况时,输出某种错误码或空响应。
我可以使用这类域外数据的样本来观察会发生什么,并量化模型凭空幻觉出内容的频率。这一点非常重要,因为这个模型成败的关键就是准确性。
这些新闻稿试图透露一些信息,却又不会透露太多。事实上,当我在 2011 年发布有关这些新闻稿的报告时,ISAF 甚至专门发布了一篇新闻稿(!),其中写道:
“在反叛乱战争中,信息并不总是对外公开,因此,基于新闻稿开展的研究既可能不完整,也可能存在问题。[…] 仅仅分析新闻稿,无法开展具有权威性的研究,因为通过此类新闻稿发布的信息在设计上就是不完整的。”
因此,阅读这些新闻稿在很大程度上是在做弦外之音的解读。在前面引用的新闻稿中,所有数量都很明确——“一名协助者”“一名男性”“两名武装分子”——所以很容易确定有多少人被击毙或抓获。但在很多新闻稿中,尤其是在突袭行动频率极高的时期,你只能对其中一些词语的含义作出假设,再为这些词语赋予最小值。
因此,‘a couple’ 表示至少两个,而 ‘a few’ 则表示三个或更多。类似地,‘dozens’ 表示不止一个“十几”,因此其最小值至少为 24。原始报告中写道:
“如果一篇新闻稿称有 ‘insurgents’ 被拘留,却没有提供更多细节,我们就将该事件中被拘留人数的最小值记为 2,因为无法确定人数是否更多。我们将 ‘a couple’ 理解为 2。我们将 ‘several’ 理解为至少 3,尽管在其他情况下,‘several’ 曾被用于指代 7 人或 8 人。我们归类为至少 3 的其他表达还包括:‘a few’、‘some’、‘a group’、‘a small group’ 和 ‘multiple’;这些表达有时会指代多得多的人数,但为了得出最低限度仍可接受的数字,在新闻稿没有提供其他信息的情况下,我们选择了较小的数字。我们将 ‘numerous’ 和 ‘a handful’ 理解为至少 4,将 ‘a large number’ 理解为至少 5。”
这些报告大多描述当天或前一天发生的事件,但偶尔也会提到发生在“上周四”或“上周”的事件。这时,你就必须知道新闻稿的发布日期,再据此进行计算。对于这种向前回溯的时间标注,我尤其想知道——更准确地说,是尤其担心——我的 LLM 表现如何。无论最后得到什么分数,这个问题大概都能通过一些手动解析和逻辑来修复,但我们首先需要知道它究竟是不是一个问题。
一般来说,事件都会被标注所在省份——准确地说,只有 23 起事件例外。但如果没有省份信息,LLM 可能就需要根据村庄名称反推出省份,或者只能说明事件发生在阿富汗南部,乃至整个阿富汗范围内。有几次,新闻稿本身其实出现了错误,声称 X 村或 Y 村位于某个省份,但实际情况并非如此,它属于另一个省份。那么在这种情况下,我们应该期望 LLM 将事件归入该村庄实际所属的正确省份,还是保留新闻稿中的错误?
有时,一篇新闻稿可能会说某个事件发生在“X 省的省会”,却没有提到该城市的名称。因此,LLM 必须具备一些这方面的知识,而我想测试它在这种情况下的表现。
这些错误也许看起来微不足道,但对于这样的项目来说——我的报告基于这些数据提出了一些相当严厉的指控,并得出了某些结论——事实出错是不可接受的。对于面向内部的 LLM 聊天机器人,出错的代价很小;但对于这样的项目,潜在后果可能严重得多,因此我才要构建如此细致的评估。
部分新闻稿还存在另一个问题:同一个地点或人名可能采用多种不同的拼写方式。对于某些内容——例如省份名称——统一采用固定的命名规范是合理的,但对于另一些内容,应该如何处理并不总是那么明确。因此,我们的评估应当确保 LLM 输出能够正确识别某些省份、称谓或姓名的常见变体。
有些叙述非常复杂,可能根本不存在一种正确的方法,来为已发布的文本分配确切数字。在标注这些样本时,即便我们知道确实发生了某些事情,我也常常只是将最小人数保留为零。LLM 是否也会作出同样的判断?它应该在什么阈值下决定不冒险猜测?
显而易见的下一步,是把这些评估标准真正编写成代码,然后在我们的微调 LLM 以及通过 API 调用的专有模型上运行。在接下来的几天里,我会继续推进这项工作。幸运的是,我第一次撰写报告时,就已经完成了识别上述问题所需的大部分工作。因此,现在需要做的并不是开辟多少新领域,而只是坐下来把事情完成。