共计 1779 个字符,预计需要花费 5 分钟才能阅读完成。
为什么模型微调如此重要?
在 NLP 和 CV 任务中,预训练模型(如 BERT、ResNet)已经学会了丰富的通用特征表示。但直接使用这些预训练参数往往无法在特定任务上达到最佳效果,这就是微调的意义所在。

新手常见的误区包括:
- 盲目使用预训练模型的默认参数
- 认为更高的学习率总是更好
- 忽略批量大小对模型收敛的影响
- 不使用验证集来监控训练过程
优化器选择:Adam vs SGD
在微调场景中,优化器的选择会显著影响模型性能。以下是两种常用优化器的对比:
# Adam 优化器示例
optimizer = torch.optim.Adam(model.parameters(), lr=1e-5, weight_decay=1e-4)
# SGD 优化器示例
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3, momentum=0.9)
Adam 特点:
– 自适应学习率
– 适合大多数场景
– 初始学习率可以设置较小
SGD 特点:
– 需要手动调整学习率
– 配合 momentum 效果更好
– 在 CV 任务中表现优异
PyTorch 微调完整框架
下面是一个完整的微调代码框架,包含学习率调度和早停机制:
import torch
from torch.optim.lr_scheduler import ReduceLROnPlateau
# 1. 定义早停机制
class EarlyStopping:
def __init__(self, patience=5):
self.patience = patience
self.counter = 0
self.best_loss = float('inf')
def __call__(self, val_loss):
if val_loss < self.best_loss:
self.best_loss = val_loss
self.counter = 0
else:
self.counter += 1
if self.counter >= self.patience:
return True
return False
# 2. 初始化模型和优化器
model = MyPretrainedModel()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-5)
scheduler = ReduceLROnPlateau(optimizer, 'min', patience=2)
early_stopping = EarlyStopping(patience=5)
# 3. 训练循环
for epoch in range(100):
model.train()
for batch in train_loader:
optimizer.zero_grad()
outputs = model(batch)
loss = criterion(outputs, batch.labels)
loss.backward()
optimizer.step()
# 验证阶段
model.eval()
val_loss = evaluate(model, val_loader)
# 调整学习率
scheduler.step(val_loss)
# 早停检查
if early_stopping(val_loss):
print('Early stopping triggered')
break
避坑指南
数据分布偏移
当训练数据和实际应用数据分布不一致时:
- 减小初始学习率
- 增加更多的数据增强
- 使用更强的正则化
小样本场景
在小样本学习中:
- 使用更小的批量大小
- 增加 dropout 比例
- 尝试冻结部分层
GPU 显存不足
当遇到显存问题时:
# 使用梯度累积
batch_size = 4
accum_steps = 8 # 实际批量大小 =4*8=32
for i, batch in enumerate(train_loader):
loss = model(batch) / accum_steps
loss.backward()
if (i+1) % accum_steps == 0:
optimizer.step()
optimizer.zero_grad()
GLUE 基准测试结果
| 调参策略 | MRPC Acc | CoLA MCC |
|---|---|---|
| 默认参数 | 82.3 | 58.1 |
| 调优后 | 86.7 | 62.4 |
思考题
当预训练模型和下游任务领域差异较大时(如用 BERT 做医学文本分类):
- 是否需要完全解冻所有层?
- 应该如何设计分层学习率?
- 领域自适应技术是否能帮助改善性能?
期待在评论区看到你的见解和实践经验!
正文完
