1.数据增广
在一个已有的数据集上,使得有更多的多样性。例如改变图像的颜色、亮度、色温、形状。每次随即在线生成数据。
常见数据增强:
- 反转:左右、上下翻转(并不总是可行)
- 切割:从图片中切割一块,然后变形到固定形状。一般最后正形成224x224,因为ImageNet上像224x224。随机高宽比,随机大小,随机位置。
- 变色:改变色调、饱和度、明亮度
在torchvision中的normalize,是从ImageNet数据集上计算得到的,是ImageNet数据集上图像三通道的的均值和方差。微调,使用预训练模型的时候,需要使用。
2.微调
标注一个数据集很贵。现在用的ImageNet有120万张图像,类别数1000;MNIST有6万张样本,类别数10。希望能在很大的数据集上训练好的模型能够帮助提升自己训练集的精度。微调通常速度更快,精度更高。
一般来说,神经网络可以分成两块:特征抽取,将原始像素变成容易线性分割的特征;线性分类器,来做分类。
将在ImageNet上训练的模型用到自己的模型的时候,特征抽取部分仍然使用,但是最后的分类器因为标号不一样就丢弃了,采用随机初始化。训练的时候,使用更小的学习率,是用更少的数据迭代;源数据集复杂于目标数据,通常微调效果更好。
几个技巧:
- 重用分类器权重:源数据集可能也有目标数据中的部分标号,可以使用预训练好的模型分类器中对应标号权重来做初始化,没有标号的就随机初始化。
- 固定一些层:神经网络底层学习一些边边角角的纹理等特征,越高的层学习语义特征。所以低层次特征更加通用,高层次的特征更跟数据集相关。当数据较少容易过拟合的时候,可以固定底部一些层的参数,不参与更新,相当于模型变小了,更强的正则。
- 在训练时特征抽取部分学习率小一些,分类器学习率大一些。
net = torchvision.models.resnet50(pretrained=True) # 加载预训练模型
net.fc = nn.Linear(net.fc.in_features, 2) # 更改最后一层分类器,改为二分类
nn.init.xavier_uniform_(net.fc.weight) # 最后一层随机初始化