LoRA 微调入门:让大模型"特化"成你需要的样子
不用重训整个 70B 模型,只调几百万个参数,一张消费级显卡就能微调 LLM。
L4-03 RAG 解决了”让 LLM 知道你的数据”。 但有些问题 RAG 解决不了——你想改的不是”知识”,是”行为”:
- 让模型按你公司的写作风格输出
- 让模型说某种行话(法律 / 医学 / 行业)
- 让模型输出特定格式(JSON / XML / 自定义结构)
- 让模型模仿某个人物说话
这时候需要微调(Fine-tuning)。
全参数微调的问题
理论上,微调 LLM 就是”在你的数据上继续跑梯度下降”。但有个问题——
全参数微调一个 70B 模型:
- 显存:需要 ~700GB(模型 + 优化器状态 + 梯度)
- 硬件:至少 8 张 A100/H100
- 时间:几小时到几天
- 成本:每次几千到几万美元
- 风险:训坏了模型整体能力下降(“灾难性遗忘”)
绝大多数人和公司根本玩不起。
LoRA 的洞察
2021 年,微软研究院发了一篇论文 LoRA: Low-Rank Adaptation of Large Language Models。它的关键洞察:
微调 LLM 时,参数的变化矩阵 是”低秩”的。
人话翻译:
模型本来有个权重矩阵 (比如 4096 × 4096,约 1700 万参数)。微调后变成 。
LoRA 假设: 这个变化矩阵不需要 1700 万参数,可以用两个小矩阵的乘积近似:
- 是 4096 × r(r=8 时只有 32K 参数)
- 是 r × 4096(同样 32K)
- 加起来 64K 参数——少了 250 倍
叫”秩”(rank),通常取 4、8、16、32。越大效果越好但参数越多。
训练过程
只训 ,冻结原始 :
原模型: Forward:
W (4096×4096, 冻结) y = (W + A·B) · x
+
A (4096×r, 可训) ← 训这个
B (r×4096, 可训) ← 训这个
只更新 的梯度——梯度计算量减少 99%+。
显存对比
| 方案 | 显存(7B 模型) |
|---|---|
| 全参数微调 | ~80GB(多卡) |
| LoRA (r=8) | ~14GB(单卡) |
| LoRA + 4-bit 量化(QLoRA) | ~6GB(消费级显卡) |
这是个革命——你的 RTX 3090 / 4090 就能微调 7B 模型。
用 PEFT 库做一次
HuggingFace 的 PEFT(Parameter-Efficient Fine-Tuning)库让 LoRA 简单到一段代码:
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer
# 1. 加载基础模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B")
# 2. 配置 LoRA
lora_config = LoraConfig(
r=8, # 秩
lora_alpha=32, # 缩放系数(实际更新 = α/r × A·B)
target_modules=["q_proj", "v_proj"], # 只调 attention 的 Q、V
lora_dropout=0.1,
bias="none",
task_type="CAUSAL_LM"
)
# 3. 给模型穿上 LoRA "外套"
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 4,194,304 || all params: 8,030,261,248 || trainable%: 0.05
# ↑ 实际要训的
注意 trainable%: 0.05——只调了万分之五的参数。
准备训练数据
LoRA 训练数据格式(指令-回答对):
data = [
{
"instruction": "用法律严谨风格回答:合同失效有哪些情形?",
"response": "依据《民法典》第一百四十四条至一百五十三条,合同失效情形包括:..."
},
{
"instruction": "用法律严谨风格回答:什么是不可抗力?",
"response": "不可抗力指当事人在签约时不能预见..."
},
# ... 几百到几千条
]
经验:
- 几百条:能学会”风格”(语气、格式)
- 几千条:能学会”领域知识”(行业术语)
- 几万条:能学会”具体技能”(多轮对话、代码生成)
数据质量 >>> 数据数量。100 条高质量 比 1000 条低质量 强。
训练循环
用 HuggingFace Trainer:
from transformers import TrainingArguments, Trainer
from datasets import Dataset
# 转格式
dataset = Dataset.from_list([
{"text": f"Instruction: {d['instruction']}\nResponse: {d['response']}"}
for d in data
])
def tokenize(batch):
return tokenizer(batch['text'], padding=True, truncation=True, max_length=512)
dataset = dataset.map(tokenize, batched=True)
# 训练
training_args = TrainingArguments(
output_dir="./lora_law_model",
per_device_train_batch_size=4,
num_train_epochs=3,
learning_rate=2e-4,
fp16=True,
save_steps=500,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset,
)
trainer.train()
# 保存(只保存 LoRA 部分——通常 <100MB)
model.save_pretrained("./my_lora_adapter")
这就是 LoRA 训练的全部——50 行代码,1-3 小时,消费级 GPU。
QLoRA:更激进的省显存
2023 年提出 QLoRA(Quantized LoRA)—— 把基础模型量化到 4-bit,再加 LoRA:
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3-70B",
quantization_config=bnb_config,
)
# 70B 模型用 4-bit 加载,约 35GB 显存
# 再加 LoRA = 单张 H100 (80GB) 就能微调 70B!
QLoRA 让”在 1 张卡上微调 70B”成为可能——这在 2022 年是不可想象的。
部署:合并 vs 不合并
训完 LoRA 后两种部署方式:
方式 1:合并到基础模型
merged_model = model.merge_and_unload() # 把 A·B 合并到 W
merged_model.save_pretrained("./merged_model")
好处:推理时无额外开销。 坏处:每个任务都要存一份完整模型(70B 模型几百 GB)。
方式 2:动态加载 LoRA Adapter
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained("Llama-3-70B")
model = PeftModel.from_pretrained(base_model, "./my_lora_adapter")
好处:基础模型只存一份,N 个任务存 N 个小 adapter(每个几十-几百 MB)。可以动态切换 adapter——同一个基础模型服务多个垂直任务。
Salesforce、Adobe、Notion 这些公司用 LoRA adapter 给不同客户做”定制化”——一个底座 + 千个 adapter,效率极高。
别的”参数高效微调”方法
LoRA 只是 PEFT(Parameter-Efficient Fine-Tuning)家族里的一员:
| 方法 | 思路 | 参数量 |
|---|---|---|
| LoRA | 低秩矩阵分解 | 0.1-1% |
| DoRA(2024 改进) | 分解为方向 + 大小 | 0.1-1%,效果略好 |
| Prefix Tuning | 在每层加一段可训的 prefix | 0.1% |
| Adapter | 在层间插入小 MLP | 1-5% |
| (IA)³ | 元素级缩放 | 0.01% |
LoRA 仍是事实标准——简单、有效、生态成熟。
微调 vs RAG:怎么选
| 维度 | RAG | 微调 (LoRA) |
|---|---|---|
| 解决的问题 | 知识缺失 | 行为/风格 |
| 数据需求 | 文档(无需标注) | 指令-回答对(要标注) |
| 训练时间 | 几小时索引 | 几小时-几天训练 |
| 更新成本 | 索引新文档很快 | 重新训练 |
| 推理成本 | 每次多算检索 | 推理速度不变 |
| 可追溯性 | 能给出来源 | 不能 |
实战中通常组合使用:
- 基础:用 LoRA 微调让模型学会”行业风格 + 行话 + 格式”
- 加料:用 RAG 让模型能查到”最新数据 + 私有文档”
这套组合几乎是企业 AI 项目的标配。
不要为了微调而微调。
新人最常见的陷阱:拿到一个 LLM 任务,立刻想”我要微调一个模型”。
真相:90% 的问题不需要微调。先用:
- Prompt Engineering(最便宜)
- Few-shot examples(在 prompt 里给例子)
- RAG(让模型查资料)
只有当上述都不够时,才考虑微调。
先把 Prompt 用到极致,再讲微调。
一句话总结
LoRA 让”微调 LLM” 从”亿元工程”降到”几百美元的周末项目”。
它是 2023 年以来开源 LLM 生态爆发的核心技术之一——没有 LoRA,就没有今天的 Hugging Face、Civitai 等模型分享平台。
读完 L4-01, L4-02, L4-03, L4-05,你已经掌握了 LLM 应用工程的核心栈:架构 → 训练 → 应用(RAG)→ 定制(微调)。
下一站推荐:L5 多模态系列——AI 不只是处理文字。
读到这里说明你认真在学 🎯
订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。
讨论区
· 用 GitHub 账号登录评论src/components/Comments.astro 顶部填入
仓库 ID 和分类 ID(见组件注释里的配置步骤)。