30秒快速回答: LoRA(Low-Rank Adaptation,低秩适配)是一种「插件式」微调技术。它不在原模型上直接修改参数,而是在旁边训练两个小型矩阵(A 和 B),推理时把它们”插”到原模型上。因为 A 和 B 非常小(通常是原参数的 1%-5%),训练快、省显存、可插拔——训练完就是一个独立的「LoRA 权重文件」,随时换、随时卸。
LoRA vs 全量微调
| 维度 | 全量 Fine-tuning | LoRA |
|---|---|---|
| 修改参数 | 全部参数(70B → 70B 都要训) | 仅 1-5% 的新增参数 |
| 显存需求 | 极大(70B 模型需 16×A100) | 低(70B 模型单张 A100 可训) |
| 训练时间 | 数天到数周 | 数小时 |
| 存储 | 70B 完整模型(~140GB) | 几个 MB 的 LoRA 权重 |
| 可插拔 | 否(新模型替换旧模型) | 是(随时加载/卸载不同的 LoRA) |
| 效果 | 理论上限最高 | 接近全量微调(90-95%) |
LoRA 的核心原理(人话版)
传统微调:改原模型
原始权重矩阵 W (d×d,比如 4096×4096)
↓ 训练时直接更新 W
新的权重矩阵 W' = W + ΔW
ΔW 和 W 一样大,所有参数都要计算梯度、更新存储。
LoRA:不改原模型,加插件
原始 W (冻结,不训练)
+
A (d×r) × B (r×d) ← 只训练这两个小矩阵
=
最终的 W_lora
其中 r 是秩(rank),通常取 8、16 或 32。r 越小,参数越少,训练越快。
数学表达:
h = Wx + BAx
h:输出
Wx:原始模型输出(不变)
BAx:LoRA 插件的增量
为什么有效?
核心洞见:全量微调时参数的更新量 ΔW 虽然是高维的,但它有效信息集中在一个低维子空间中。LoRA 通过矩阵分解 BA 来近似这个 ΔW,用极少的参数捕捉到了更新中最重要的”方向”。
实战:用 LoRA 微调 Qwen2 模型
以下用 peft + transformers 库实现:
# 安装: pip install transformers peft accelerate bitsandbytes datasets
from transformers import (
AutoModelForCausalLM, AutoTokenizer,
TrainingArguments, Trainer, DataCollatorForLanguageModeling
)
from peft import LoraConfig, get_peft_model, TaskType
from datasets import Dataset
import torch
# 1. 加载基座模型(用 4-bit 量化节省显存)
model_name = "Qwen/Qwen2-7B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto",
load_in_4bit=True # 4-bit 量化,显存降低 4 倍
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
# 2. 配置 LoRA
lora_config = LoraConfig(
r=16, # 秩,越大效果越好但参数越多
lora_alpha=32, # 缩放因子
target_modules=[ # 在哪些层插入 LoRA
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
lora_dropout=0.1, # Dropout 防止过拟合
bias="none",
task_type=TaskType.CAUSAL_LM
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 输出: trainable params: 41,943,040 || all params: 7,057,072,128 || trainable%: 0.59%
# 原始 7B 参数中只训练 4200 万(0.59%)!
# 3. 准备训练数据
training_data = [
{"text": "用户:帮我写一段 Python 代码,实现快速排序。\n助手:好的,以下是快速排序的 Python 实现:\n```python\ndef quicksort(arr):\n if len(arr) <= 1:\n return arr\n pivot = arr[len(arr)//2]\n left = [x for x in arr if x < pivot]\n middle = [x for x in arr if x == pivot]\n right = [x for x in arr if x > pivot]\n return quicksort(left) + middle + quicksort(right)\n```"},
# ... 更多训练数据
]
dataset = Dataset.from_list(training_data)
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True,
max_length=512,
padding="max_length"
)
tokenized_dataset = dataset.map(tokenize_function)
# 4. 训练
training_args = TrainingArguments(
output_dir="./qwen2-lora-code",
per_device_train_batch_size=2,
gradient_accumulation_steps=8, # 等效 batch size = 16
num_train_epochs=3,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False)
)
trainer.train()
# 5. 保存 LoRA 权重(只有几 MB!)
model.save_pretrained("./qwen2-lora-code-final")
# 6. 推理时加载 LoRA
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map="auto",
load_in_4bit=True
)
model = PeftModel.from_pretrained(base_model, "./qwen2-lora-code-final")
inputs = tokenizer("用 Python 实现冒泡排序", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=256)
print(tokenizer.decode(outputs[0]))
QLoRA:更省显存
QLoRA 在 LoRA 基础上加入 4-bit 量化,显存需求再降 75%:
| 方式 | 70B 模型所需显存 |
|---|---|
| 全量微调 | 16×A100 (1280GB) |
| LoRA (FP16) | 2×A100 (160GB) |
| QLoRA (4-bit) | 1×A100 (80GB) |
| QLoRA (RTX 4090) | 1×RTX 4090 (24GB) |
QLoRA 让个人开发者在家用显卡上微调 70B 模型成为现实。
LoRA 的典型应用场景
| 场景 | 效果 |
|---|---|
| 代码风格适配 | 让模型严格遵循你的编码规范 |
| 客服话术定制 | 统一客服回复的语气和模板 |
| 行业术语训练 | 让模型准确使用医疗/法律/金融专业术语 |
| 输出格式固定 | 强制模型输出 JSON/XML/特定模板 |
| 角色扮演 | 训练模型模拟特定人物的说话风格 |
| 多 LoRA 切换 | 同一基座模型,不同任务加载不同 LoRA |
常见问题
Q: LoRA 的 rank(r)设多少合适?
r=8 对大部分任务够用,r=16 效果更好但参数翻倍,r=4 适合简单任务。r 超过 32 后边际收益很低,不如直接用全量微调。
Q: LoRA 训练的模型可以商用吗?
取决于基座模型的许可。如果基座模型(如 Qwen2)是 Apache 2.0 许可,你训练的 LoRA 也可以商用。OpenAI 的 Fine-tuning API 则受其服务条款约束。
Q: 多个 LoRA 可以叠加吗?
可以。比如一个 LoRA 训练了代码风格,另一个训练了医学知识,可以同时加载。但叠加时需注意权重冲突,建议调整 lora_alpha 控制各 LoRA 的影响力。
下一步建议: 用 Google Colab 的免费 T4 GPU + QLoRA,尝试微调一个 Qwen2-7B 模型,让你的 AI 学会写特定风格的文案。只需 30 分钟和 50 条训练数据。