第 2 课
← 返回系列列表

高效微调方法

Finetuning LLMs — 大模型微调

LoRA、Adapter、Prefix Tuning 等参数高效微调技术。

高效微调方法

课程简介

LoRA、Adapter、Prefix Tuning 等参数高效微调技术。

🎬 本课程视频:Finetuning LLMs — 大模型微调


参数高效微调:LoRA、Adapter 与 QLoRA

一、全量微调的挑战

全量微调(Full Fine-tuning)需要更新模型的所有参数。对于一个 70B 参数的模型,即使只使用 16 位精度,也需要约 140GB 的显存来加载模型参数,加上优化器状态和梯度,总显存需求超过 300GB。这需要多张 A100 或 H100 显卡,成本极高。

二、LoRA(Low-Rank Adaptation)

2.1 核心思想

LoRA 是目前最流行的参数高效微调方法。它的核心洞察是:预训练模型具有较低的「内在维度」——也就是说,模型适应新任务时所需的参数变化可以用一个低秩矩阵来近似

2.2 工作原理

LoRA 冻结原始模型的全部权重,在注意力层的权重矩阵旁边插入两个低秩矩阵 A 和 B 进行训练。

原始模型权重 W(冻结):
W ∈ ℝ^(d×k)

LoRA 低秩分解:
原始更新 ΔW = W_new - W(全量微调需要学习 d×k 个参数)

LoRA 近似 ΔW = BA(学习 B∈ℝ^(d×r) 和 A∈ℝ^(r×k) 共 (d+k)×r 个参数)
其中 r << min(d, k)

推理时,LoRA 的输出与原始权重输出相加:

h = Wx + BAx

2.3 关键参数:秩(Rank)

秩 r 是 LoRA 的核心超参数,控制着可训练参数的数量和模型的表达能力。

r 值 可训练参数量 表现力 推荐场景
1-4 极少 有限 简单任务、资源受限
8-16 适中 良好 大多数任务
32-64 较多 接近全量 复杂任务、追求最佳效果

Andrew Ng 推荐:大多数任务从 r=16 开始,效果不够再增加到 r=32 或 64

2.4 实现代码

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM

# 加载模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B")

# LoRA 配置
lora_config = LoraConfig(
    r=16,                    # 秩
    lora_alpha=32,           # 缩放因子(通常设为 r 的 2 倍)
    target_modules=[         # 应用 LoRA 的模块
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj"
    ],
    lora_dropout=0.05,       # dropout 率
    bias="none",             # 是否训练偏置
    task_type="CAUSAL_LM"    # 任务类型
)

# 应用 LoRA
peft_model = get_peft_model(model, lora_config)

# 检查可训练参数数量
trainable_params = sum(p.numel() for p in peft_model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in peft_model.parameters())
print(f"可训练参数:{trainable_params}/{total_params} ({100 * trainable_params / total_params:.2f}%)")

# 训练方式与全量微调相同
trainer = Trainer(
    model=peft_model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset
)
trainer.train()

# 保存 LoRA 权重(只需保存少量参数)
peft_model.save_pretrained("./lora_weights")

2.5 LoRA 的数学分析

为什么 LoRA 有效?考虑一个预训练好的权重矩阵 W₀。全量微调需要学习更新量 ΔW,使得:

W = W₀ + ΔW

LoRA 假设 ΔW 具有低秩特性,即:

ΔW = BA, 其中 B ∈ ℝ^(d×r), A ∈ ℝ^(r×k), r << min(d,k)

对于一个 4096×4096 的权重矩阵(常见于 Transformer),全量微调需要学习约 1600 万个参数。使用 LoRA(r=16)只需要学习约 13 万个参数——减少了约 120 倍。

三、其他 PEFT 方法

3.1 Adapter

在 Transformer 的每一层中插入小型前馈网络。

原始层:LayerNorm → Attention → LayerNorm → FFN
Adapter 层:LayerNorm → Attention → LayerNorm → FFN → Adapter → Residual

Adapter 的参数量通常设为主网络的 1-5%。

3.2 Prefix Tuning

在注意力机制的 Key 和 Value 前添加可学习的虚拟 Token。

# Prefix Tuning 在 attention 前加虚拟 token
prefix_length = 10  # 虚拟 token 数量
prefix_embedding = nn.Parameter(torch.randn(prefix_length, hidden_dim))

3.3 Prompt Tuning

在模型的输入嵌入前添加 soft prompt(可学习的嵌入向量)。

[soft_prompt_1] [soft_prompt_2] ... [soft_prompt_k] [原始输入]

3.4 方法对比

方法 参数效率 推理开销 实现复杂度 效果
LoRA 优秀
Adapter 略增 良好
Prefix Tuning 略增 中等
Prompt Tuning 最高 中等(依赖任务)

四、QLoRA:量化 LoRA

4.1 核心思想

QLoRA 在 LoRA 的基础上进一步引入了 4-bit 量化,使微调超大模型成为可能。

4.2 工作原理

  1. 4-bit NormalFloat 量化:将模型权重量化为 4-bit,显存需求降低约 4 倍
  2. 双重量化:对量化常数再进行一次量化,进一步节省显存
  3. 分页优化器:利用 CPU 内存作为显存的扩展,处理偶尔的显存溢出
  4. LoRA 训练:在量化的模型上应用 LoRA

4.3 实现

from transformers import BitsAndBytesConfig
import torch

# 4-bit 量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",        # NormalFloat 4-bit
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True     # 双重量化
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3-70B",
    quantization_config=bnb_config,
    device_map="auto"
)

# 应用 LoRA(配置不变)
peft_model = get_peft_model(model, lora_config)

# 训练(注意:量化模型不能训练量化参数,只能训练 LoRA 参数)

4.4 QLoRA 的显存优势

配置 7B 模型 13B 模型 70B 模型
全量微调(16-bit) 56GB 104GB 560GB
LoRA(16-bit) 28GB 52GB 280GB
QLoRA(4-bit) 7GB 13GB 70GB

单张 RTX 4090(24GB 显存)即可使用 QLoRA 微调 70B 模型。

五、PEFT 的最佳实践

5.1 如何选择 PEFT 方法?

  1. 首选 LoRA:通用性最强,效果稳定,推理无额外开销
  2. 需要极致参数效率:QLoRA(显存受限时)
  3. 自然语言理解任务:Adapter 有时表现更好
  4. 文本生成任务:LoRA 是主流选择

5.2 LoRA 配置建议

5.3 多任务 LoRA

可以为不同任务训练不同的 LoRA 适配器,推理时根据需要加载:

任务 A 的 LoRA 权重 → path/to/lora_A
任务 B 的 LoRA 权重 → path/to/lora_B

推理时:
加载基础模型 + 任务 A 的 LoRA → 执行任务 A
加载基础模型 + 任务 B 的 LoRA → 执行任务 B

六、总结

参数高效微调(PEFT)技术大幅降低了微调大语言模型的门槛。LoRA 通过低秩分解实现与全量微调接近的效果,同时只更新极少量参数。QLoRA 通过 4-bit 量化进一步将显存需求降低 4 倍,单张消费级显卡即可微调 70B 模型。选择合适的 PEFT 方法和配置,可以在有限资源下实现高质量的领域适配。

七、LoRA 的优势与局限

7.1 LoRA 的主要优势

7.2 LoRA 的局限

八、QLoRA:量化 LoRA

8.1 QLoRA 的核心思想

QLoRA = 4-bit 量化 + LoRA。将预训练模型量化为 4-bit(NormalFloat4),然后在这个量化模型上应用 LoRA 微调。

8.2 QLoRA 的显存节省

方法 7B 模型 13B 模型 70B 模型
全量微调 56GB 104GB 560GB
LoRA 14GB 26GB 140GB
QLoRA 4GB 8GB 48GB

8.3 QLoRA 的实现

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config
)

九、总结

关键要点回顾:
- PEFT 是大模型微调的实用方案
- LoRA 通过低秩矩阵分解大幅减少可训练参数
- Adapter 在 Transformer 层中插入小型神经网络
- Prefix Tuning 在输入前缀中学习连续向量
- QLoRA 结合 4-bit 量化进一步降低硬件门槛

七、LoRA 的优势与局限

7.1 LoRA 的主要优势

7.2 LoRA 的局限

八、QLoRA:量化 LoRA

8.1 QLoRA 的核心思想

QLoRA = 4-bit 量化 + LoRA。将预训练模型量化为 4-bit(NormalFloat4),然后在这个量化模型上应用 LoRA 微调。

8.2 QLoRA 的显存节省

方法 7B 模型 13B 模型 70B 模型
全量微调 56GB 104GB 560GB
LoRA 14GB 26GB 140GB
QLoRA 4GB 8GB 48GB

8.3 QLoRA 的实现

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config
)

九、总结

关键要点回顾:
- PEFT 是大模型微调的实用方案
- LoRA 通过低秩矩阵分解大幅减少可训练参数
- Adapter 在 Transformer 层中插入小型神经网络
- Prefix Tuning 在输入前缀中学习连续向量
- QLoRA 结合 4-bit 量化进一步降低硬件门槛

七、LoRA 的优势与局限

7.1 LoRA 的主要优势

7.2 LoRA 的局限

八、QLoRA:量化 LoRA

8.1 QLoRA 的核心思想

QLoRA = 4-bit 量化 + LoRA。将预训练模型量化为 4-bit(NormalFloat4),然后在这个量化模型上应用 LoRA 微调。

8.2 QLoRA 的显存节省

方法 7B 模型 13B 模型 70B 模型
全量微调 56GB 104GB 560GB
LoRA 14GB 26GB 140GB
QLoRA 4GB 8GB 48GB

8.3 QLoRA 的实现

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config
)

九、总结

关键要点回顾:
- PEFT 是大模型微调的实用方案
- LoRA 通过低秩矩阵分解大幅减少可训练参数
- Adapter 在 Transformer 层中插入小型神经网络
- Prefix Tuning 在输入前缀中学习连续向量
- QLoRA 结合 4-bit 量化进一步降低硬件门槛

延伸阅读

← 微调基础与策略 微调评估与部署 →