1. 迁移学习
2. 预训练模型
3. 使用预训练模型
4. 运用预训练模型
? 提取特征(extractfeatures)
? 优化模型(finetune the model)
5. 优化模型的方式
6. 在数字识别中使用预训练模型
? 只针对输出密集层(outputdense layer)的重新训练
? 冻结初始几层网络的权重因子
1什么是迁移学习?
我们知道,神经网络需要用数据来训练,它从数据中获得信息,进而把它们转换成相应的权重。这些权重能够被提取出来,迁移到其他的神经网络中,我们“迁移”了这些学来的特征,就不需要从零开始训练一个神经网络了。
现在,让我们从自身进化的角度来讨论这种迁移学习的重要性。这是Tim Urban最近在waitbutwhy.com上的一篇文章中提出的观点。
2. 什么是预训练模型?
简单来说,预训练模型(pre-trained model)是前人为了解决类似问题所创造出来的模型。你在解决问题的时候,不用从零开始训练一个新模型,可以从在类似问题中训练过的模型入手。
比如说,如果你想做一辆自动驾驶汽车,可以花数年时间从零开始构建一个性能优良的图像识别算法,也可以从Google在ImageNet数据集上训练得到的inception model(一个预训练模型)起步,来识别图像。
一个预训练模型可能对于你的应用中并不是100%的准确对口,但是它可以为你节省大量功夫。
接下来,我会举个例子来说明。
3. 为什么我们要用预训练模型?
上周我一直在尝试解决Crowdanalytix platform上的一个问题:从手机图片中分辨场景。
这是一个图像分类的问题,训练数据集中有4591张图片,测试集中有1200张图片。我们的任务是将图片相应地分到16个类别中。在对图片进行一些预处理后,我首先采用一个简单的MLP(Multi-laterPerceptron)模型,结构如下图所示:
在对输入图片(224*224*3)平整化后,为了简化上述结构,我用了三个各含有500个神经元的隐藏层。在输出层中,共有16个神经元对应着十六个类别。
我只能将训练的准确率控制在6.8%,这是个很不理想的结果。我尝试对隐藏层、隐层中神经元的数量以及drop out速率进行调整,但准确度都没有太大的提升。而如果增加隐藏层和其中神经元的数量,每个周期的运行时间则会增加20s以上。(我的开发环境是12GBVRAM,Titan X GPU)
下面是我用上文所述结构的MLP模型训练输出的结果。
可以看出,除非指数级地增加训练时长,MLP模型无法提供给我更好的结果。因此,我转而采用CNN(卷积神经网络),看看他们在这个数据集上的表现,以及是否能够提高训练的准确度。
CNN的结构如下:
我使用了3个卷积的模块,每个模块由以下部分组成:
· 32个5*5的filter
· 线性整流函数(ReLU)作为激活函数
· 4*4的最大值池化层
最后一个卷积模块输出的结果经过平整化后会被传递到一个拥有64的神经元的隐藏层上,随后通过一个drop out rate = 0.5处理后传递到输出层。
最终训练的结果记录如下:
准确率15.75%,尽管与MLP模型相比有所提升,但每个周期的运行时间也增加了。
而更重要的是,数据集中最大类别所含图片数量约占总数17.6%左右。
只要把所有的图片都归到最大的类别,我们就能够得到比MLP、CNN训练出来的模型更好的结果(ノへ ̄、)。
此外,增加更多的卷积模块也会大大增加训练时长。
于是,我转而去采用预训练模型,这样我不需要重新训练我的整个结构,只需要针对其中的几层进行训练即可。
因此,我采用了在ImageNet数据集上预先训练好的VGG16模型,这个模型可以在Keras库中找到。
模型的结构如下所示:
在VGG16结构的基础上,我只将softmax层的1000个输出改为16个,从而适应我们这个问题的情景,随后重新训练了dense layer。
导入必要的库
from keras.models import Sequential
from keras.layers.core import Flatten, Dense, Dropout
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.optimizers import SGD