迁移学习在实际应用中需要注意什么?
写在前面
实际上,很少有人从头开始训练整个卷积网络(使用随机初始化),因为拥有足够大小数据集的情况相对较少。相反,通常是在一个非常大的数据集(例如ImageNet
,它包含120
万幅图像,1000
个类别)上预训练卷积神经网络,然后使用卷积神经网络作为初始化或固定的特征提取器来完成感兴趣的任务。
迁移方法
迁移学习主要有两种常见的实现方法:特征提取和参数微调。
特征提取
拿一个在ImageNet
上预先训练好的卷积神经网络,冻结除全连接层外的所有层的参数,修改全连接层的输出后仅训练全连接层。怎么修改全连接层的输出?在ImageNet
上训练的模型的全连接层的输出是1000
个类的分数,因为ImageNet
要分1000
类。假如你要训练的是手写数字也就是mnist
数据集,那么将这个输出改为10
就行了,因为0~9
不就是10
类嘛。
参数微调
使用预训练模型的参数来初始化我们的网络模型,修改全连接层后再继续反向传播来微调预训练模型的权值。可以对预训练模型的所有层进行微调,也可以保持一些较早的层的固定(由于过度拟合的问题),只对网络的一些较高级别的部分进行微调。研究表明,预训练模型前面的层中包含更通用的特征,对很多任务都适用,越往后的层就越反映原始数据集中各类的细节信息。
使用场景
上面讲了两种常用的迁移学习的方法,当我们训练一个新的数据集的时候具体应该选择哪一种?这受若干个因素的影响,但影响最大的主要是新数据集的尺寸(大还是小),以及它与原始数据集(预训练模型所使用的数据集)的相似度,下面是一些可以在这四个主要场景中应用的经验:
- 数据集较小,但与原始数据集相似:由于数据集较小,使用参数微调的方法会有过拟合(
overfitting
)的风险。又因为数据集与原始数据集相似度高,也就是特征相近,因此可以用特征提取的迁移学习方法。 - 数据集较大,且与原始数据集相似:数据集较大的话就不用担心过拟合了,又因为与原始数据集相似,所以可以考虑参数微调的迁移学习方法。
- 数据集较小,且与原始数据集不同:由于数据集很小,不适合使用参数微调,可以考虑特征提取。又因为与原始数据集的差异大,所以特征提取的时候需要变通一下,只冻结预训练模型的前几层参数,作为特征提取器,然后将提取的特征喂给SVM分类器。
- 数据集较大,但与原始数据集不同:这种情况下有两种选择,因为数据集较大,完全可以考虑不使用迁移学习,也就是从头开始训练,也可以使用参数微调的迁移学习方法训练整个网络。实际上,还是推荐迁移学习的方法,因为迁移学习起点高、收敛快。
数据集大小 | 和预训练模型使用数据集的相似度 | 一般选择 |
---|---|---|
小 | 高 | 特征提取 |
大 | 高 | 参数微调 |
小 | 低 | 特征提取+SVM |
大 | 低 | 从头训练或参数微调(推荐) |
实用建议
迁移学习一般不建议选择太大的学习率(learning rate
),1e-4
或1e-5
或许是一个不错的选择。既然我们选择了迁移学习,使用了预训练模型,那么我们就应该认为该预训练模型的权重是比较好的,所以不应该太快或太大的调节它们,而是微调。当然你也可以设置一个学习率调节器,让学习率根据训练的轮数(epoch
)调节,比如每5
轮训练后学习率就降低0.1
个乘法因子。学习率的自动调节在机器学习框架pytorch
和tensorflow
中都有对应的实现。
实战教程
为了更好的理解和掌握迁移学习的方法,或许实战是一个不错的选择。这里推荐一个使用迁移学习在较小的蚂蚁和蜜蜂的数据集上训练一个分类器的实例: