微调方法总览
五类微调:标签数据微调 / 基于特征微调 / 知识蒸馏 / 适配器(Adapter)微调 / 提示词微调。 全量微调的风险:破坏原参数结构、损伤通用语义理解能力。经验判断:**3 个版本以上的 LLM 都有解决问题的能力,非极特殊场景不需要微调**——先 Prompt/RAG/Agent,微调是最后手段。
PEFT(Parameter-Efficient Fine-Tuning,HF 开源库)集成 Prefix Tuning / Adapter / LoRA。LoRA 标准用法: ```python from peft import LoraConfig, TaskType, get_peft_model peft_config = LoraConfig( task_type=TaskType.CAUSAL_LM, inference_mode=False, r=8, # 秩:8/16/32 lora_alpha=32, # 缩放:一般为 r 的 2 倍 lora_dropout=0.1, target_modules=["query_key_value"], # ChatGLM3 的 QKV 投影 ) model = get_peft_model(model, peft_config).to("cuda") model.print_trainable_parameters() # 可训练参数常只占 0.1%~3% ```
值得微调的四种情况:①提高输出稳定性 ②用户量大降推理成本 ③提高生成速度 ④私有部署。 值得记住的对照:微调=闭卷背书(长期记住),RAG=开卷考试(随时换书)——知识频繁变化选 RAG,风格/格式/稳定性选微调。
LoRA 原理详解
核心思想:微调增量 ΔW 是**低秩**的,用两个小矩阵乘积近似: $$\Delta W = BA, \quad B \in \mathbb{R}^{d \times r},\ A \in \mathbb{R}^{r \times k},\ r \ll \min(d,k)$$ 前向:$h = Wx + \frac{\alpha}{r} \cdot BAx$,W 冻结,只训 A、B。 参数量从 $d \times k$ 降为 $2 \times d \times r$——d=4096、r=16 时省约 99.2%。 **重要辨析**:LoRA 省的是**训练阶段**资源(梯度/优化器状态/存储);推理合并($W' = W + \frac{\alpha}{r}BA$)后计算量与显存**完全不省**。比喻:LoRA 是"软装",不动房子结构。
初始化技巧:**A 用 Kaiming 随机初始化,B 初始化为全 0**——保证训练起点 BA=0,等于预训练模型本身;α 平衡增量贡献、稳定训练。 两种推理形态:不合并(多适配器热切换 `switch_task`,省存储)vs 合并 `merge_and_unload()`(零额外延迟);手写实现只需包一层 `LinearWithLoRA(nn.Module)`。
| 套路 | r | alpha | target_modules | |------|---|-------|----------------| | 快速实验 | 8 | 16 | 注意力 QKV | | 标准微调 | 16 | 32 | 七个线性投影 | | 最佳效果 | 32 | 64 | all-linear | dropout 取 0~0.1(小数据/短训练可取 0,低秩本身就是正则化)。
显存账本(7B 级参考值): | 场景 | 显存 | |------|------| | FP16 推理 | ~14-16 GB | | LoRA 微调 | ~18-26 GB | | 全量微调 | ~54 GB | - 微调比推理多吃在**常驻激活值**;BA 乘积会产生与 W 同大小的瞬时峰值尖刺(单层 FP16 全量 ~64MB vs LoRA ~16.5MB) - **gradient checkpointing** 可把激活 12GB 压到 ~3GB(再省 4-6GB)——4090 24G 可跑 7B LoRA
ChatGLM3 实战
数据:CrossWOZ 汉语跨领域对话(酒店/餐饮/打车/地铁)。数据增强思路:不同风格提问、全场景覆盖、由测试团队负责发现知识缺陷再回补。
```bash # lora_train.sh(AutoDL 环境) CUDA_VISIBLE_DEVICES=0 python main_lora.py \ --train_file ../data/train.chatglm3.jsonl \ --model_name_or_path /root/autodl-tmp/chatglm3-6b \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 2 \ --num_train_epochs 4 --learning_rate 2e-4 \ --lora_rank 8 --lora_alpha 32 --lora_dropout 0.1 ``` checkpoint 目录按步数滚动(checkpoint-300 … 3000);ssh -L 6006 映射 tensorboard。
`gradient_accumulation_steps` 三重作用:省显存(小 batch 多累积)/ 降低更新频率(更稳)/ 处理样本不平衡。 $$\text{真实 batch} = \text{GPU数} \times \text{per\_device\_batch} \times \text{grad\_accum}$$
评估(llama3 路线同款):BitsAndBytesConfig 4bit NF4 双重量化加载 + `PeftModel.from_pretrained(model, checkpoint)` 注入评估。 指标:slot_P / slot_R / slot_F1(槽位抽取)与 bleu-4(生成质量): $$\text{BLEU-4} = BP \cdot \exp\left(\sum_{n=1}^{4} \frac{1}{4}\ln p_n\right)$$ 实测成绩:slot_F1 92.96 / bleu-4 64.07。
视觉模型微调(unsloth)
DeepSeek-OCR2 微调(unsloth + transformers 4.56.2 + trl 0.22.2): ```python from unsloth import FastVisionModel model, tokenizer = FastVisionModel.from_pretrained( "./deepseek_ocr2", load_in_4bit=False, auto_model=AutoModel) # 五档:Tiny/Small/Base/Large/Gundam(base_size/image_size/crop_mode 不同) ``` - 基线:hezarai/parsynth-ocr-200k,CER=23% - LoRA:7 个 target_modules、r=16、**dropout=0**(数据仅 1000 条、仅 60 步、OCR 是确定性映射、低秩即正则、底模已强) - 数据:`convert_to_conversation` 转成 `<|User|>/<Assistant|>` 对话格式;自定义 DataCollator(image_size=768 / train_on_responses_only) - 训练:**必须 `remove_unused_columns=False`**(视觉任务) - 结果:**可训练 86M/3.47B(2.48%),60 步 12.4 分钟,峰值显存 8.37GB,CER 23%→6%**
Qwen3-VL-8B 微调(LaTeX_OCR 手写公式→LaTeX,68,686 条): ```python model = FastVisionModel.from_pretrained( "unsloth/Qwen3-VL-8B-Instruct-unsloth-bnb-4bit", load_in_4bit=True) # 4bit ~8GB / 16bit ~16GB ``` - **模块化开关**:`finetune_vision_layers / finetune_language_layers / finetune_attention_modules / finetune_mlp_modules`——只视觉 0.6% / 只语言 1.2% / 全部 1.8% 参数 - 数据格式:user/assistant content 数组(type: text/image) - `UnslothVisionDataCollator + SFTTrainer`,`dataset_kwargs={"skip_prepare_dataset": True}` - 效果:LaTeX 准确率 60% → 85%(30 步)→ 95%(完整训练)
保存三件套:LoRA 适配器目录 / 16bit 合并权重 / GGUF 多格式: | 格式 | 体积 | 说明 | |------|------|------| | f16 | 最大 | 全精度 | | q8_0 | ~1/2 | 近无损 | | q5_k_m | ~40% | 推荐 | | q4_k_m | ~1/4 | 显存受限 | 工具补充:LLaMAFactory 提供界面化微调;模型选择"选新不选旧",定期用新数据重训。
参考
     LoRA 论文 
     unsloth