计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-24

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-24


目录

文章目录


1. Optimizing Preference Alignment with Differentiable NDCG Ranking

Authors: Jiacong Zhou, Xianyun Wang, Jun Yu

https://arxiv.org/abs/2410.18127

使用可微分NDCG排序来优化偏好对齐

摘要

本文提出了一种新的方法,名为直接排名偏好优化(Direct Ranking Preference Optimization, DRPO),用于改善大型语言模型(LLMs)与人类偏好的对齐。通过将人类偏好对齐问题视为学习排名(Learning-to-Rank, LTR)任务,并利用排序网络和不同的排序策略,DRPO能够在考虑偏好数据的基础上优化响应的排名。由于传统的Normalized Discounted Cumulative Gain(NDCG)度量不可微分,本文提出了一种可微分的NDCG(diffNDCG)损失函数,以便于端到端的优化。此外,本文还提出了一种新颖的基于边际的自适应排名策略,以提高生成响应的质量。广泛的实验表明,DRPO在提升生成响应质量方面优于现有的基线方法。

研究背景

大型语言模型(LLMs)在多样化的数据集上训练,能够在广泛的任务上展现出令人印象深刻的能力。然而,由于训练数据的多样性,这些模型有时会产生与人类偏好不一致的内容,例如编造的答案、冒犯性评论或有害的回应。为了确保人工智能系统的安全性和可控性,研究者们开始关注如何引导LLMs生成与人类偏好一致的响应。

问题与挑战

尽管已有研究通过强化学习(Reinforcement Learning with Human Feedback, RLHF)来对齐LLMs与人类偏好,但这些方法在优化过程中存在复杂性,且由于训练成本高昂而难以实现。此外,现有的偏好对齐技术主要关注成对的人类偏好,这限制了模型在处理复杂偏好关系时的表现。研究表明,当前的偏好对齐技术在标准数据集上的排名准确率低于60%,这表明现有方法未能充分捕捉序列中的理想偏好关系。

如何解决

为了解决上述挑战,本文提出了DRPO方法,它将人类偏好对齐视为一个LTR任务,并利用NDCG这一广泛使用的LTR指标来优化基于偏好数据的响应排名。由于NDCG的不可微分性,本文提出了diffNDCG损失函数,通过排序网络来模拟NDCG。此外,为了提高生成响应的质量,本文提出了一种新颖的基于边际的自适应排名策略。

创新点

  1. 直接排名偏好优化(DRPO):将人类偏好对齐问题视为LTR任务,并使用NDCG作为优化指标,这是首次尝试将LLMs与排名人类偏好数据对齐。
  2. 自适应排名策略(Adaptive Rank Policy Score):提出了一种新的排名策略,它根据相对位置动态调整偏好和非偏好响应之间的得分边际,以最大化偏好响应的可能性。
  3. 可微分的NDCG(diffNDCG):开发了一种可微分的NDCG度量,通过优化diffNDCG损失函数,可以优先考虑排名列表顶部的响应,并对于错误放置的高相关性项施加更严格的惩罚。

算法模型

算法框架

DRPO算法包括三个主要组成部分:排名分数计算、可微分响应排名和diffNDCG损失函数。

排名分数计算

  • 策略参考比率(Policy Reference Ratio, PRR):计算排名分数的基本标准是,更受偏好的响应应获得更高的分数。PRR是一种常用的策略,它通过比较策略模型πθ和参考模型πref之间的相对可能性来计算排名分数。
  • 自适应排名策略分数(Adaptive Rank Policy Score, ARP):ARP专注于生成序列的对数似然,并基于对数似然建立一个基于长度归一化的基本分数函数。此外,ARP通过结合基础加权排名位置项和过去分数的指数移动平均估计来定义排名感知边际。

可微分响应排名

  • 排序网络:使用排序网络对响应进行排序,该网络通过比较和交换操作对序列进行排序,同时保持可微分性。
  • 可微分交换操作:通过引入S形函数,将传统的max和min操作转换为可微分的形式,从而实现在整个排序过程中的端到端优化。

diffNDCG损失函数

  • NDCG:NDCG是一种有效的LTR指标,用于衡量排名质量。它根据响应的相关性分数和排名位置为响应分配收益,并为排名位置应用折扣因子。
  • 可微分NDCG(diffNDCG):通过使用可微分的排序网络,将NDCG的计算过程转换为可微分的形式,从而可以直接优化NDCG指标。

实验效果

数据集和模型

  • 数据集:使用了Anthropic的Helpful and Harmless(HH)数据集、UltraFeedback数据集和VLFeedback数据集。
  • 模型:主要基于Qwen1.5模型和Mistral模型进行实验,并在多模态偏好对齐任务中训练了Qwen-VL-Chat模型。

基线方法

与多种基线方法进行了比较,包括SFT、DPO、PRO、LiPO、DPOBT、DPOPL等。

主要结果

  • 在HH数据集上,DRPO在不同模型规模下均优于基线方法。例如,与SFT相比,GPT-4的胜率提高了5.22%至6.13%,奖励模型的胜率提高了4.69%至8.98%。
  • 在UltraFeedback数据集上,DRPO在MT-Bench上的表现与其他方法相当,但在AlpacaEval2.0的长度控制胜率(LC)和原始胜率(WR)上分别提高了1.2%和0.7%。
  • 在多模态VLFeedback数据集上,DRPO在MME基准测试中比其他方法高出21.8分,在MM-Vet基准测试中提高了1.4分,在MM-Bench基准测试中提高了1.64%。


重要数据与结论

  • DRPO在不同数据集和模型规模上均显示出优于现有方法的性能,这证明了其在提升LLMs与人类偏好对齐方面的有效性。
  • diffNDCG损失函数和自适应排名策略(ARP)是提升模型性能的关键因素。通过优化diffNDCG,模型能够更准确地对响应进行排名,并在排名准确性和胜率方面取得了显著提升。

推荐阅读指数

4/5

本文提出了一种创新的方法来优化大型语言模型与人类偏好的对齐,通过将问题视为学习排名任务,并引入可微分的NDCG损失函数,有效地提高了模型的性能。

2. Advancing NLP Security by Leveraging LLMs as Adversarial Engines

Authors: Sudarshan Srinivasan, Maria Mahbub, Amir Sadovnik

https://arxiv.org/abs/2410.18215

文章标题翻译

利用大型语言模型作为对抗引擎来推进自然语言处理的安全性

摘要

本文提出了一种新颖的方法来利用大型语言模型(LLMs)生成多样化的对抗性攻击,以增强自然语言处理(NLP)的安全性。基于近期展示LLMs在创建词级对抗样本方面的有效性,我们主张将这一概念扩展到包括对抗性补丁、通用扰动和针对性攻击在内的更广泛的攻击类型。我们认为,LLMs在语言理解和生成方面的复杂能力可以跨不同领域和分类器架构产生更有效、语义一致且类似人类的对抗样本。这种对抗性NLP的范式转变具有深远的影响,可能增强模型的鲁棒性,发现新的漏洞,并推动防御机制的创新。通过探索这一新领域,我们的目标是促进更安全、可靠和值得信赖的NLP系统的发展,以应对关键应用。

研究背景

基于变换器的NLP模型在多个领域取得了显著的成功,但这些系统仍然容易受到对抗性攻击的威胁,这在关键领域中对其可靠性和可信度构成了重大风险。

问题与挑战

尽管现有的对抗性攻击方法取得了一定的成功,但它们面临着实质性的限制,这些限制阻碍了它们在现实世界场景中的有效性和适用性。这些挑战包括:

  1. 生成的对抗样本缺乏语义一致性。
  2. 对抗样本的可转移性差,即在一个模型上生成的攻击往往无法有效转移到其他模型或领域。

如何解决

我们提出利用LLMs来生成对抗样本,这可以克服当前方法的许多限制:

  • LLMs能够生成与原始输入保持上下文相关性和语义一致性的对抗样本。
  • LLMs生成的对抗样本与人类编写的内容难以区分,增强了攻击的隐蔽性。
  • 预训练于大量不同领域数据的LLMs能够跨多个领域和分类器架构生成有效的对抗样本。
  • LLMs的少样本学习能力表明它们可以快速适应新任务或领域,允许生成多样化的攻击类型。
  • LLMs对上下文和语义的理解能够生成在欺骗分类器的同时仍保留原文本意图的对抗样本。

创新点

  1. LLMs作为对抗引擎:将LLMs用作生成对抗样本的工具,而不是将它们作为对抗攻击的目标。
  2. 多样化的对抗攻击类型:超越词级修改,包括对抗性补丁、通用扰动、针对性攻击和可转移攻击。
  3. 上下文感知的对抗样本生成:利用LLMs的上下文理解能力,生成与周围文本无缝集成的对抗样本,使其更难以检测。

算法模型

本文提出的模型基于LLMs,通过微调或提示LLMs基于特定的攻击目标和约束生成对抗样本。这可能涉及迭代细化,其中LLM生成候选样本,接收关于其有效性的反馈,并相应地改进其输出。

实验效果

本文是一篇立场论文,因此没有提供具体的实验数据或结果。然而,作者讨论了这种方法的潜在影响和未来方向,包括:

  • 通过先进的对抗训练增强基于变换器的分类器的鲁棒性。
  • 生成人类般的对抗样本,重新评估AI漏洞的性质和模型鲁棒性的定义。
  • 从攻击安全性的角度揭示现有NLP系统的未知漏洞。
  • 开启AI对齐领域的新研究方向,以及利用LLMs生成多样化对抗攻击的研究。

推荐阅读指数

3/5

尽管本文没有提供实验数据,但它提出了一个创新的视角,即利用LLMs作为生成对抗样本的工具,这可能对NLP安全性领域产生重大影响。

3. Beyond Multiple-Choice Accuracy: Real-World Challenges of Implementing Large Language Models in Healthcare

Authors: Yifan Yang, Qiao Jin, Qingqing Zhu, Zhizheng Wang, Francisco Erramuspe

'Alvarez, Nicholas Wan, Benjamin Hou, Zhiyong Lu

https://arxiv.org/abs/2410.18460

超越多项选择准确率:在医疗保健中实施大型语言模型的现实挑战

摘要

大型语言模型(LLMs)在医疗领域因其类人能力而受到显著关注,这促进了探索它们在各种医疗保健应用中的潜力的努力。然而,尽管未来充满希望,LLMs在实际设置中的现实使用仍然存在多个挑战和障碍。本文从四个独特的方面讨论了LLMs在医疗应用中的关键挑战:运营漏洞、伦理和社会考虑、性能和评估困难,以及法律和监管合规性。解决这些挑战对于充分利用LLMs并确保它们负责任地融入医疗保健至关重要。

研究背景

LLMs作为医疗应用中的有力工具,提供了前所未有的能力来处理复杂的医疗数据、协助决策制定和简化工作流程。尽管潜力巨大,LLMs也提出了必须解决的挑战,以确保它们安全有效地融入现实世界的临床实践。这些挑战从技术问题(如幻觉)到围绕数据隐私、公平性和偏见的伦理问题。

问题与挑战

LLMs在医疗设置中的部署可能需要更多的谨慎,因为患者的生命处于危险之中。例如,LLM的一个错误建议可能导致误诊或不适当的治疗,从而导致患者死亡。除了技术挑战外,医疗中部署LLM还必须满足比一般领域更严格的法律和监管要求,因为医疗应用直接影响患者安全,涉及受隐私法保护的敏感健康数据,并且需要遵守严格的临床准确性和伦理责任标准,以避免伤害或误诊。

如何解决

要解决这些挑战,需要从多个角度进行综合考虑和策略制定:

  1. 性能和评估挑战:需要开发新的评估框架,模拟医生-患者互动,以更真实地评估LLMs的临床效用。
  2. 运营漏洞:需要提高LLMs的鲁棒性,减少幻觉的发生,并开发有效的内容验证方法。
  3. 伦理和社会考虑:需要确保LLMs的使用是负责任和公平的,这可能涉及使用多样化的数据集进行训练,以及开发减少偏见的技术。
  4. 法律和监管合规性:需要确保LLMs符合数据隐私、知识产权和医疗设备法规的现有法律。

创新点

  1. 跨领域挑战的综合视角:本文不仅关注医疗领域特有的挑战,还结合了一般领域的挑战,提供了一个更全面和相关的视角。
  2. 多维度挑战的分类:将挑战分为性能和评估、运营漏洞、伦理和社会考虑以及法律和监管合规性四个关键领域,为理解和解决这些挑战提供了清晰的框架。
  3. 现实世界评估的强调:强调了在现实世界临床设置中评估LLMs的重要性,而不是仅仅依赖于多项选择问题(MCQs)的评估。

性能和评估挑战

目前,大多数LLMs通过多项选择问题(MCQs)来评估其医疗能力,如美国医疗执照考试(USMLE)的MedQA子集、PubMedQA、MedMCQA和MMLU的医疗子集。这些数据集通常被使用是因为评估可以通过比较预测答案选择与地面真相自动进行,而不需要任何领域专业知识。然而,使用MCQs评估LLMs存在显著局限性,因为现实世界的临床设置中不会有任何选择可用。模仿医生-患者互动的评估框架,如AgentClinic和AMIE,代表了未来探索的有希望的方向。

此外,MCQ高分背后可能隐藏着缺陷,模型预测正确选择但提出错误的理由。具体来说,Jin等人评估了GPT-4 Vision回答《新英格兰医学杂志》图像挑战问题的理由。他们发现,尽管GPT-4 Vision通过多项选择选择准确率达到了专家级表现,但模型经常在正确最终答案时提出有缺陷的理由。这种有缺陷的理由在图像理解中最为常见,其次是逐步推理和医学知识的回忆,在正确答案中大约占30%。

模型鲁棒性和泛化

模型泛化能力是机器学习模型在来自不同来源的类似数据上表现良好的能力。在医疗AI中,这一点很重要,因为模型可能被部署在不同的患者群体、成像设备和临床设置中。然而,数据异质性提出了重大挑战:由于设备和成像协议的差异,医疗图像可能差异很大,以及患者队列的特征,如年龄、种族和健康状况。

通常,在一个数据集上训练的模型在该特定数据集上表现出色,但往往无法泛化到具有不同特征的其他数据集。一般医疗LLMs在MedQA等广泛领域表现出色,但在专业任务上表现不佳。Meditron在MedQA上的准确率为70.2%,但在从放射学文本中识别寡转移非小细胞肺癌的准确性较低。Meditron在MIMIC-CXR和MIMIC-IV等数据集上的总结性能也较低。

这些结果突出了一般医疗LLMs在处理放射学和ICU护理等专业医疗子领域时面临的挑战。因此,对这些模型进行领域特定数据的微调对于提高它们在这些专业领域的性能至关重要。例如,在眼科相关的患者查询中,经过微调的GPT-3.5得分为87.1%,而Llama2-13b得分为80.9%,表明即使较小的LLMs在应用专业微调时也能表现良好。此外,经过微调的LLMs还成功学习了放射肿瘤学特定信息,并生成了临床专家评为3.44分的医生信件,这表明在各种专业医疗领域使用微调模型的优势。

多语言能力也是泛化和鲁棒性的重要方面。在美国等国家,人们来自不同的语言背景,语言协助在临床设置中也很重要,以支持患者和医疗从业者。大多数当前的LLMs都是基于英语开发的,在同一医疗QA任务中,英语和其他语言之间的性能差异可能高达0.30 AUC。对于希伯来语等较不常见的语言,LLM难以达到与英语相当的性能。由于语言障碍可能影响患者护理,提高LLM的多语言能力对于LLM在不同语言中提供一致和准确的医疗支持至关重要。

运营漏洞

当仔细检查LLM生成的内容时,文献中讨论的最令人关注的问题之一是幻觉的发生,即LLM生成不准确、不一致或完全编造的内容。例如,Jin等人表明,ChatGPT为了使用它们作为支持其答案的证据,生成了假的文章标题和PMIDs。LLM中的幻觉可以分为两类:内在和外在。内在幻觉发生在生成的文本与输入数据直接矛盾时,如在处理临床笔记时产生不一致和不准确的输出。外在幻觉是指无法通过输入源验证或反驳的内容,这可能发生在LLM在咨询医疗信息或医疗文献参考资料时生成编造的回应。

在医疗应用中,这些幻觉可能产生严重后果,如误读临床试验结果或误分类患者数据。例如,最近的一项研究提议使用GPT-4从患者临床笔记中提取"头盔状态"。尽管模型在许多情况下表现良好,但它在遇到否定词如"未戴头盔"时表现出幻觉,导致分类错误。此外,LLM在回应医疗相关问题时可能会产生自相矛盾的答案。

减轻幻觉的一个主要挑战是验证生成内容的准确性,特别是当训练数据不完整或访问关键来源(如临床试验)受到版权或其他限制时。在这种情况下,LLM可能会用推理内容填补空白,导致外在幻觉,破坏所呈现信息的可靠性。Ji等人探讨了医疗中内在和外在幻觉的情况,他们强调当LLM面临不完整或模糊的数据时,它们倾向于生成事实上不正确的内容,经常编造听起来合理但不忠实的回应。与医疗应用中的幻觉类似的担忧也出现在谷歌的Bard模型中。模型输出中编造的参考资料和引用显示了幻觉如何误导研究人员和医疗专业人士。

此外,将LLM作为临床证据总结等任务的端到端系统引入了额外的复杂性。这些过程通常涉及多个步骤,如搜索、筛选和评估证据,其中任何步骤的错误都可能级联到最终输出。

推荐阅读指数

3/5

文章强调了在现实世界的临床设置中评估LLMs的重要性,并提出了一系列关键挑战,这些挑战需要在将LLMs融入医疗保健实践之前得到解决。

4. LLM as a code generator in Agile Model Driven Development

Authors: Ahmed R. Sadik, Sebastian Brulin, Markus Olhofer, Antonello Ceravola,

Frank Joublin

https://arxiv.org/abs/2410.18489

在敏捷模型驱动开发中将大型语言模型作为代码生成器

摘要

在模型驱动开发(MDD)中利用大型语言模型(LLMs),如GPT-4,自动生成代码是一个重大进步,但也面临挑战。自然语言描述软件时的模糊性给生成可部署的、结构化的软件工件带来了实质性障碍。本研究支持模型驱动开发作为一种可行的策略,提出了一种敏捷模型驱动开发(AMDD)方法,该方法采用GPT-4作为代码生成器。这种方法提高了代码自动生成过程的灵活性和可扩展性,并提供了允许无缝适应模型或部署环境变化的敏捷性。我们通过使用统一建模语言(UML)建模多智能体无人机车队(UVF)系统来说明这一点,通过集成对象约束语言(OCL)进行代码结构元建模,以及使用FIPA本体语言进行通信语义元建模,显著减少了模型歧义。应用GPT-4的自动生成能力产生了与JADE和PADE框架兼容的Java和Python代码。我们对自动生成的代码进行了全面评估,验证了其与预期行为的一致性,并确定了智能体交互的改进。在结构上,我们评估了仅受OCL元模型约束的代码复杂性,与受OCL和FIPA本体元模型影响的代码复杂性。结果表明,受本体约束的元模型产生的代码固有地更复杂,但其圈复杂度仍然在可管理的水平内,表明可以加入额外的元模型约束而不超出复杂性的高风险阈值。

研究背景

在人工智能时代,LLMs在多样化的代码库上进行训练,为模型驱动开发(MDD)带来了新的创新机会。MDD旨在提高软件工程实践的效率和持久性。因此,本工作扩展了我们在16中的研究,以增强敏捷模型驱动开发(AMDD)。我们的方法利用现有的LLMs,如GPT-4,自动生成可部署的软件工件17。我们的目标是节省在MDD中传统上所需的大量时间和精力,用于为每次部署开发和更新独特的代码生成器10,确保自动生成的代码结构良好,满足其预期功能和指定要求8。从形式化图形语言如统一建模语言(UML)、系统建模语言(SysML)或业务流程模型和表示法(BPMN)图表生成代码已成为当代软件工程的基石13。有了适当的工具,这些语言可以无缝转换为可执行代码,提高软件开发过程的效率22。通过集成这些语言的静态和动态方面,并使用如对象约束语言(OCL)4或FIPA元本体9等声明性语言细化模型,促进了复杂、结构良好代码的生成11,14。这种自动化确保了设计和实现之间的一致性,最小化了编码错误,并提高了软件质量,从而加快了市场进入21。深入理解系统的动态行为和总体视图对于掌握其功能至关重要23。评估自动生成代码的质量对于验证我们提出的AMDD方法至关重要。传统的可测试性、可维护性和可靠性措施,由于是定性的,容易受到主观偏见的影响12。然而,我们的研究旨在应用客观、可衡量的标准。我们分析的核心是模型生成的代码的结构完整性,我们使用圈复杂度作为结构健全性的关键指标。此外,我们的评估还包括对不同编程语言的代码功能进行比较分析,与模型设计中描述的预期行为相对比1

问题与挑战

自然语言的固有模糊性不仅对机器解释构成挑战,也对人类理解构成挑战。在利用GPT-4进行可部署代码的自动生成时,输入提示的不清晰和开放式特性经常导致代码有缺陷和不完整。这个问题在要生成的软件由不同互联工件组成的场景中尤为明显。因此,不可能用自然语言精确地封装软件。MDD通过提供高级模型作为生成最终代码的主要来源来解决这个问题。然而,设计和维护这些模型带来的挑战可能会分散MDD的有效性。首先,虽然像UML这样的传统建模方法在结构化数据方面表现出色,但它们在提供语义深度和基于规则的知识方面往往不足2。因此,尽管产生的模型在结构上健全且行为准确,但缺乏有效表示复杂现实世界情况所需的语义丰富性。其次,将这些模型转换为可执行代码远非直接15。它需要手动制作并不断更新代码生成器以适应模型修改和不断发展的技术栈,当在不同编程语言之间切换部署时,这一挑战被放大5

如何解决

解决这些问题的方法是采用敏捷模型驱动开发(AMDD)方法,该方法使用GPT-4作为代码生成器,无缝解释模型以生成准备部署的相互关联的软件工件。我们利用PlantUML将UML图表转换为正式的文本表示,以弥合基于文本的GPT-4提示和视觉UML图表之间的差距,从而便于直接输入GPT-4。如图2所示,建模者首先构建模型的层次:结构层、行为层和约束层。结构层概述了模型的静态方面,展示了软件组件及其复杂的关系。类图阐明了对象之间的关系和层次结构,包图将对象分组以突出依赖关系,组件图提供了系统功能和组件间链接的高级视图。部署图说明了系统的物理架构的硬件设置和组件分布,而对象图提供了对象的运行时快照,配置文件图将UML模型适应特定平台。行为层通过各种图表描绘了系统的运作和交互。序列图绘制了事件序列,提供了交互的时间线,活动图提供了详细的过程流程。交互图和时序图进一步探讨了组件相互作用和时间的重要性。用例图展示了外部实体与系统之间的交互,状态图追踪了实体的生命周期和状态转换。尽管结构和行为图表提供了全面的视图,但它们在阐明治理规则和语义方面不足。我们的研究引入了约束层,通过纳入超出UML范围的显式元值和规则来细化模型架构。我们使用OCL来定义详细

创新点

  1. 强可扩展性:随着计算预算的增加,MDMs的最佳验证损失按照幂律下降,与ARMs的速率相匹配。尽管MDMs仍然需要大约16倍于ARMs的计算资源才能达到相当的验证损失,但这一差距小于连续扩散模型观察到的64倍,并且随着未来优化的进行,这一差距可以进一步缩小。
  2. 零样本语言理解的竞争力:在八个标准零样本基准测试中,MDMs不仅超越了同样大小的ARM,还在四项任务中超越了更大的1.5B GPT-2模型。此外,当按照扩展定律扩大16倍预训练时间时,MDMs在所有任务中一致性地超越了ARMs。
  3. 条件生成中的灵活权衡:在标准MT-Bench上,一个11B MDM在匹配同样大小的ARM的性能的同时,实现了1.4倍的采样时间加速。通过增加采样步骤,MDMs可以在以1.4倍变慢的代价下进一步提高生成质量。
  4. 解决ARMs的挑战性任务:MDMs有效地缓解了时间质量退化,并且成功克服了更大的ARMs遇到的反向诅咒,如Llama-2(13B)和GPT-3(175B)。

算法模型

本文介绍了掩蔽扩散模型(MDMs)的基本方法,它建立在Ou等人(2024)的先进MDM之上,适合扩展。MDMs通过一个前向过程逐渐向数据中添加噪声,并学习一个相应的反向过程来生成样本。文中详细描述了前向过程、反向过程和训练目标,并提出了一种新的无监督分类器自由引导(CFG)方法,该方法在给定的条件下,通过重新调整分布来推断,有效地利用了大规模未配对数据。

实验效果

实验结果表明,MDMs在多个关键的语言任务中展现出了强大的性能和可扩展性。在语言理解方面,一个11B的MDM在八个标准的零样本基准测试中,超越了同样大小的ARM以及更大的1.5B GPT-2模型。在文本生成方面,MDMs在保持与ARMs相同性能的同时,实现了1.4倍的加速,或者在更高的计算成本下实现更高的质量。此外,MDMs有效地解决了ARMs面临的挑战性任务,如反向诅咒和时间质量退化。

重要数据与结论

本文的实验结果强调了MDMs作为ARMs在大规模语言建模中的有前途的替代品。通过扩展分析和无监督CFG的支持,MDMs在关键任务中展现出了与ARMs相当甚至更优越的性能。此外,MDMs有效地解决了ARMs的固有局限性,如改善双向推理能力。

推荐阅读指数

4/5

本文为理解MDMs在语言建模中的潜力提供了宝贵的见解,并为未来的研究提供了明确的方向。

5. Scaling up Masked Diffusion Models on Text

Authors: Shen Nie, Fengqi Zhu, Chao Du, Tianyu Pang, Qian Liu, Guangtao Zeng,

Min Lin, Chongxuan Li

https://arxiv.org/abs/2410.18514

代码:https://github.com/ML-GSAI/SMDM

扩展文本上的掩蔽扩散模型

摘要

掩蔽扩散模型(MDMs)在语言建模方面展现出了潜力,但其在核心语言任务,如文本生成和语言理解方面的可扩展性和有效性尚未充分探索。本文建立了MDMs的第一个扩展定律,展示了与自回归模型(ARMs)相当的扩展速率和相对较小的计算差距。受其可扩展性的激励,我们训练了高达11亿参数的MDMs家族,系统地评估了它们与相当或更大尺寸的ARMs的性能。充分利用MDMs的概率公式,我们提出了一个简单但有效的无监督分类器自由引导(CFG),有效地利用大规模未配对数据,提高了条件推理的性能。在语言理解方面,一个11亿MDM显示出了竞争力,超越了更大的1.5亿GPT-2模型在八个零样本基准测试中的四个。在文本生成方面,MDMs提供了与使用KV缓存的ARMs相比的灵活权衡:MDMs在速度上匹配ARMs的性能,或者在更高的计算成本下实现比ARMs更高的质量。此外,MDMs通过有效处理双向推理和适应数据中的时间变化,解决了ARMs面临的挑战性任务。值得注意的是,一个11亿MDM打破了许多更大的ARMs遇到的反向诅咒,这些ARMs拥有更多的数据和计算资源,如Llama-2(13亿)和GPT-3(175亿)。我们的代码可在 https://github.com/ML-GSAI/SMDM 上找到。

研究背景

自回归模型(ARMs)一直是概率语言建模的黄金标准。它们预测下一个标记的能力,基于链规则,自然地与语言的顺序性质对齐,并在与Transformer集成时有效扩展。然而,ARMs在需要双向上下文理解或处理数据中的时间变化的推理任务中表现出固有的局限性。这些局限性被广泛认为是反向诅咒和时间质量退化,显著限制了它们在复杂语言建模场景中的适用性。此外,它们对输出长度的线性采样时间增长为长文本生成带来了实际挑战。

问题与挑战

ARMs的局限性激发了对替代方法的兴趣:掩蔽扩散模型(MDMs)。MDMs由于其独特的概率框架而展现出希望,该框架通过填充序列中的掩蔽位置来实现灵活的双向上下文建模。尽管最近的研究显示了在无条件文本生成和零样本困惑度评估中的潜力,但MDMs的可扩展性和它们在关键语言任务中的有效性,如条件生成和语言理解,仍然是未解决的问题。此外,尚不清楚MDMs是否能够解决ARMs的固有局限性,例如提高双向推理能力。

如何解决

为了解决这些问题,我们提出了一个全面的MDMs研究,挑战了ARMs的长期主导地位,涉及语言模型的关键因素:可扩展性、语言理解和条件生成的能力。为了实现这一点,我们训练了一系列高达11亿参数的MDMs,并建立了MDMs的第一个扩展定律。利用它们独特的概率框架,我们提出了一个简单但有效的无监督分类器自由引导(CFG)机制,以利用无监督数据来增强涉及条件分布的语言任务的推理性能。值得注意的是,无监督CFG不依赖于配对数据,但仍然可以从配对数据中受益,实现超越标准CFG的性能。

创新点

  1. 强可扩展性:随着计算预算的增加,MDMs的最佳验证损失按照幂律下降,与ARMs的速率相匹配。尽管MDMs仍然需要大约16倍于ARMs的计算资源才能达到相当的验证损失,但这一差距小于连续扩散模型观察到的64倍,并且随着未来优化的进行,这一差距可以进一步缩小。
  2. 零样本语言理解的竞争力:在八个标准零样本基准测试中,MDMs不仅超越了同样大小的ARM,还在四项任务中超越了更大的1.5亿GPT-2模型。此外,当按照扩展定律扩大16倍预训练时间时,MDMs在所有任务中一致性地超越了ARMs。
  3. 条件生成中的灵活权衡:在标准MT-Bench上,一个11亿MDM在匹配同样大小的ARM的性能的同时,实现了1.4倍的采样时间加速。通过增加采样步骤,MDMs可以在以1.4倍变慢的代价下进一步提高生成质量。
  4. 解决ARMs的挑战性任务:MDMs有效地缓解了时间质量退化,并且成功克服了更大的ARMs遇到的反向诅咒,如Llama-2(13亿)和GPT-3(175亿)。

算法模型

本文介绍了掩蔽扩散模型(MDMs)的基本方法,它建立在Ou等人(2024)的先进MDM之上,适合扩展。MDMs通过一个前向过程逐渐向数据中添加噪声,并学习一个相应的反向过程来生成样本。文中详细描述了前向过程、反向过程和训练目标,并提出了一种新的无监督分类器自由引导(CFG)方法,该方法在给定的条件下,通过重新调整分布来推断,有效地利用了大规模未配对数据。

实验效果

实验结果表明,MDMs在多个关键的语言任务中展现出了强大的性能和可扩展性。在语言理解方面,一个11亿的MDM在八个标准的零样本基准测试中,超越了同样大小的ARM以及更大的1.5亿GPT-2模型。在文本生成方面,MDMs在保持与ARMs相同性能的同时,实现了1.4倍的加速,或者在更高的计算成本下实现更高的质量。此外,MDMs有效地解决了ARMs面临的挑战性任务,如反向诅咒和时间质量退化。

重要数据与结论

本文的实验结果强调了MDMs作为ARMs在大规模语言建模中的有前途的替代品。通过扩展分析和无监督CFG的支持,MDMs在关键任务中展现出了与ARMs相当甚至更优越的性能。此外,MDMs有效地解决了ARMs的固有局限性,如改善双向推理能力。

推荐阅读指数

4/5

对于对大型语言模型、扩散模型和自然语言处理感兴趣的研究人员和实践者来说,本文值得一读。

python 复制代码
'''
This file is inspired by the code provided by the author of https://arxiv.org/abs/2406.11473
'''
import torch
import re
from pathlib import Path
import random
import numpy as np
import torch.nn.functional as F
from datasets import Dataset
from lm_eval.__main__ import cli_evaluate
from lm_eval.api.instance import Instance
from lm_eval.api.model import LM
from lm_eval.api.registry import register_model
from tqdm import tqdm

from transformers import AutoTokenizer
from lit_gpt.diffmodel import TransEncoder, Config
from safetensors.torch import load_file


def set_seed(seed):
    torch.manual_seed(seed)
    random.seed(seed)
    np.random.seed(seed)

    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False


@register_model("mdlm")
class MDLMEvalHarness(LM):
    def __init__(
            self,
            model_name="tiny",
            ckpt_path=None,
            mask_id=32000,
            max_length=2048,
            batch_size=32,
            mc_num=1024,
            padding=False,
            nll_type='mc',
            greddy=False,
            cfg=0.,
            device="cuda",
    ):
        super().__init__()
        assert nll_type in ['mc', 'chain_rule']

        model_name = f'Diff_LLaMA_{model_name}M'
        config = Config.from_name(model_name)
        self.model = TransEncoder(config).to(device)

        self.model.load_state_dict(load_file(ckpt_path))
        self.model.eval()

        self.mask_id = mask_id
        self.tokenizer = AutoTokenizer.from_pretrained('TinyLlama/TinyLlama-1.1B-intermediate-step-1431k-3T')

        self.mc_num = mc_num
        self.batch_size = int(batch_size)
        assert mc_num % self.batch_size == 0
        self.sampling_eps = 0.
        self.max_length = max_length
        self.padding = padding
        self.nll_type = nll_type
        self.greddy = greddy

        self.cfg = cfg
        self.device = torch.device(device)

    def _forward_process(self, batch):
        b, l = batch.shape
        # sample from U[0, 1] following https://arxiv.org/pdf/2107.00630 I.1
        u0 = torch.rand(1, device=batch.device, dtype=torch.float32)
        indices = torch.arange(b, device=batch.device).float()
        t = (u0 + indices / b) % 1

        p_mask = (1 - self.sampling_eps) * t + self.sampling_eps

        p_mask = p_mask[:, None].repeat(1, l)

        mask_indices = torch.rand((b, l), device=batch.device) < p_mask
        noisy_batch = torch.where(mask_indices, self.mask_id, batch)

        return noisy_batch, p_mask

    @torch.no_grad()
    def get_logits(self, batch, prompt_index):
        '''
        prompt_index : 1D bool tensor, length=batch.shape[1]
        '''
        if self.cfg > 0.:
            assert len(prompt_index) == batch.shape[1]
            prompt_index = prompt_index.unsqueeze(0).repeat(batch.shape[0], 1)
            un_batch = batch.clone()
            un_batch[prompt_index] = self.mask_id
            batch = torch.cat([batch, un_batch])

        if self.padding:
            input = torch.full((batch.size(0), 2048), self.mask_id, device=self.device)
            input[:, :batch.shape[1]] = batch
        else:
            input = batch

        with torch.cuda.amp.autocast(dtype=torch.bfloat16):
            logits = self.model(input)

        if self.cfg > 0.:
            logits, un_logits = torch.chunk(logits, 2, dim=0)
            logits = un_logits + (self.cfg + 1) * (logits - un_logits)
        return logits[:, :batch.shape[1]]

    @torch.no_grad()
    def _eval_target_nll_ar(self, prefix, target):
        '''
        Utilize the chain rule to compute the likelihood
        We need to perform len(target) forward passes in parallel
        '''
        prefix, target = prefix.unsqueeze(0), target.unsqueeze(0) # 1*l1, 1*l2

        prompt_index = torch.arange(prefix.shape[1] + target.shape[1], device=self.device) < prefix.shape[1]
        perturbed_ = target.repeat(target.shape[1], 1).clone().contiguous() # l2*l2

        mask_index = torch.ones((perturbed_.shape[1], perturbed_.shape[1]), dtype=torch.bool)
        mask_index = torch.triu(mask_index)

        perturbed_[mask_index] = self.mask_id
        perturbed_seq = torch.cat([prefix.repeat(perturbed_.shape[0], 1), perturbed_], dim=-1)

        logits_ = []
        num = len(perturbed_seq) // self.batch_size if len(perturbed_seq) % self.batch_size == 0 else len(perturbed_seq) // self.batch_size + 1
        for i in range(num):
            end = (i + 1) * self.batch_size if (i + 1) * self.batch_size < len(perturbed_seq) else len(perturbed_seq)
            perturbed_seq_ = perturbed_seq[i * self.batch_size: end]
            perturbed_seq_ = perturbed_seq_.to(self.device)
            if len(perturbed_seq_.shape) == 1:
                perturbed_seq_ = perturbed_seq_.unsqueeze(0)
            logits = self.get_logits(perturbed_seq_, prompt_index)
            logits_.append(logits.cpu())
        logits = torch.cat(logits_, dim=0)

        temp_index = torch.ones((perturbed_.shape[1], perturbed_.shape[1]), dtype=torch.bool)
        temp_index = torch.triu(temp_index, diagonal=1)
        mask_index[temp_index] = False
        logits_index = torch.cat([torch.zeros((perturbed_.shape[1], prefix.shape[1]), dtype=torch.bool), mask_index], dim=-1)
        loss = F.cross_entropy(logits[logits_index], target[0], reduction='sum').cpu().float()
        return loss


    @torch.no_grad()
    def _eval_target_nll_mc(self, prefix, target):
        '''
        Employ Monte Carlo estimation to establish a lower bound of the log-likelihood
        '''
        seq = torch.concatenate([prefix, target])[None, :]
        seq = seq.repeat((self.batch_size, 1)).to(self.device)

        prompt_index = torch.arange(seq.shape[1], device=self.device) < len(prefix)

        loss_acc = []
        for _ in range(self.mc_num // self.batch_size):
            perturbed_seq = seq.clone()
            perturbed_seq_, p_mask = self._forward_process(seq)
            perturbed_seq[:, -len(target):] = perturbed_seq_[:, -len(target):]

            mask_indices = perturbed_seq == self.mask_id

            logits = self.get_logits(perturbed_seq, prompt_index)

            loss = F.cross_entropy(logits[mask_indices], seq[mask_indices], reduction='none') / p_mask[mask_indices]
            loss = loss.sum() / self.batch_size
            loss_acc.append(loss.cpu())

        return sum(loss_acc) / len(loss_acc)

    @torch.no_grad()
    def suffix_greedy_prediction(self, prefix, target):
        if not self.greddy:
            return False

        seq = torch.full((1, len(prefix) + len(target)), self.mask_id, device=self.device)
        prompt_index = torch.arange(seq.shape[1], device=self.device) < len(prefix)
        prefix, target = prefix.to(self.device), target.to(self.device)
        seq[0, :len(prefix)] = prefix

        for i in range(len(target)):
            mask_index = (seq == self.mask_id)
            logits = self.get_logits(seq, prompt_index)[mask_index]
            x0 = torch.argmax(logits, dim=-1)

            p = torch.softmax(logits.to(torch.float32), dim=-1)
            confidence = torch.gather(p, dim=-1, index=torch.unsqueeze(x0, -1)).squeeze(dim=-1)
            _, index = torch.sort(confidence, descending=True)
            x0[index[1:]] = self.mask_id
            seq[mask_index] = x0.clone()
        correct = target == seq[0, len(prefix):]
        correct = torch.all(correct)
        return correct


    def _encode_pair(self, context, continuation):
        n_spaces = len(context) - len(context.rstrip())
        if n_spaces > 0:
            continuation = context[-n_spaces:] + continuation
            context = context[:-n_spaces]

        whole_enc = self.tokenizer(context + continuation)["input_ids"]
        context_enc = self.tokenizer(context)["input_ids"]

        context_enc_len = len(context_enc)
        continuation_enc = whole_enc[context_enc_len:]

        return context_enc, continuation_enc

    def loglikelihood(self, requests: list[Instance]) -> list[tuple[float, bool]]:
        def _tokenize(e):
            prefix, target = self._encode_pair(e["prefix"], e["target"])
            return {
                "prefix_text": e["prefix"],
                "target_text": e["target"],
                "prefix": prefix,
                "target": target,
            }

        ds = []
        ds = [{"prefix": req.args[0], "target": req.args[1]} for req in requests]
        ds = Dataset.from_list(ds)
        ds = ds.map(_tokenize)
        ds = ds.with_format("torch")
        prompt_len = [len(x["prefix"]) + len(x["target"]) for x in ds]

        assert max(prompt_len) <= 2048

        out = []
        with torch.no_grad():
            for elem in tqdm(ds, desc="Computing likelihood..."):
                prefix = elem["prefix"]
                target = elem["target"]

                if self.nll_type == 'mc':
                    ll = -self._eval_target_nll_mc(prefix, target)
                elif self.nll_type == 'chain_rule':
                    ll = -self._eval_target_nll_ar(prefix, target)
                else:
                    raise NotImplementedError(self.nll_type)

                is_target_greedy_dec = self.suffix_greedy_prediction(prefix, target)

                out.append((ll, 1.0 if is_target_greedy_dec else 0.0))
        return out

    def loglikelihood_rolling(self, requests: list[Instance]):
        raise NotImplementedError

    def generate_until(self, context, max_length, stop, **generation_kwargs):
        raise NotImplementedError


if __name__ == "__main__":
    set_seed(1234)
    cli_evaluate()

后记

如果觉得我的博客对您有用,欢迎 打赏 支持!三连击 (点赞、收藏、关注和评论 ) 不迷路,我将持续为您带来计算机人工智能前沿技术(尤其是AI相关的大语言模型,深度学习和计算机视觉相关方向)最新学术论文及工程实践方面的内容分享,助力您更快更准更系统地了解 AI前沿技术

相关推荐
予枫的编程笔记2 小时前
Agent 到底是什么?从架构演进看 AI Agent 的工程定义
人工智能·agent·harness·agent的演进
Jerry3 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry5 小时前
LeetCode 459. 重复的子字符串
算法
成都渲染101云渲染66665 小时前
如何在3ds Max中实现更快、更高质量的渲染
前端·javascript·人工智能
十铭忘7 小时前
MOTIONGPT3:人类运动作为第二模态
人工智能
海石7 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石7 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
weigangwin8 小时前
采用 mem0 之前,先决定 Agent 到底允许记住什么
人工智能·opencv·ai·llm·memory·ai agent·mem0
木木学AI8 小时前
AI客服系统技术选型:Agentic架构与传统规则引擎的能力差异评估
人工智能·架构
hhzz8 小时前
Python大数据实战(十六):音乐推荐系统——基于协同过滤算法构建个性化歌单引擎
大数据·人工智能·python·数据挖掘·数据分析