使用skorch实现迁移学习的完整指南
skorch 项目地址: https://gitcode.com/gh_mirrors/sko/skorch
什么是迁移学习
迁移学习(Transfer Learning)是机器学习中一种重要的技术,它允许我们将一个预训练模型的知识迁移到新的任务上。这种方法特别适用于深度学习领域,因为从头开始训练深度神经网络通常需要大量数据和计算资源。
在计算机视觉领域,迁移学习尤为常见。我们可以利用在大型数据集(如ImageNet)上预训练的模型,通过微调(fine-tuning)或特征提取(feature extraction)的方式,将其应用于新的、通常规模较小的数据集上。
skorch项目简介
skorch是一个将PyTorch与scikit-learn无缝集成的Python库,它提供了scikit-learn风格的API来训练PyTorch神经网络。这使得我们可以利用scikit-learn强大的工具生态系统(如网格搜索、管道等)来处理PyTorch模型。
准备工作
安装必要的库
在开始之前,我们需要确保安装了以下Python库:
- torch
- torchvision
- skorch
- numpy
数据集介绍
本教程使用的是蚂蚁和蜜蜂的二分类数据集,包含:
- 训练集:每个类别120张图片
- 验证集:每个类别75张图片
数据集已经预先划分为训练集和验证集,这有助于我们评估模型的泛化能力。
数据预处理
数据增强
对于训练数据,我们应用了以下增强技术:
- 随机裁剪到224x224大小
- 随机水平翻转
这些技术有助于增加数据的多样性,防止模型过拟合。
数据标准化
所有图像都进行了标准化处理,使用了ImageNet数据集的均值和标准差:
- 均值:[0.485, 0.456, 0.406]
- 标准差:[0.229, 0.224, 0.225]
使用这些特定值是因为我们的预训练模型是在ImageNet上训练的,保持一致的预处理有助于模型更好地工作。
构建预训练模型
我们使用ResNet18作为基础模型,这是一个在ImageNet上预训练的中等规模卷积神经网络。
class PretrainedModel(nn.Module):
def __init__(self, output_features):
super().__init__()
model = models.resnet18(pretrained=True)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, output_features)
self.model = model
def forward(self, x):
return self.model(x)
关键点:
- 我们保留了除最后一层外的所有预训练权重
- 替换了最后的全连接层以适应我们的二分类任务
- 输出特征数设为2(蚂蚁和蜜蜂两个类别)
使用skorch配置训练
学习率调度器
我们使用StepLR调度器,每7个epoch将学习率乘以0.1:
from skorch.callbacks import LRScheduler
lrscheduler = LRScheduler(
policy='StepLR', step_size=7, gamma=0.1)
这种学习率衰减策略有助于模型在训练后期更精细地调整权重。
模型检查点
设置检查点回调以保存最佳模型:
from skorch.callbacks import Checkpoint
checkpoint = Checkpoint(
f_params='best_model.pt', monitor='valid_acc_best')
这会监控验证集准确率,并在达到新高时保存模型。
冻结层
我们冻结了除最后一层外的所有权重:
from skorch.callbacks import Freezer
freezer = Freezer(lambda x: not x.startswith('model.fc'))
这种策略称为"特征提取",即只训练新添加的分类层,而保持预训练特征提取器的权重不变。
完整的神经网络分类器
将所有组件组合起来:
net = NeuralNetClassifier(
PretrainedModel,
criterion=nn.CrossEntropyLoss,
lr=0.001,
batch_size=4,
max_epochs=25,
module__output_features=2,
optimizer=optim.SGD,
optimizer__momentum=0.9,
iterator_train__shuffle=True,
iterator_train__num_workers=2,
iterator_valid__num_workers=2,
train_split=predefined_split(val_ds),
callbacks=[lrscheduler, checkpoint, freezer],
device='cuda'
)
配置详解:
- 使用交叉熵损失函数
- 初始学习率0.001
- 批量大小4(可根据GPU内存调整)
- 训练25个epoch
- 使用带动量的SGD优化器
- 启用数据加载器的多线程
- 使用验证集进行模型选择
- 在GPU上训练(如果可用)
训练过程分析
从训练日志可以看到:
- 初始验证准确率就很高(94.77%),这得益于预训练模型的特征提取能力
- 随着训练进行,损失持续下降
- 第5个epoch达到最高验证准确率96.08%
- 学习率在第7个epoch后下降,导致训练损失变化趋缓
这种表现说明:
- 迁移学习非常有效,即使只训练最后一层也能获得很好的结果
- 预训练模型已经学习到了通用的图像特征
- 我们的微调策略是合适的
实际应用建议
- 数据量较小时:建议冻结大多数层,只训练最后的分类层
- 数据量适中时:可以解冻更多层进行微调
- 计算资源有限时:考虑使用更小的预训练模型(如ResNet18而非ResNet50)
- 不同领域数据:如果新数据与预训练数据差异很大,可能需要解冻更多层
常见问题解决
- 过拟合:增加数据增强、使用更小的学习率、添加Dropout层
- 训练不稳定:减小学习率、增大批量大小、使用学习率预热
- 内存不足:减小批量大小、使用更小的模型、尝试混合精度训练
总结
通过本教程,我们学习了如何使用skorch实现迁移学习。关键点包括:
- 利用预训练模型作为特征提取器
- 替换并训练最后的分类层
- 使用skorch的简洁API配置训练过程
- 应用各种回调函数增强训练控制
迁移学习是深度学习实践中极其重要的技术,而skorch使得这一过程更加简单和可维护。希望本教程能帮助你快速上手迁移学习在实际项目中的应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考