目录
1. 全量微调(Full Fine-tuning)
原理
全量微调是将预训练模型的所有参数(如BERT的1亿参数)全部放开,通过反向传播更新所有参数,使其适应新任务。
- 数学表达:
假设原始模型参数为θpreθpre,微调后参数为θfine=θpre+Δθθfine=θpre+Δθ,其中ΔθΔθ通过梯度下降更新。 - 目标函数:
Ltask(θfine)=∑iLoss(fθfine(xi),yi)Ltask(θfine)=∑iLoss(fθfine(xi),yi)
其中fθfθ是模型,xixi是输入,yiyi是标签。
实现步骤
python
深色版本
from transformers import AutoModelForSequenceClassification, Trainer, TrainingArguments
# 加载预训练模型
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=2)
# 解冻所有参数
for param in model.parameters():
param.requires_grad = True
# 定义训练配置
training_args = TrainingArguments(
output_dir="full_finetune",
learning_rate=2e-5,
per_device_train_batch_size=8,
num_train_epochs=3,
weight_decay=0.01,
)
# 定义数据集和训练器
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset,
)
# 开始训练
trainer.train()
优缺点
- 优点:
- 效果最佳:参数完全适应任务,精度最高。
- 简单直接:无需复杂设计,适合计算资源充足的场景。
- 缺点:
- 资源消耗大:需大量计算资源(如GPU)和数据(通常需数万条标注数据)。
- 过拟合风险:小数据时可能过度拟合。
适用场景
- 任务与预训练目标差异大(如从文本分类转向设备故障诊断)。
- 数据量充足(如数万条标注设备手册文本)。
2. 冻结微调(Frozen Fine-tuning)
原理
仅微调模型顶层(如分类头),底层参数冻结。
- 数学表达:
θfine=(θbasefrozen,θheadunfrozen)θfine=(θbasefrozen,θheadunfrozen)
其中θbaseθbase是冻结的底层参数,θheadθhead是可训练的顶层参数。
实现步骤
python
深色版本
# 冻结底层参数
for param in model.bert.parameters(): # 假设模型是BERT
param.requires_grad = False
# 解冻分类头
for param in model.classifier.parameters():
param.requires_grad = True
# 其余训练步骤同全量微调
优缺点
- 优点:
- 节省资源:仅训练少量参数(如分类层的几百个参数)。
- 快速收敛:适合数据量小(如数百条标注数据)。
- 缺点:
- 效果受限:底层参数无法适应新任务,可能精度不足。
适用场景
- 数据量极小(如只有几百条标注设备手册)。
- 任务与预训练目标相似(如从文本分类转向相似任务)。
3. LoRA(Low-Rank Adaptation)
原理
在模型的每一层(如注意力层、前向层)中,添加一个低秩矩阵(如A∈Rd×rA∈Rd×r和B∈Rr×dB∈Rr×d,r≪dr≪d),通过微调这两个小矩阵来调整模型行为。
- 数学表达:
原始权重矩阵WW被分解为:
Wnew=Wpre+A⋅BWnew=Wpre+A⋅B
其中AA和BB是低秩矩阵,仅需微调这两个矩阵。
实现步骤
python
深色版本
from peft import get_peft_config, PeftType, get_peft_model
# 配置LoRA参数
config = PeftConfig(
task_type=PeftType.LORA,
r=8, # 低秩秩数(r越小,参数越少)
lora_alpha=32,
lora_dropout=0.1,
)
# 应用LoRA到模型
model = get_peft_model(model, config)
# 训练时仅优化LoRA参数
for name, param in model.named_parameters():
if "lora" in name:
param.requires_grad = True
else:
param.requires_grad = False
# 训练步骤同全量微调
优缺点
- 优点:
- 极低资源消耗:仅需微调少量参数(如模型参数的0.1%)。
- 支持大模型:适合在边缘设备部署(如BERT-large)。
- 缺点:
- 效果略逊:低秩矩阵可能无法捕捉复杂任务。
适用场景
- 模型体积大(如GPT-3、BERT-large),但计算资源有限。
- 需要快速迭代(如设备手册版本频繁更新)。
4. P-Tuning / Prefix-Tuning
原理
在输入的前面添加可学习的“虚拟token”(如20个),这些token通过梯度更新来引导模型输出。原始参数保持冻结。
- 数学表达:
输入序列X=[P,Xreal]X=[P,Xreal],其中PP是可学习的前缀(虚拟token),XrealXreal是真实输入。
实现步骤
python
深色版本
from peft import PrefixTuningConfig
# 配置Prefix Tuning参数
config = PrefixTuningConfig(
task_type=PeftType.PREFIX_TUNING,
num_virtual_tokens=20, # 前缀长度
prefix_projection=True, # 是否添加投影层
)
# 应用Prefix Tuning到模型
model = get_peft_model(model, config)
# 训练时仅优化前缀参数
for name, param in model.named_parameters():
if "prefix" in name:
param.requires_grad = True
else:
param.requires_grad = False
# 训练步骤同全量微调
优缺点
- 优点:
- 灵活性高:通过调整前缀可适应多种任务(如不同设备类型的故障诊断)。
- 轻量级:仅需微调少量参数(如20个虚拟token的嵌入)。
- 缺点:
- 效果依赖前缀设计:需合理设置虚拟token数量和初始化方式。
适用场景
- 需要快速切换任务(如不同设备部件的故障诊断)。
- 任务需要明确的上下文引导(如特定术语的解释)。
5. Adapter Tuning
原理
在模型的每一层中插入一个小型神经网络(Adapter模块),通过调整Adapter参数来适应任务,原始参数冻结。
- 数学表达:
原始层的输出HH通过Adapter调整:
Hnew=H+Adapter(H)Hnew=H+Adapter(H)
其中Adapter通常为两层全连接网络:
Adapter(H)=σ(W2⋅σ(W1⋅H)+b2)+b1Adapter(H)=σ(W2⋅σ(W1⋅H)+b2)+b1
其中W1,W2W1,W2是Adapter的参数。
实现步骤
python
深色版本
from peft import AdapterConfig
# 配置Adapter参数
config = AdapterConfig(
hidden_size=768, # 模型隐藏层维度
reduction_factor=16, # 压缩因子(越小,参数越少)
non_linearity="relu", # 激活函数
)
# 应用Adapter到模型
model = get_peft_model(model, config)
# 训练时仅优化Adapter参数
for name, param in model.named_parameters():
if "adapter" in name:
param.requires_grad = True
else:
param.requires_grad = False
# 训练步骤同全量微调
优缺点
- 优点:
- 模块化设计:Adapter可独立训练或复用(如不同设备品牌共享Adapter)。
- 效果平衡:介于LoRA和全量微调之间。
- 缺点:
- 计算稍高:比LoRA需要更多参数。
适用场景
- 需要模块化扩展(如不同设备品牌分别适配Adapter)。
- 任务需要中等精度(如设备参数分类)。
6. Prompt Tuning
原理
固定模型参数,仅优化输入的提示词(Prompt),通过设计更精准的Prompt引导模型输出。
- 数学表达:
输入为X=[Ptuned,Xreal]X=[Ptuned,Xreal],其中PtunedPtuned是可学习的Prompt(如“涡轮机故障诊断:”)。
实现步骤
python
深色版本
from peft import PromptTuningConfig
# 配置Prompt Tuning参数
config = PromptTuningConfig(
task_type=PeftType.PROMPT_TUNING,
num_virtual_tokens=20, # 可学习的Prompt长度
tokenizer_name_or_path="bert-base-uncased",
)
# 应用Prompt Tuning到模型
model = get_peft_model(model, config)
# 训练时仅优化Prompt参数
for name, param in model.named_parameters():
if "prompt" in name:
param.requires_grad = True
else:
param.requires_grad = False
# 训练步骤同全量微调
优缺点
- 优点:
- 零参数微调模型:完全冻结模型,仅调整输入。
- 易解释:Prompt可直接查看和优化。
- 缺点:
- 效果有限:依赖Prompt的设计,可能无法解决复杂任务。
适用场景
- 模型无法修改(如使用远程API)。
- 需要可解释性高的任务(如生成结构化答案)。
7. 混合微调方法
示例:LoRA + Adapter
结合低秩矩阵和Adapter模块,进一步提升效果:
python
深色版本
from peft import PeftConfig, PeftType
# 配置LoRA和Adapter的混合参数
config = PeftConfig(
task_type=PeftType.LORA,
r=8,
lora_alpha=32,
lora_dropout=0.1,
adapter_config=AdapterConfig( # 添加Adapter
hidden_size=768,
reduction_factor=16,
),
)
# 应用混合微调
model = get_peft_model(model, config)
8. 选择微调方法的决策流程
步骤1:评估任务需求
- 任务类型:分类、生成、检索?
- 数据量:小(<1k)、中(1k-10k)、大(>10k)?
- 计算资源:GPU/TPU数量、内存限制?
步骤2:选择方法
条件 | 推荐方法 | 原因 |
---|---|---|
大数据 + 高资源 | 全量微调 | 最优效果,资源充足。 |
小数据 + 低资源 | 冻结微调或LoRA | 节省资源,快速收敛。 |
需要模块化适配 | Adapter | 模块化扩展,复用性强。 |
需要快速任务切换 | P-Tuning | 虚拟前缀灵活引导。 |
仅能修改输入 | Prompt Tuning | 零参数微调,完全冻结模型。 |
步骤3:调参建议
- LoRA:
- 调整rr(秩):r=8r=8适合小模型,r=16r=16适合大模型。
- Prefix Tuning:
- 调整虚拟token数量:2020~3030通常足够。
- Adapter:
- 调整reduction_factorreduction_factor:88~1616平衡参数量和效果。
9. 常见问题与解决方案
Q1:内存不足怎么办?
- 解决方案:
- 使用LoRA/Adapter:仅微调少量参数。
- 梯度累积: python
深色版本
# 每4个batch累积梯度 trainer = Trainer( ..., gradient_accumulation_steps=4, )
Q2:过拟合如何缓解?
- 解决方案:
- 早停法(Early Stopping): python
深色版本
from transformers import EarlyStoppingCallback trainer = Trainer( ..., callbacks=[EarlyStoppingCallback(early_stopping_patience=3)], )
- 数据增强:对小数据集进行同义词替换或噪声注入。
- 早停法(Early Stopping): python
Q3:如何评估微调效果?
- 指标:
- 分类任务:准确率、F1-score。
- 生成任务:BLEU、ROUGE分数。
- 检索任务:Recall@K、MRR(Mean Reciprocal Rank)。
10. 总结:方法对比表
方法 | 参数量(占原模型%) | 适用数据量 | 效果排名 | 内存占用 | 典型场景 |
---|---|---|---|---|---|
全量微调 | 100% | 大(>10k) | 1 | 高 | 设备故障诊断(数据充足) |
冻结微调 | 0.1%~1% | 小(<1k) | 3 | 低 | 手册分类(数据稀缺) |
LoRA | 0.01%~0.1% | 中(1k~10k) | 2 | 中 | 边缘设备部署(资源有限) |
P-Tuning | 0.05%~0.2% | 中(1k~10k) | 2.5 | 中 | 快速任务切换(如多设备) |
Adapter | 0.1%~1% | 中(1k~10k) | 2.3 | 中 | 模块化适配(品牌差异) |
Prompt Tuning | 0% | 小(<1k) | 4 | 极低 | 生成结构化答案(如维修步骤) |
最后的话
选择微调方法就像“给模型戴眼镜”——
- 全量微调是定制光学镜片,效果最佳但成本高;
- LoRA/Adapter是薄款眼镜,轻便且适合日常使用;
- 冻结微调是老花镜,简单但可能看不清细节;
- P-Tuning/Prompt Tuning是太阳镜,灵活但功能有限。