人工智能

大型语言模型微调的完整指南

mm

大型语言模型(LLM)如GPT-4、LaMDA、PaLM等,以其在广泛的主题上理解和生成类似人类文本的卓越能力,引起了人们的关注。这些模型是在包含数十亿个单词的互联网、书籍和其他来源的巨大数据集上进行预训练的。

这种预训练阶段使得模型具备了广泛的语言知识,包括语言、主题、推理能力,甚至某些存在于训练数据中的偏见。然而,尽管这些预训练的LLM具有令人难以置信的广度,但它们缺乏特定领域或任务的专业知识。

这就是微调的用处——将预训练的LLM适应于特定的应用或用例。通过在较小的任务特定数据集上进一步训练模型,我们可以调整其能力以符合该领域的细微差别和要求。

微调类似于将广泛知识的普通专家转变为特定领域的专家。在本指南中,我们将探讨LLM微调的什么、为什么和如何。

大型语言模型微调

大型语言模型微调

什么是微调?

微调的核心是将大型预训练模型更新其参数,使用第二个训练阶段的数据集,针对目标任务或领域进行定制。这种方法使得模型能够学习和内化特定领域的细微差别、模式和目标。

预训练捕获了广泛的语言理解,从巨大和多样化的文本语料库中获得,而微调则使得这种一般能力变得专业化。它类似于将一个文艺复兴人转变为行业专家。

预训练模型的权重,编码其一般知识,作为微调过程的起点或初始化。然后,模型在任务特定数据集上进行进一步训练,优化整个模型以适应该数据分布。

通过将模型暴露在这种特定数据分布上,并相应地调整模型参数,我们可以使LLM更加准确和有效地适应目标用例,同时仍然受益于广泛的预训练能力作为基础。

为什么要微调LLM?

有几个关键原因说明为什么您可能想要微调一个大型语言模型:

  1. 领域定制:每个领域都有其自己的语言惯例、术语和背景。微调允许您将一般模型定制为适应特定领域的语言和需求。
  2. 任务专用化:LLM可以被微调为执行各种自然语言处理任务,如文本摘要、机器翻译、问答等。这种专用化提高了模型在目标任务上的性能。
  3. 数据合规性:高度监管的行业如医疗和金融有严格的数据隐私要求。微调允许在保护敏感信息的同时训练LLM使用特定组织的数据。
  4. 有限标记数据:从头开始训练模型需要大量标记数据,这可能很难获得。微调允许通过利用预训练模型的能力来实现强大的任务性能,即使只有有限的监督示例。
  5. 模型更新:随着新数据的出现,微调可以进一步更新模型以纳入最新的知识和能力。
  6. 缓解偏见:LLM可以从广泛的预训练数据中学习社会偏见。微调可以通过在经过策划的数据集上进行训练来减少和纠正这些不良偏见。

本质上,微调弥合了一般模型和特定应用之间的差距。它增强了模型输出的准确性、安全性和相关性,以适应目标用例。

大型语言模型微调

大型语言模型微调

提供的图表概述了实施和利用大型语言模型(LLM)的过程,特别是针对企业应用。最初,一个预训练模型如T5被输入结构化和非结构化的公司数据,这些数据可能以各种格式出现,例如CSV或JSON。这些数据经过监督、无监督或转移微调过程,增强了模型对公司特定需求的相关性。

一旦模型使用公司数据进行微调,其权重就会相应地更新。训练好的模型然后迭代通过进一步的训练周期,持续改进其响应以适应新出现的公司数据。该过程是迭代和动态的,模型学习和重新训练以适应不断变化的数据模式。

训练好的模型的输出——代表单词的标记和嵌入——然后被部署用于各种企业应用。这些应用可以从聊天机器人到医疗保健等领域,每个领域都需要模型理解和响应特定行业的查询。在金融领域,应用包括欺诈检测和威胁分析;在医疗保健领域,模型可以协助患者查询和诊断。

训练好的模型处理和响应新公司数据的能力确保了其实用性得到维持和提高。因此,企业用户可以通过应用程序与模型交互,提出问题并获得反映模型在领域特定数据上训练和微调的信息丰富的响应。

这种基础设施支持广泛的企业应用,展示了LLM在企业背景下被适当实施和维护时的多功能性和适应性。

微调方法

大型语言模型微调有两种主要策略:

1)全模型微调

在全微调方法中,预训练模型的所有参数(权重和偏差)在第二个训练阶段都被更新。模型被暴露在任务特定标记数据集上,标准训练过程优化整个模型以适应该数据分布。

这种方法使得模型能够进行更全面的调整和适应目标任务或领域。然而,全微调有一些缺点:

  • 它需要大量的计算资源和时间来训练,类似于预训练阶段。
  • 存储需求很高,因为您需要为每个任务维护一个单独的微调模型副本。
  • 存在“灾难性遗忘”的风险,即微调会导致模型丢失一些在预训练期间学习的通用能力。

尽管有这些限制,全微调仍然是一种强大且广泛使用的技术,当资源允许且目标任务明显偏离一般语言时。

2)高效微调方法

为了克服全微调的计算挑战,研究人员开发了高效的策略,只更新模型参数的较小子集。这些参数高效的技术在专业化和降低资源需求之间取得了平衡。

一些流行的高效微调方法包括:

前缀微调:这里,引入了一组任务特定的向量或“前缀”,并训练它们来条件化预训练模型的注意力以适应目标任务。只有这些前缀在微调期间被更新。

LoRA(低秩适应)LoRA 在预训练模型的每个层中注入可训练的低秩矩阵。这些小秩调整有助于使模型专业化,而无需更新所有参数。

当然,我可以提供有关LoRA(低秩适应)的详细解释,包括数学公式和代码示例。LoRA是一种流行的参数高效微调(PEFT)技术,在大型语言模型(LLM)适应领域获得了显著关注。

什么是LoRA?

LoRA是一种微调方法,它向预训练LLM引入少量可训练参数,使其能够高效地适应下游任务,同时保留大部分原始模型的知识。与其微调LLM的所有参数,LoRA将任务特定的低秩矩阵注入模型的层中,从而在微调过程中实现显著的计算和内存节省。

数学公式

LoRA(低秩适应)是一种大型语言模型(LLM)微调方法,它向预训练模型的权重矩阵中引入低秩更新。对于权重矩阵 0∈, LoRA添加一个低秩矩阵 , 其中 , 其中 是秩。这种方法显著减少了可训练参数的数量,使得模型能够高效地适应下游任务,并且只需要最小的计算资源。更新的权重矩阵由 给出。

这种低秩更新可以被解释为通过添加低秩矩阵 来修改原始权重矩阵 。LoRA的关键优势在于,相比于更新所有 参数,只需要优化 参数中的 ,从而显著减少了可训练参数的数量。

以下是使用 peft 库将LoRA应用于预训练LLM进行文本分类的Python示例:

</div>
<div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color="">from</span> transformers <span class="token" data-darkreader-inline-color="">import</span> AutoModelForSequenceClassification
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color="">from</span> peft <span class="token" data-darkreader-inline-color="">import</span> get_peft_model<span class="token" data-darkreader-inline-color="">,</span> LoraConfig<span class="token" data-darkreader-inline-color="">,</span> TaskType
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># 加载预训练模型</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">model <span class="token" data-darkreader-inline-color="">=</span> AutoModelForSequenceClassification<span class="token" data-darkreader-inline-color="">.</span>from_pretrained<span class="token" data-darkreader-inline-color="">(</span><span class="token" data-darkreader-inline-color="">"bert-base-uncased"</span><span class="token" data-darkreader-inline-color="">,</span> num_labels<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">2</span><span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># 定义LoRA配置</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">peft_config <span class="token" data-darkreader-inline-color="">=</span> LoraConfig<span class="token" data-darkreader-inline-color="">(</span>task_type<span class="token" data-darkreader-inline-color="">=</span>TaskType<span class="token" data-darkreader-inline-color="">.</span>SEQ_CLS<span class="token" data-darkreader-inline-color="">, </span>r<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">8</span><span class="token" data-darkreader-inline-color="">,</span> <span class="token" data-darkreader-inline-color=""># 低秩更新的秩</span>
lora_alpha<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">16</span><span class="token" data-darkreader-inline-color="">,</span></code><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># 低秩更新的缩放因子</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""> target_modules<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">[</span><span class="token" data-darkreader-inline-color="">"q_lin"</span><span class="token" data-darkreader-inline-color="">,</span> <span class="token" data-darkreader-inline-color="">"v_lin"</span><span class="token" data-darkreader-inline-color="">]</span><span class="token" data-darkreader-inline-color="">,</span> <span class="token" data-darkreader-inline-color=""># 将LoRA应用于查询和值层</span>
<span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># 创建LoRA启用的模型</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">model <span class="token" data-darkreader-inline-color="">=</span> get_peft_model<span class="token" data-darkreader-inline-color="">(</span>model<span class="token" data-darkreader-inline-color="">,</span> peft_config<span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># 使用LoRA微调模型</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># ... (训练代码省略)</span></code></div>
</div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">

在这个例子中,我们加载一个预训练的BERT模型用于序列分类,并定义一个LoRA配置。参数 r 指定低秩更新的秩,lora_alpha 是更新的缩放因子。参数 target_modules 表示哪些层应该接收低秩更新。创建LoRA启用的模型后,我们可以继续使用标准训练过程进行微调。

适配层:与LoRA类似,但不是低秩更新,而是插入预训练模型的每个变换器块中的一些薄“适配”层。只有这些新紧凑层的参数被训练。

提示微调:这种方法完全冻结预训练模型。相反,引入可训练的“提示”嵌入作为输入来激活模型的预训练知识以适应目标任务。

这些高效方法可以实现高达100倍的计算减少,与全微调相比,同时仍然实现了许多任务的竞争性性能。它们还减少了存储需求,避免了全模型复制。

然而,对于与一般语言或需要更全面的专业化大相径庭的任务,它们的性能可能会落后于全微调。

微调过程

无论微调策略如何,专门化LLM的过程都遵循一个通用的框架:

  1. 数据准备:您需要获取或创建一个标记数据集,该数据集将输入(提示)映射到输出,以适应您的目标任务。对于文本生成任务,如摘要,这将是输入文本到摘要输出对。
  2. 数据拆分:按照最佳实践,将您的标记数据集拆分为训练、验证和测试集。这将数据分开用于模型训练、超参数调优和最终评估。
  3. 超参数调优:参数如学习率、批大小和训练计划需要针对您的数据进行调优。这通常涉及一个小的验证集。
  4. 模型训练:使用调优的超参数,在整个训练集上运行微调优化过程,直到模型在验证集上的性能停止改善(早期停止)。
  5. 评估:评估微调模型在保留的测试集上的性能,理想情况下,测试集应包括真实世界的示例,以适应目标用例,以估计真实世界的有效性。
  6. 部署和监控:一旦满意,微调模型可以部署以对新输入进行推理。监控其性能和准确性随时间的变化对于概念漂移至关重要。

虽然这概述了总体过程,但许多细微差别会影响特定LLM或任务的微调成功。策略,如课程学习、多任务微调和少样本提示,可以进一步提高性能。

此外,高效微调方法需要额外的考虑。例如,LoRA需要通过组合层条件预训练模型输出的技术。提示微调需要精心设计的提示来激活正确的行为。

高级微调:融入人类反馈

虽然使用标记数据集的标准监督微调有效,但一个令人兴奋的前沿领域是直接使用人类偏好和反馈来训练LLM。这种人机交互方法利用了强化学习的技术:

PPO(近端策略优化):这里,LLM被视为强化学习代理,其输出被视为“动作”。一个奖励模型被训练来预测人类评分或质量评分用于这些输出。PPO然后优化LLM以生成最大化奖励模型评分的输出。

RLHF(从人类反馈中学习强化学习):这种方法扩展了PPO,通过直接将人类反馈纳入学习过程。与固定奖励模型不同,奖励来自迭代的人类评估,用于LLM的输出,在微调过程中进行。

虽然计算密集,但这些方法允许根据人类评估的期望特征来塑造LLM的行为,而超出了静态数据集的范围。

像Anthropic这样的公司使用RLHF使他们的语言模型,如Claude,具有改进的真实性、伦理和安全意识,而不仅仅是任务能力。

潜在风险和局限性

虽然微调LLM非常强大,但也存在需要谨慎管理的风险:

偏见放大:如果微调数据包含社会偏见,模型可能会放大这些不良偏见。策划代表性和去偏差的数据集至关重要。

事实漂移:即使在高质量数据上进行微调,语言模型也可能“编造”不正确的事实或输出不一致的训练示例,尤其是在长对话或提示中。事实检索方法可能是必要的。

可扩展性挑战:像GPT-3这样的巨型模型的全微调需要巨大的计算资源,这对于许多组织来说可能不可行。高效微调部分缓解了这一问题,但有权衡。

灾难性遗忘:在全微调过程中,模型可能会经历灾难性遗忘,即丢失在预训练期间学习的一些通用能力。多任务学习可能是必要的。

知识产权和隐私风险:用于微调的专有数据可能会泄漏到公开发布的语言模型输出中,带来风险。差异隐私和信息危害缓解技术是活跃的研究领域。

总体而言,虽然微调非常有用,但它是一个细致的过程,需要在数据质量、身份考虑、风险缓解和基于用例要求的性能效率权衡之间取得平衡。

未来:语言模型定制

展望未来,微调和模型适应技术的进步对于解锁大型语言模型在各个应用和领域的全部潜力至关重要。

更高效的方法可以使更大的模型(如PaLM)在有限的资源下进行微调,从而使更多人能够使用。自动化数据集创建管道和提示工程可以简化专业化过程。

从原始数据中无需标签的自监督微调技术可能会开辟新的前沿。组合方法可以将针对不同任务或数据训练的微调子模型组合起来,允许按需构建高度定制的模型。

最终,随着LLM变得更加普遍,将其无缝地定制和专业化以适应每一个可想象的用例将至关重要。微调和相关模型适应策略是实现大型语言模型作为灵活、安全、强大的AI助手的愿景的关键步骤,该助手可以增强人类在每个领域和事业中的能力。

我已经沉浸在了令人着迷的机器学习和深度学习世界中五年了。我的热情和专业知识让我为超过50个不同的软件工程项目做出了贡献,特别关注AI/ML。我的持续的好奇心也让我对自然语言处理产生了兴趣,这是一个我渴望进一步探索的领域。