AI大模型微调
大模型微调(Fine-tuning)是指在预训练模型的基础上,使用特定任务或领域的数据继续训练,让模型更好地适应具体应用场景。下面是微调的完整过程,包括主流方法和关键步骤。
一、微调的核心思想
预训练模型已经学习了通用的语言知识(语法、推理、常识等),微调相当于把通才变为专才——用少量高质量任务数据调整模型参数,使其在特定任务(如情感分析、法律问答、医疗诊断)上表现更优。
微调的两种常见模式:
全量微调:更新模型所有参数,效果好但计算开销大。
参数高效微调 (PEFT):只更新少量额外参数(如 LoRA、Adapter),在保持效果的同时大幅降低显存需求。
二、微调的完整流程
步骤1:明确任务与数据准备
确定任务类型:文本分类、指令跟随、代码生成、对话摘要等。
收集/标注数据:需要输入-输出对。例如情感分析数据
(文本, 标签),对话数据(用户消息, 助手回复)。数据质量要求:
干净、一致、无噪声(去除错误标注、重复、无关内容)。
规模:几百到几十万条不等,取决于任务难度和模型大小(通常几千条已能看到明显效果)。
分布:覆盖实际部署场景的边界情况。
数据集划分:训练集、验证集、测试集(例如 8:1:1)。
步骤2:预处理与格式化
模板化:将原始数据构造成模型能理解的对话/指令格式。例如,微调 Llama 2 时常用:
text
[INST] {用户问题} [/INST] {期望回答}分词:将文本转换为令牌 ID,同时填充/截断到统一长度(例如 2048 tokens)。
遮蔽:自回归训练时,需要因果掩码(causal mask)确保模型只能看到前面的 token。
处理标签:对于生成任务,通常将输入部分的标签设为 -100(忽略损失),只计算输出部分的损失。
步骤3:选择微调方法
| 方法 | 更新参数量 | 显存需求 | 效果 | 适用场景 |
|---|---|---|---|---|
| 全量微调 | 100% | 极高 | 最好 | 数据量大、有充足计算资源 |
| LoRA | 0.1%~1% | 低 | 媲美全量 | 绝大多数场景 |
| QLoRA | ~0.1% | 极低(4-bit量化) | 接近全量 | 单卡微调7B~70B模型 |
| Adapter | ~1% | 较低 | 中等 | 较旧的技术,现较少用 |
| Prefix Tuning | 很少 | 低 | 中等 | 生成任务 |
LoRA 原理:冻结原始权重,在旁支插入低秩矩阵(A和B),训练时只更新这两个小矩阵,最后与原始权重合并。
步骤4:设置训练超参数
关键超参数及其典型值(以 LoRA 微调 7B 模型为例):
| 参数 | 全量微调 | LoRA | 说明 |
|---|---|---|---|
| 学习率 | 5e-6 ~ 5e-5 | 1e-4 ~ 5e-4 | LoRA 通常需要更高学习率 |
| 批次大小 | 4~32 | 4~16 | 受限于显存 |
| 训练轮次 | 2~5 | 3~10 | 小数据集可多轮,防止过拟合 |
| 优化器 | AdamW / AdamW | AdamW | 常用 |
| 梯度累积步数 | 1~8 | 1~4 | 等效增大 batch size |
| 学习率调度 | 余弦退火 / 线性衰减 | 余弦退火 | |
| 预热步数 | 0~100 | 0~200 | |
| 最大序列长度 | 512~4096 | 与基座一致 |
LoRA 特有参数:
r(秩):通常 8, 16, 32。越大能力越强,但参数增多。alpha:缩放因子,通常设为 2r 或与 r 相等。dropout:0~0.1,防过拟合。
步骤5:执行训练
硬件要求:
7B 模型全量微调:至少 1 张 80G A100 或 2~4 张 40G A100。
7B LoRA/QLoRA:1 张 24G 显卡(RTX 3090/4090)足够。
13B QLoRA:24G 勉强可跑;33B 需要 2×24G 或 A100 40G。
常见工具:
Hugging Face Transformers + PEFT + TRL:最通用,支持 SFTTrainer。
LLaMA-Factory:WebUI 操作,低代码。
Axolotl:配置化微调,适合生产。
Unsloth:专门优化 Llama/Mistral 微调速度,快 2~5 倍。
训练循环示意(伪代码):
python
for epoch in range(num_epochs): for batch in dataloader: # 前向:输入 batch 得到 logits outputs = model(input_ids=batch["input_ids"], labels=batch["labels"]) loss = outputs.loss # 反向传播 loss.backward() # 梯度裁剪(防止爆炸) torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) # 更新参数 optimizer.step() scheduler.step() optimizer.zero_grad() # 记录损失,在验证集上评估
步骤6:评估与验证
验证集损失:判断是否过拟合(训练损失持续降,验证损失上升 → 停止)。
任务具体指标:
分类:准确率、F1。
生成:ROUGE-L、BLEU(参考答案)、人工评分或 GPT-4 评估。
对抗测试:检查是否产生有害内容、幻觉、格式错误。
步骤7:合并与部署
LoRA 权重合并:可将 adapter 合并回基座模型,得到一个完整的新模型文件。
量化:若需降低部署成本,可再量化到 int8 或 int4(GPTQ、AWQ)。
部署格式:导出为 HuggingFace 格式,或转换为 vLLM、TGI 能加载的格式。
提供服务:用 FastAPI 封装模型推理接口,或使用推理引擎加速。
三、微调中的常见陷阱与建议
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 模型只重复输入 | 模板错误 / 标签遮蔽不当 | 检查 labels 中是否将输入部分设为 -100 |
| 灾难性遗忘 | 学习率过高 / 训练过久 | 降低学习率,添加少量原始预训练数据混合训练 |
| 过拟合 | 数据太少或轮次太多 | 增加正则(dropout,权重衰减),早停,收集更多数据 |
| 效果不如提示工程 | 微调数据质量差或任务简单 | 先尝试 few-shot 提示,不行再微调 |
| 显存不足 | 模型大,序列长 | 使用 LoRA + 梯度检查点 + 4-bit 量化 |
四、一个最小的微调示例(使用 LLaMA-Factory)
bash
# 安装 LLaMA-Factory git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e . # 准备数据:data/medical.json (格式示例) [ {"instruction": "什么是高血压?", "output": "高血压是指..."}, ... ] # 启动微调命令行 llamafactory-cli train \ --model_name_or_path meta-llama/Llama-2-7b-hf \ --stage sft \ --dataset medical \ --template llama2 \ --finetuning_type lora \ --lora_rank 8 \ --output_dir ./lora_medical \ --per_device_train_batch_size 4 \ --learning_rate 1e-4 \ --num_train_epochs 5五、总结
大模型微调的关键不在于复杂的代码,而在于高质量的数据 + 合适的微调方法 + 正确的超参数。对于大多数开发者,推荐LoRA/QLoRA + Hugging Face PEFT + 小型专用数据集,可以在消费级显卡上快速得到效果不错的垂直领域模型。如果追求极致效果且资源充足,才考虑全量微调。
如果需要更深入解释某个环节(例如数据构造细节、LoRA 原理、评估方法等),可以继续问我。
