人机协同蒸馏实用指南
随着自然语言处理领域的进步和新理念的发展,出现了越来越多高效利用计算资源的方法,从而产生运行成本更低、更易于控制的AI系统。
工业领域的软件
在众多炒作中,需要牢记AI开发本质上仍是软件开发,许多相同原则仍然适用。虽然工作流快速变化,新范式不断涌现,但最终帮助团队可靠构建技术的基本要素不变。行业经验表明,我们需要解决方案具备:
- 模块化:能够以不同方式组合我们理解的少量基础组件
- 透明性:能够调试或预防问题
- 可解释性:能够建立关于系统工作原理的正确心智模型
如果AI系统是一个需要一次性解决整个问题的黑盒,我们很难深入了解应用在不同场景下的表现以及如何改进它。这就变成了纯粹的经验性问题:只能尝试看看。
另一个维度涉及整个开发工作流和生命周期。我们通常需要:
- 数据隐私:内部数据不离开服务器,满足法律和监管要求
- 可靠性:具有稳定的请求时间和极少故障
- 经济性:符合预算限制
这使得依赖第三方API变得不切实际。不幸的是,运行开源模型并不一定比使用API更便宜,因为某些提供商确实具有规模经济优势。然而,将对大型生成模型的依赖从运行时转移到开发阶段改变了这一计算。如果我们能够生成更小的任务特定模型,就能实现更具成本效益的解决方案,同时提供完整的数据隐私和更低的运营复杂性,从而显著提高可靠性。
应用NLP策略
为了说明这一理念,这里有一个经典的应用NLP问题:假设您为电子制造商或零售商工作,收集了用户生成的产品评论并希望进一步分析。计划可能包括:
- 在评论中查找产品提及
- 将提及链接到包含更多元信息的目录
- 提取不同属性(如电池、相机、性能和设计)的客户情感,称为"面向方面的情感分析"
- 以结构化格式将结果添加到数据库,以便查询和大规模计算情感分析
观察数据,一些情感表达非常直接,几乎不需要复杂解决方案。其他则更加微妙:我们知道移动电源是什么,并且需要一直使用它意味着手机电池寿命可能很差。做出这种预测需要大量关于语言和世界的知识。
大型生成模型非常擅长这一点。然而,我们解决这个特定问题所需的知识实际上只是模型能力及其权重编码的非常小的子集。那么,如果我们只能提取那些部分,并为我们的特定面向方面情感任务创建更小的任务特定组件呢?
上下文学习:使用自然语言提示访问信息,而无需为特定任务微调模型权重 迁移学习:使用从不同任务学到的知识(例如预测下一个单词的语言建模目标)来改进另一个任务的泛化能力
关注上下文学习作为新技术并不意味着迁移学习已被取代或过时。它只是用于不同目的的不同工具。最新文献表明,与少样本上下文学习方法相比,使用BERT-base等嵌入的迁移学习仍然非常有竞争力(Zhou等,2024)。
这确实有道理:如果没有可扩展的方法用标注数据改进模型,那将很奇怪。还需要记住,研究中的评估通常在基准数据集上进行,即我们本质上无法控制的数据集。然而,在应用工作中,我们完全控制数据。因此,如果使用基准数据已经显示出有希望的准确性,我们很可能通过创建自己的任务特定数据获得更好的结果。
使用LLM进行预测任务
从根本上说,面向方面的情感分析是预测任务,而不是生成任务。我们试图创建结构化输出,供其他程序使用——而不是生成供人类使用的非结构化文本或图像。
上下文学习引入了一种新的工作流,使用预训练模型执行预测任务:通常使用提示模板和相应的解析器,将原始文本输出转换为任务特定的结构化数据,而不是在编码器模型之上训练任务网络。
对于蒸馏,我们可以将输出用作任务特定模型的训练数据。理想情况下,我们希望包含人机协同步骤,以便纠正LLM可能出现的任何错误。如果不纠正错误,我们无法真正期望比LLM做得更好——垃圾进,垃圾出,正如他们所说。
缩小原型与生产之间的差距
构建令人印象深刻的演示和原型从未如此容易。但与此同时,许多团队正在经历所谓的"原型高原":当需要将解决方案投入生产时,原型无法转化为可用的系统。
根本原因之一通常在于工作流的分歧。如果原型假设的输入和输出与生产系统根本不同,例如样本文本到文本与用户生成的文本到结构化数据,就无法保证它在实践中以相同方式工作。理想情况下,您需要一个标准化输入输出并使用应用程序在运行时需要处理和生成的相同数据结构的原型工作流。
设计评估
退一步并致力于稳健稳定的评估可能不是原型过程中最令人兴奋的部分,但至关重要。没有良好的评估,您将无法知道系统是否在改进以及您所做的更改是否确实带来更好的结果。您的评估应由运行时数据的具体示例组成,您知道这些示例的正确答案——仅使用您能想到的任意示例尝试,或请另一个LLM为您进行评估是不够的这就像在训练数据上进行评估:它不会提供有意义的见解,只会复制模型的预测,而这正是您首先要评估的内容。
评估系统时,准确性分数不是唯一应该跟踪的指标:更重要的是系统的效用:它是否解决了应该解决的问题,以及是否适合应用程序的更大背景。
在应用NLP中,注意效用和准确性之间的区别很重要。“准确性"代表您可以在测试集上计算的任何客观分数[…]。这是一个您可以跟踪的数字,如果一切顺利,该数字应该上升。相反,模型的"效用"是它在应用程序或项目中的影响。这很难衡量,并且始终取决于应用程序背景。
尽管我们希望世界整齐地归类,但通常不会,这在处理自然语言时尤其如此。就像代码一样,您想到的第一个想法通常不是最好的。一旦开始处理数据,您将不可避免地遇到未考虑的边缘情况,并且需要适应。这意味着您需要一个允许迭代工作并考虑自然语言结构和歧义的工作流。
从原型到生产的结构化数据
我相信缩小原型和生产之间的差距最终归结为正确的开发者工具。在设计spacy-llm时我们思考了很多,这是spaCy的扩展库,提供组件以使用开源和专有LLM进行各种结构化预测任务,如命名实体识别、文本分类或关系提取,内置经过实战测试的提示,可根据需要自定义。
使用spaCy和LLM驱动组件的原型工作流
以前,尝试一个想法并创建预测某些内容且可以改进的模型需要大量的数据标注工作,结果相当不确定。使用spacy-llm,您现在可以在几分钟内构建一个工作原型,并通过结构化Doc对象访问预测,该对象表示输入文本以及文档、跨度和令牌级别的预测。这还为原型设计和生产期间的输入和输出提供了标准化接口,无论您决定部署LLM驱动的方法,还是为生产系统用蒸馏版本替换组件。
使用spaCy和蒸馏任务特定组件的生产工作流
人机协同蒸馏
使用LLM组件引导管道使我们能够快速获得工作系统,并为特定任务(如文本分类或命名实体识别)生成标注数据。如果我们能够稍微改进标签——通过数据聚合丢弃明显问题,或手动纠正,或两者兼而有之——我们可以在比LLM输出更正确的数据上训练,这使我们有机会获得不仅更小更快而且更准确的模型。
目标是通过流式输入和纠正LLM的预测来创建黄金标准数据,仅提取我们感兴趣的信息,直到任务特定模型的准确性达到或超过零样本或少样本LLM基线。使用迁移学习并用预训练嵌入初始化模型意味着我们实际上需要相对较少的任务特定示例。
将人类纳入循环时,我们需要考虑其自然限制:人类擅长处理上下文和歧义,但在记忆事物和一致执行一系列重复步骤方面比机器差得多。如果呈现太多信息,我们也会不知所措并失去注意力,从而导致因疏忽而犯错。
这意味着请求人类反馈和纠正的最佳方式可能与为机器学习模型构建任务的方式大不相同。理想情况下,我们希望构建界面以减少认知负荷,并仅关注从人类那里获得最少必要信息,以纠正LLM预选的注释。
关于Prodigy
Prodigy是一个现代可编写脚本的注释工具,用于为机器学习模型创建训练和评估数据。内置的LLM工作流通过将模型纳入循环帮助您自动化数据集创建。然后您可以使用创建的数据集训练蒸馏模型。
上述示例说明了用Prodigy定义的两种可能界面。多项选择界面(左)包括各种属性的正面和负面情感,同时还允许空值(如果未选择任何选项),因为并非所有评论都涵盖所有可用方面。
另一种方法(右)是对数据进行多次传递,一次注释一个方面的情感。虽然这似乎为人类创造了更多工作,但实验表明这种方法实际上可以比同时注释所有类别快得多,因为它帮助注释者集中注意力并让他们更快地处理示例。
案例研究和结果
自从为spaCy和Prodigy发布LLM驱动的蒸馏工作流以来,我们一直在各种用例中尝试它们,并开始记录不同领域的行业项目,这些项目已经能够取得非常有希望的结果。
您是否在项目中尝试过人机协同蒸馏并有有趣的用例分享?或者需要帮助在组织中实施类似工作流?与我们联系!
PyData NYC:分析Reddit上的烹饪帖子
在去年由Ryan和我在PyData NYC主持的研讨会中,我们设定了一个雄心勃勃的目标:能否用任务特定组件击败LLM?作为任务,我们选择从r/cooking Reddit帖子中提取DISH、INGREDIENT和EQUIPMENT。通过使用LLM预注释跨并与参与者一起纠正预测,我们能够用任务特定组件击败74%的少样本基线,产生一个小型模型工件和20倍的推理时间加速。
- 数据开发时间是指基于参与者在研讨会中花费的时间,单人产生训练和评估示例所需的时间。
指标 | 生成式LLM | 蒸馏组件 |
---|---|---|
准确性 (F分数) | 0.74 | 0.74 |
速度 (词/秒) | < 100 | ~ 2,000 |
模型大小 | ~ 5 TB | 400 MB |
参数 | 1.8t | 130m |
训练示例 | 0 | 800 |
评估示例 | 200 | 200 |
数据开发时间 1 | ~ 2h | ~ 8h |
由于研讨会的时间限制,我们在达到基线准确性后停止,但更多注释可能会带来更好的结果。处理数据还揭示了许多边缘情况,并引发了关于标签方案的有趣讨论(例如"Cheetos是成分吗?")。对于实际应用,解决这些问题很重要:如果不清楚如何应用预期的分类,开发产生一致结果的AI系统将更加困难。
某全球机构:实时商品交易洞察
某全球机构是全球能源和商品数据和洞察的领先提供商之一,涵盖金属、农产品和化学品等原材料。为了提供更好的市场透明度并实时生成结构化数据,他们的团队构建并部署了小至6 MB的高效spaCy管道,这些管道完全在高安全环境中内部运行,并满足严格的推理SLA。在开发期间使用LLM和Prodigy进行半自动注释,他们还能够将数据收集和注释工作流的速度提高10倍。
指标 | 全球碳信用 | 美洲原油 | 亚洲钢筋 |
---|---|---|---|
准确性 (F分数) | 0.95 | 0.96 | 0.99 |
速度 (词/秒) | 15,730 | 13,908 | 16,015 |
模型大小 | 6 MB | 6 MB | 6 MB |
训练示例 | 1,598 | 1,695 | 1,368 |
评估示例 | 211 | 200 | 345 |
数据开发时间 | ~ 15h | ~ 15h | ~ 15h |
将其视为重构过程
虽然您可以将蒸馏视为纯粹的技术挑战,但我认为将其视为重构过程更有意义。就像编写和重构软件一样,您试图将更大的问题分解为模块化和可组合的构建块。目标是从可用技术中选择最佳可能技术,并平衡运营复杂性、易用性和结果质量之间的权衡。
重构也是重新评估依赖关系的机会:引入这个大型库是否有意义,而您只使用其中的一个简单函数?同样,您能否用更小更快的版本替换更大、更慢、更昂贵的模型?是否有可以从运行时移动到开发的依赖关系?
使问题更容易
在应用工作中,您被允许使问题更容易,这很容易被忘记!这不是大学或学术界,您被赋予固定输入和输出的数据集。与其他类型的工程一样,这不是一场为最困难的问题想出最聪明解决方案的竞赛。我们试图完成任务。如果我们能用简单得多的问题替换困难的问题,那就是胜利。
降低系统的运营复杂性也意味着出错的可能性更小。如果确实出现问题,诊断和修复它们会变得容易得多。在其核心,许多NLP系统由相对简单的分类组成。您可以将它们全部塞进单个提示中,或者将它们分解成可以独立处理的较小部分。如今许多分类任务实际上非常容易解决——但如果一个模型需要一次性完成所有任务,它们就会变得复杂得多。
与其抛弃我们学到的所有软件设计知识并要求LLM一次性完成所有工作,我们可以将问题分解成部分,并将LLM视为系统中的另一个模块。当我们的需求发生变化或扩展时,我们不必回去更改整个内容。
仅仅因为结果更容易,并不意味着到达那里的过程是微不足道的。只是关于这个过程