目录
1. 确定目标:明确任务和数据
- 任务类型:
确定你要解决的问题类型,例如:- 文本分类(如情感分析)
- 图像分类(如识别猫狗)
- 序列生成(如文本生成或机器翻译)
- 数据集:
收集或准备与任务相关的数据集,并进行初步分析:- 数据规模(样本数量、类别分布)
- 数据质量(是否有噪声、缺失值、标签错误)
- 数据预处理需求(如文本清洗、图像归一化)
2. 选择预训练模型
- 预训练模型:
根据任务选择合适的预训练模型:- 文本任务:BERT、RoBERTa、GPT、T5
- 图像任务:ResNet、EfficientNet、ViT
- 多模态任务:CLIP、Mixture of Experts(MoE)
- 模型来源:
常用的模型库包括:- Hugging Face(如
transformers
库) - PyTorch/TensorFlow官方模型库
- Timm库(针对计算机视觉)
- Hugging Face(如
3. 数据预处理
(1) 数据清洗与格式化
- 文本数据:
- 去除特殊字符、停用词
- 统一大小写(如全小写)
- 处理缺失值或异常标签
- 图像数据:
- 调整尺寸(如统一为224x224)
- 归一化(如将像素值缩放到[0,1]或[-1,1])
- 数据增强(如旋转、翻转、裁剪)
(2) 划分数据集
- 训练集:用于模型训练(通常占80%)。
- 验证集:用于调参和监控过拟合(通常占10%)。
- 测试集:最终评估模型性能(通常占10%)。
(3) 数据加载与批处理
- 使用
DataLoader
(PyTorch)或tf.data
(TensorFlow)将数据分批次加载: python深色版本
from torch.utils.data import DataLoader, Dataset class MyDataset(Dataset): def __init__(self, data, labels): self.data = data self.labels = labels def __len__(self): return len(self.data) def __getitem__(self, idx): return self.data[idx], self.labels[idx] train_dataset = MyDataset(train_data, train_labels) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
4. 构建微调模型架构
(1) 加载预训练模型
- 文本模型示例(Hugging Face): python
深色版本
from transformers import BertModel, BertConfig model = BertModel.from_pretrained("bert-base-uncased")
- 图像模型示例(PyTorch): python
深色版本
import torchvision.models as models model = models.resnet18(pretrained=True)
(2) 修改模型尾部(适配任务)
- 分类任务:替换最后一层全连接层(全连接层的输出维度需匹配任务类别数): python
深色版本
# 对于ResNet: num_features = model.fc.in_features model.fc = nn.Linear(num_features, num_classes) # num_classes是目标类别数 # 对于BERT: model.classifier = nn.Linear(model.config.hidden_size, num_classes)
(3) 冻结部分层(可选)
- 冻结预训练层:保留底层的通用特征提取能力,只训练新增层: python
深色版本
for param in model.parameters(): param.requires_grad = False # 冻结所有层 # 解冻最后一层(如分类层) for param in model.fc.parameters(): # 对BERT可能是model.classifier.parameters() param.requires_grad = True
5. 设置训练参数
(1) 优化器与学习率
- 选择优化器:
- 常用优化器:Adam、AdamW、SGD
- 示例: python
深色版本
optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)
- 学习率(Learning Rate):
- 预训练模型微调时,学习率通常比从头训练低(如1e-5到1e-3)。
- 可使用学习率调度器(如
torch.optim.lr_scheduler.CosineAnnealingLR
)。
(2) 损失函数
- 根据任务选择损失函数:
- 分类任务:交叉熵损失(
nn.CrossEntropyLoss
) - 回归任务:均方误差(
nn.MSELoss
) - 生成任务:交叉熵或自定义损失(如BERT的MLM损失)
- 分类任务:交叉熵损失(
(3) 其他超参数
- 批量大小(Batch Size):根据硬件限制选择(如32、64、128)。
- 训练轮次(Epochs):通常5-20轮,根据验证集表现调整。
- 早停(Early Stopping):当验证损失不再下降时停止训练,防止过拟合。
6. 训练模型
(1) 定义训练循环
python
深色版本
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
for epoch in range(num_epochs):
model.train()
total_loss = 0
for batch in train_loader:
inputs, labels = batch
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
# 验证阶段
model.eval()
val_loss = 0
with torch.no_grad():
for batch in val_loader:
inputs, labels = batch
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
val_loss += criterion(outputs, labels).item()
print(f"Epoch {epoch+1}, Train Loss: {total_loss/len(train_loader)}, Val Loss: {val_loss/len(val_loader)}")
(2) 监控训练过程
- 使用工具如TensorBoard或Weights & Biases记录损失、准确率等指标。
- 定期保存模型检查点(Checkpoint): python
深色版本
torch.save(model.state_dict(), f"model_epoch{epoch}.pth")
7. 调整超参数(可选)
- 网格搜索(Grid Search)或随机搜索(Random Search):
调整学习率、批量大小、层冻结策略等。 - 自动化工具:
使用Optuna
或Ray Tune
进行超参数优化。
8. 评估与部署
(1) 模型评估
- 在测试集上评估最终性能: python
深色版本
model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += criterion(output, target).item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() print(f"Test Accuracy: {100. * correct / len(test_loader.dataset)}%")
(2) 部署模型
- 导出模型为ONNX格式或使用框架工具(如TorchScript): python
深色版本
torch.onnx.export(model, torch.randn(1, 3, 224, 224), "model.onnx")
9. 常见问题与解决方案
(1) 过拟合
- 解决方法:
- 增加数据增强(如随机裁剪、翻转)。
- 添加正则化(如Dropout、L2正则化)。
- 减少模型复杂度或训练轮次。
(2) 欠拟合
- 解决方法:
- 增加训练轮次或学习率。
- 解冻更多层(释放模型潜力)。
- 尝试更复杂的模型架构。
(3) 计算资源不足
- 解决方法:
- 使用小批量(如batch_size=16)。
- 使用模型量化或知识蒸馏(Knowledge Distillation)。
- 选择轻量级模型(如MobileNet、DistilBERT)。
10. 总结:微调的流程图
深色版本
1. 确定任务和数据 →
2. 选择预训练模型 →
3. 数据预处理 →
4. 修改模型尾部 →
5. 设置超参数 →
6. 训练并监控 →
7. 调参优化 →
8. 评估与部署
附录:代码示例(文本分类)
以下是一个完整的微调BERT进行文本分类的代码框架:
python
深色版本
import torch
from transformers import BertTokenizer, BertForSequenceClassification
from torch.utils.data import Dataset, DataLoader
# 加载预训练模型和分词器
model_name = "bert-base-uncased"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=num_classes)
# 数据预处理
class TextDataset(Dataset):
def __init__(self, texts, labels):
self.encodings = tokenizer(texts, truncation=True, padding=True, max_length=512)
self.labels = labels
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
item = {k: torch.tensor(v[idx]) for k, v in self.encodings.items()}
item["labels"] = torch.tensor(self.labels[idx])
return item
# 加载数据
train_dataset = TextDataset(train_texts, train_labels)
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
# 训练配置
device = torch.device("cuda")
model.to(device)
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)
criterion = nn.CrossEntropyLoss()
# 训练循环(参考步骤6)
关键点回顾
- 微调的核心:利用预训练模型的通用特征,仅针对特定任务调整部分参数。
- 数据质量:垃圾进,垃圾出(Garbage In, Garbage Out)。
- 超参数调优:学习率、批量大小、层冻结策略是关键。