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 条训练数据。