微调评估与部署
课程简介
微调模型评估、灾难性遗忘检测、模型部署。
🎬 本课程视频:Finetuning LLMs — 大模型微调
微调评估与部署
一、微调后最重要的一个问题
微调完成后,摆在面前最重要的问题是:模型真的变好了吗?
这个问题不是表面上看起来那么简单。微调可能提升模型在目标任务上的表现,但同时可能导致通用能力的下降。这种「进步」是否真的值得?需要全面的评估体系来回答。
二、三维度评估体系
2.1 任务表现评估
评估指标选择:
根据任务类型选择合适的指标:
- 分类任务:准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 分数
- 生成任务:BLEU(机器翻译)、ROUGE(文本摘要)、Perplexity(语言模型)
- 问答任务:精确匹配(EM)、F1 分数
测试集设计:
def build_test_set():
'''构建高质量的测试集'''
test_set = []
# 1. 正常场景(65%)
for example in normal_cases:
test_set.append({
"input": example.input,
"expected": example.output,
"category": "normal"
})
# 2. 边界场景(20%)
for example in edge_cases:
test_set.append({
"input": example.input,
"expected": example.output,
"category": "edge"
})
# 3. 对抗样本(10%)
for example in adversarial_cases:
test_set.append({
"input": example.input,
"expected": example.output,
"category": "adversarial"
})
# 4. 未见过的场景(5%)
for example in unseen_cases:
test_set.append({
"input": example.input,
"expected": example.output,
"category": "unseen"
})
return test_set
注意事项:
- 测试集绝对不能与训练集重叠
- 测试集要具有挑战性——太简单的测试集无法区分模型好坏
- 测试规模:至少 100 条,建议 200-500 条
2.2 灾难性遗忘检测
这是微调评估中最容易被忽视的环节。灾难性遗忘是指模型在学习新任务的过程中,遗忘了之前在预训练阶段学到的通用能力。
def evaluate_catastrophic_forgetting(original_model, finetuned_model):
'''检测灾难性遗忘'''
benchmarks = {
"mmlu": evaluate_mmlu, # 多任务语言理解
"hellaswag": evaluate_hellaswag, # 常识推理
"gsm8k": evaluate_gsm8k, # 数学推理
"human_eval": evaluate_human_eval # 代码生成
}
results = {}
for benchmark_name, eval_fn in benchmarks.items():
original_score = eval_fn(original_model)
finetuned_score = eval_fn(finetuned_model)
change = finetuned_score - original_score
results[benchmark_name] = {
"before": original_score,
"after": finetuned_score,
"change": change
}
if change < -0.05: # 下降超过 5%
print(f"警告:{benchmark_name}下降了 {change:.2%}")
return results
基准测试套件:
- MMLU:涵盖 57 个学科的多任务准确率
- HellaSwag:常识推理能力
- GSM8K:小学数学推理
- HumanEval:代码生成能力
如果微调后通用基准测试的分数下降超过 5%,说明存在明显的灾难性遗忘。
2.3 稳定性测试
def stability_test(model, test_inputs, num_runs=5):
'''测试模型输出的稳定性'''
results = []
for test_input in test_inputs:
outputs = []
for _ in range(num_runs):
output = model.generate(test_input, temperature=0)
outputs.append(output)
# 计算一致性
consistency = compute_consistency(outputs)
results.append({
"input": test_input,
"outputs": outputs,
"consistency": consistency
})
return results
三、部署策略
3.1 完整模型 vs PEFT 适配器
| 维度 | 完整模型 | PEFT 适配器 |
|---|---|---|
| 部署复杂度 | 低(单文件) | 中(基础模型 + 适配器) |
| 推理延迟 | 相同 | 相同(LoRA 无额外延迟) |
| 存储空间 | 大(~16GB for 7B) | 小(~10MB for LoRA) |
| 灵活性 | 低(一个模型一个任务) | 高(切换任务只需换适配器) |
| 批处理效率 | 高 | 中(需合并权重) |
3.2 推理优化
# 合并 LoRA 权重(提高批处理效率)
from peft import PeftModel
# 合并权重
merged_model = peft_model.merge_and_unload()
# 或使用 vLLM 部署优化
from vllm import LLM
llm = LLM(
model="./my_finetuned_model",
tensor_parallel_size=2, # 多卡并行
gpu_memory_utilization=0.9
)
3.3 持续监控
部署后的持续监控体系:
class ModelMonitor:
'''微调模型的生产监控'''
def monitor(self, predictions, feedback):
metrics = {
"latency_p50": compute_percentile(predictions.latency, 50),
"latency_p99": compute_percentile(predictions.latency, 99),
"user_satisfaction": compute_satisfaction_rate(feedback),
"error_rate": compute_error_rate(predictions),
"drift_detection": detect_distribution_drift(predictions)
}
# 如果检测到性能下降,触发告警
if metrics["error_rate"] > 0.1:
alert("错误率超过 10%,建议检查模型")
if metrics["drift_detection"]:
alert("检测到数据分布漂移,可能需要增量微调")
return metrics
四、增量微调
微调不是一次性的工作。当模型在生产环境中运行一段时间后,可能需要基于新的数据进行增量更新:
def incremental_finetune(base_model, new_data, lora_weights=None):
'''增量微调'''
if lora_weights:
# 在现有 LoRA 基础上继续训练
model = PeftModel.from_pretrained(base_model, lora_weights)
else:
# 从头训练新的 LoRA
model = get_peft_model(base_model, lora_config)
# 混合新旧数据进行训练
combined_data = balance_datasets(old_data, new_data)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=combined_data
)
trainer.train()
return model
五、微调失败模式
常见失败模式及解决方案:
| 失败模式 | 表现 | 解决方案 |
|---|---|---|
| 过拟合 | 训练 loss 低,验证 loss 高 | 减少 epoch、增加数据多样性 |
| 欠拟合 | 训练 loss 不下降 | 增大学习率、增加训练数据 |
| 灾难性遗忘 | 通用基准测试下降 | 混合通用数据训练、降低学习率 |
| 数据偏差 | 只对训练数据分布有效 | 增加数据多样性、检查数据分布 |
| 格式过拟合 | 模型只会输出训练数据的格式 | 增加输出格式的多样性 |
六、总结
微调后的评估体系需要覆盖任务表现、灾难性遗忘和稳定性三个维度。任务评估用测试集指标验证核心任务的效果,通用基准测试检测灾难性遗忘的程度,稳定性测试确保输出的可靠性。部署时需要在完整模型和 PEFT 适配器之间做出权衡,持续的监控体系保障生产环境的稳定运行。微调不是一次性的动作,持续监控和增量优化才是长期维护模型质量的正确姿势。
六、灾难性遗忘的应对策略
6.1 什么是灾难性遗忘
灾难性遗忘(Catastrophic Forgetting)是指微调过程中,模型在提升特定任务性能的同时,丢失了预训练阶段学到的一般知识和能力。
6.2 检测方法
- 通用能力评估:在微调前后评估模型在通用 benchmark 上的表现
- 能力对比:对比微调前后在“无关任务”上的表现差异
- 知识探测:用特定的知识探测问题测试模型的知识保留
6.3 缓解策略
- 混合训练:在微调数据中混入通用数据
- EWC(Elastic Weight Consolidation):对重要参数的更新施加约束
- 知识蒸馏:用原始模型指导微调模型保持能力
- 多任务微调:在微调时同时训练多个任务
七、部署方案选择
| 条件 | 推荐方案 |
|---|---|
| 日请求量 < 1000 | 云端 API 调用 |
| 日请求量 1000-10000 | 私有化部署 |
| 日请求量 > 10000 | GPU 集群部署 |
| 延迟要求 < 100ms | 模型蒸馏 + 量化 |
| 需要数据隐私 | 本地私有化部署 |
八、总结
关键要点回顾:
- 微调评估需要任务评估和通用评估两个维度
- 灾难性遗忘是微调的主要风险
- 评估数据集应该全面的覆盖各种场景
- 部署方案需综合考虑成本、延迟、隐私等因素
- 微调是一个“实验-评估-调整”的迭代过程
六、灾难性遗忘的应对策略
6.1 什么是灾难性遗忘
灾难性遗忘(Catastrophic Forgetting)是指微调过程中,模型在提升特定任务性能的同时,丢失了预训练阶段学到的一般知识和能力。
6.2 检测方法
- 通用能力评估:在微调前后评估模型在通用 benchmark 上的表现
- 能力对比:对比微调前后在“无关任务”上的表现差异
- 知识探测:用特定的知识探测问题测试模型的知识保留
6.3 缓解策略
- 混合训练:在微调数据中混入通用数据
- EWC(Elastic Weight Consolidation):对重要参数的更新施加约束
- 知识蒸馏:用原始模型指导微调模型保持能力
- 多任务微调:在微调时同时训练多个任务
七、部署方案选择
| 条件 | 推荐方案 |
|---|---|
| 日请求量 < 1000 | 云端 API 调用 |
| 日请求量 1000-10000 | 私有化部署 |
| 日请求量 > 10000 | GPU 集群部署 |
| 延迟要求 < 100ms | 模型蒸馏 + 量化 |
| 需要数据隐私 | 本地私有化部署 |
八、总结
关键要点回顾:
- 微调评估需要任务评估和通用评估两个维度
- 灾难性遗忘是微调的主要风险
- 评估数据集应该全面的覆盖各种场景
- 部署方案需综合考虑成本、延迟、隐私等因素
- 微调是一个“实验-评估-调整”的迭代过程
六、灾难性遗忘的应对策略
6.1 什么是灾难性遗忘
灾难性遗忘(Catastrophic Forgetting)是指微调过程中,模型在提升特定任务性能的同时,丢失了预训练阶段学到的一般知识和能力。
6.2 检测方法
- 通用能力评估:在微调前后评估模型在通用 benchmark 上的表现
- 能力对比:对比微调前后在“无关任务”上的表现差异
- 知识探测:用特定的知识探测问题测试模型的知识保留
6.3 缓解策略
- 混合训练:在微调数据中混入通用数据
- EWC(Elastic Weight Consolidation):对重要参数的更新施加约束
- 知识蒸馏:用原始模型指导微调模型保持能力
- 多任务微调:在微调时同时训练多个任务
七、部署方案选择
| 条件 | 推荐方案 |
|---|---|
| 日请求量 < 1000 | 云端 API 调用 |
| 日请求量 1000-10000 | 私有化部署 |
| 日请求量 > 10000 | GPU 集群部署 |
| 延迟要求 < 100ms | 模型蒸馏 + 量化 |
| 需要数据隐私 | 本地私有化部署 |
八、总结
关键要点回顾:
- 微调评估需要任务评估和通用评估两个维度
- 灾难性遗忘是微调的主要风险
- 评估数据集应该全面的覆盖各种场景
- 部署方案需综合考虑成本、延迟、隐私等因素
- 微调是一个“实验-评估-调整”的迭代过程
延伸阅读
- 📺 B 站播放列表:Finetuning LLMs — 大模型微调
- 📚 更多学习资源,请访问 deeplearning.ai 官网