跳至主要内容

精通低秩适配(LoRA):助力大型语言模型高效适配

在本指南中探索突破性的低秩适配(LoRA)技术。了解 LoRA 如何革新大型语言模型的微调方式。
· 10分钟 阅读

使用 AI 探索

LoRA: Low-Rank Adaptation of Large Language Models

LoRA:大型语言模型的低秩适配

随着大型语言模型(LLM)(如GPT、LLaMa、Claude 2等)的推出,机器学习与自然语言处理(NLP)领域取得了长足进步。这些模型在从文本生成到语言理解的诸多应用中展现出非凡能力。

然而,这些模型在实际部署与微调方面面临巨大挑战,主要源于其规模和复杂性。

这正是低秩适配(LoRA)大显身手之处,它为上述挑战提供了行之有效的解决方案。

本教程旨在从理论与实践两方面,帮助您理解 LoRA 是什么,以及如何从中获益。

背景

LoRA 的诞生可追溯至 2021 年初、GPT-3 发布之后。微软与 OpenAI 在合作中面临一个难题:如何让像 GPT-3 这样的大模型具备商业可行性。

他们发现,仅靠一次性提示(one-shot prompting)不足以在生产环境中获得最佳表现,尤其是在将自然语言翻译为代码等复杂任务上。由此,他们开始探索既具成本效益又高效的微调方法。

LoRA 的发明源于产品需求:在运行时实现大语言模型的快速、高效、低成本微调,以支持领域专用、高效任务切换或用户切换。

LoRA 研究论文由微软研究团队于 2021 年 10 月发表。

为何需要 LoRA?

在了解 LoRA 及其解决方案之前,让我们先厘清问题本身。

GPT-4、Claude 2、LLaMA 70b 等大型语言模型能力强大,但也非常通用且庞大。若要将这些模型用于医护、银行等特定领域,或用于将文本转换为代码等特定任务,我们需要对其进行微调。

微调是指在特定的小型数据集上训练预训练模型,使其在特定任务或领域上表现更佳。随着模型规模不断增大(例如 GPT-3 具有 1750 亿参数),全量微调(即重新训练所有模型参数)在时间、成本和资源上愈发不可行。

LoRA 是一种用于微调大模型的技术。

LoRA 的工作原理

从高层来看,LoRA 的工作方式如下:

它保持原始模型不变,并在模型的每一层添加一些体量很小且可训练的组件。这样可以显著减少可训练参数的数量,进而降低训练过程中的 GPU 显存需求——这也是微调或训练大模型时的另一大难题。

例如,全量微调 GPT-3 需要训练 1750 亿个参数。使用 LoRA 后,GPT-3 的可训练参数大约可减少 1 万倍,GPU 显存需求也可降低三倍。

归根结底,LoRA 解决了以下问题:

  1. 速度——更少的可训练参数意味着更快的训练速度
  2. 算力资源——更少的可训练参数意味着所需算力更低,使大模型微调在经济上更可行
  3. 内存效率——更少的可训练参数可缓存在内存中,无需进行低效的磁盘读取

低秩矩阵

在深入 LoRA 细节之前,让我们先理解低秩矩阵这一概念。

低秩矩阵源自数学中的线性代数。简单来说,矩阵的秩衡量了该矩阵所代表数据的“信息量”或“维度”。具体可分解如下:

  • 矩阵:
    矩阵是一个由数字构成的长方形数组。例如,3×3 矩阵有 3 行和 3 列。
  • 矩阵的秩
    矩阵的秩由其中线性无关的行或列的数量决定。线性无关意味着任一行(或列)都不能由其他行(或列)的线性组合得到。
    若所有行(或列)线性无关,则矩阵满秩。
    若某些行(或列)可由其他行(或列)组合得到,则矩阵为低秩。
  • 低秩矩阵:
    若一个矩阵的秩小于其在给定规模下的最大可能值,则该矩阵为低秩。例如,在 3×3 矩阵中,若秩小于 3,即为低秩矩阵。

示例:

考虑一个 3 × 3 矩阵:

image2.png

这里,第二行只是第一行的 2 倍,第三行是第一行的 3 倍。这意味着各行并非线性无关。该矩阵的秩为 1(因为只有第一行是独立的),小于 3×3 矩阵的最大秩 3。因此,这是一个低秩矩阵。

低秩矩阵在诸多应用中具有重要意义,例如数据压缩:降低矩阵秩有助于在尽可能保留信息的同时压缩数据。

矩阵的秩对行与列同样适用。关键在于,无论基于行还是列来计算,矩阵的秩都是相同的。这源于线性代数中的一个基本性质——秩-零化度定理(Rank-Nullity Theorem)。

通俗地说,该定理表示矩阵的行空间(由各行张成的空间)与列空间(由各列张成的空间)具有相同维度,而这个共同的维度即为矩阵的秩。

因此,在上述 3 × 3 矩阵的例子中,秩为 1,意味着只有一行线性无关,同样也只有一列线性无关。

什么是 LoRA?

简单来说,LoRA 利用低秩矩阵的思想,使模型训练过程极其高效且快速。

大型模型拥有大量参数。例如,GPT-3 有 1750 亿个参数。这些参数就是存储在矩阵中的数字,存储它们需要极大的空间。

全量微调意味着要训练所有参数,这将需要海量算力资源,对于 GPT 这类规模的模型,成本轻易就可达数百万美元。

与需要调整整个模型的传统微调不同,LoRA 专注于修改更小的一组参数(低秩矩阵),从而降低计算与内存开销。

LoRA 基于对大型模型本质上具有低维结构的理解。通过利用低秩矩阵,LoRA 能够高效地对这些模型进行适配。其核心思想在于:模型的显著变化可以用更少的参数来表示,从而让适配过程更高效。

Fine-Tuning LLMs: LoRA or Full-Parameter? An in-depth Analysis with Llama 2

来源:微调 LLM:LoRA 还是全量参数?基于 Llama 2 的深入分析

那么它具体如何运作?

首先,使用前述的低秩分解技术,将大型权重矩阵分解为更小的矩阵。这会大幅减少可训练参数的数量。以 GPT-3 为例,可训练参数可减少 1 万倍。也就是说,应用 LoRA 后,不再需要训练 1750 亿参数,而只需训练 1750 万参数。

我们不会更改预训练模型的任何参数,而只训练低秩矩阵。由于参数更少,这一过程会快得多。

权重是可加的。这意味着在推理阶段,只需将低秩矩阵的权重与预训练权重相加即可,不会引入额外的时延。低秩矩阵本身也很小,因此易于在不同任务和不同用户之间装载与卸载。

LoRA 的优势

使用 LoRA 进行微调有多重优势:

1. 训练与部署高效

LoRA 降低了计算负担,使模型能够更快适配。由于需要的可训练参数更少,即便在算力较弱的硬件上也能对大模型进行微调。

2. 保持模型质量与推理速度

尽管参数数量减少,LoRA 仍能保持原始模型的质量与推理速度。

3. 检查点体积显著降低

LoRA 能显著缩小模型检查点的大小。例如,在 GPT-3 上,检查点大小可从 1 TB 降至仅 25 MB。

4. 无额外推理时延

LoRA 在推理阶段不会引入额外时延。低秩矩阵仅用于训练,推理时与原始参数合并,因此不会变慢。这也使运行时的快速模型切换成为可能,而不增加推理时延。

5. 通用性强

LoRA 适用于任何使用矩阵乘法的模型(如支持向量机),可广泛应用于许多其他场景。事实上,LoRA 在 Stable Diffusion 等图像模型中被广泛用于将风格注入到大型图像模型中。

Stable Diffusion 中的 LoRA

LoRA 技术也在 Stable Diffusion 等图像模型中被广泛采用。

思路与语言模型基本一致。与其对 Stable Diffusion 等大型模型进行全量微调,不如仅在小数据集上训练低秩矩阵。

在语言模型中,目标是领域专用;而在图像模型中,最典型的用途是生成图像时采用某种风格或保持角色一致性。

这些低秩矩阵被称为适配器(adapter),体量很小。互联网上有成千上万的适配器可供下载,您可以将它们加载到基础的 Stable Diffusion 模型之上,生成特定风格的图像。

LoRA 在 Stable Diffusion 中的常见用途包括:

  • 风格专化——如二次元风格、油画风格等
  • 角色专化——稳定生成马里奥、海绵宝宝等角色形象
  • 质量提升——更高细节、更佳人脸等

您可以组合多个 LoRA,以获得兼具多种专化效果的输出。

image1.png

Stable Diffusion 模型的不同适配器(图片来源)

如果您想学习如何用个人照片成功微调 Stable Diffusion XL,请查看 Datacamp 上的使用 DreamBooth 和 LoRA 微调 Stable Diffusion XL一文。

将 LoRA 与 Prefix-Tuning 结合

Prefix tuning 是一种轻量方法,通过优化称为“前缀”的连续向量,并将其添加到每个 Transformer 层的输入中。模型以去前缀的方式训练,只关注这些向量。

前缀微调的优势:

  • 每个任务只需存储小型前缀向量,而非微调后模型的完整副本
  • 便于任务切换与个性化
  • 与全量微调相比表现良好,尤其是在小数据场景中
  • 计算成本更低,因为训练期间只更新前缀

LoRA 与前缀微调可在 PEFT(参数高效微调)框架中结合使用:

  • LoRA 降低总体参数量,而前缀微调提供任务级控制
  • 二者配合可在最少数据与算力下完成专用微调
  • 非常适合使用有限领域数据对大型 LLM 进行领域适配
  • 这种模块化微调为算力受限的用户释放大型 LLM 的全部潜力

使用 Python 中的 Loralib 库实现 LoRA 的示例

要实现 LoRA,您可以使用微软的 Loralib 库。安装方式:

pip install loralib

采用 LoRA 后,您平常训练神经网络的方式基本无需改变。

# ===== Before =====
# layer = nn.Linear(in_features, out_features)

# ===== After ======
import loralib as lora
# Add a pair of low-rank adaptation matrices with rank r=16
layer = lora.Linear(in_features, out_features, r=16)

在训练循环开始前,您只需添加:

import loralib as lora

model = YourNeuralNetwork()

# This sets requires_grad to False for all parameters
lora.mark_only_lora_as_trainable(model)

# Training loop
for batch in dataloader:
   ...

保存检查点时,您可以只生成包含 LoRA 参数的 state_dic。

# ===== Before =====
# torch.save(model.state_dict(), checkpoint_path)

# ===== After =====
torch.save(lora.lora_state_dict(model), checkpoint_path)

如果您对神经网络了解不多,也不必担心。请查阅如何用 PyTorch 训练 LLM一文,从环境搭建到最终实现,全面掌握使用 PyTorch 训练大型语言模型的流程。

致谢:代码示例转载自 Microsoft/LoRA GitHub。

结语

LoRA 成为应对大型模型规模与复杂性所带来重大挑战的不可或缺技术。

通过利用低秩矩阵,LoRA 提供了更高效且具成本效益的模型适配途径,显著减少可训练参数与 GPU 显存需求,从而加速训练并提升内存效率。

LoRA 的应用超越语言模型,也能用于 Stable Diffusion 等图像模型,以便在图像生成中实现风格专化与角色一致性。

如果您对这些技术能构建什么充满好奇,欢迎阅读我们的指南:5 个可用生成式 AI 模型构建的项目以进一步了解。

Moez Ali

作者

Moez Ali

数据科学家,PyCaret 的创始人兼作者

主题