在alexnet的权值迁移成功后,下一步要做的就是将这个网络fine-tune成适用于自己的数据集的网络。这里我主要把这部分工作分成三部分
1.重新训练最后一层fc层
显然,最后一层fc层肯定和你想要输出的分类信息有关的,所以这一层的权值必须要重新训练
2.确定需要fine-tune的网络
最简单的情况是固定所有的权值(在初始化权值变量的时候声明此变量不可训练),只重新训练最后一层fc层,从实验结果来看这个结果比较差。fine-tune越多层网络,有可能得到更好的效果,但是耗时也越久
在我实现的例子中,我直接是在模型函数里确定哪些层是可训练的,这点只需要在声明变量的时候设置trainable参数值就可以(True表示可训练,False表示不可训练)
改进:一般来说不会将整个网络都微调(fine-tune)来适应自己的数据集,也就是说总有一些网络层是不可训练的。但是如果我们任然在训练的过程中不断循环的把image传递(feed in)到这些层中,显然这样做很耗时而且是没有意义的(因为这些层是不可学习的,同一张照片传递1次和传递10000次都是一样的效果),一种改进方法是一次性将图片传递进这些网络,保存提取下来的信息,然后再循环的将这些信息传递到可训练的网络层里面(相当于用不能fine-tune的网络来提取图片的特征信息,然后再建立网络来处理这些特征信息)
3.调整自己的数据集,满足网络的输入要求,同时可以使用数据增强(data augment)技术,扩展数据集
实验结果:
这里我用的数据集是inception模型迁移学习中用的5种花的分类
分别比较fine-tune不同层网络的效果
橙色微调网络最多:从conv5-fc6-fc7-fc8
浅蓝中间:从fc6-fc7-fc8
深蓝微调最浅的网络:fc7-fc8
可以看到从效果来说微调的网络越多效果就越好,但是耗时也会越多。
改进:
可以看到上面跑10,000个循环就花了差不多一个小时,还是有点慢的。主要优化的点在于那些不微调的网络层。
假设一张图片,在alexnet中要训练1000次,也就是每一层网络都要前向,反向这张图片1000次。对于可学习的网络层来说这样做肯定是必须的,但是对于不可学习的网络层(如conv1-conv2-con3-con4等),这样就显得没有必要了,因为这些层的参数不可改变,所以没有必要反向计算。
所以一种很直观的方法是将图片集一次传递到这些不可训练的网络中,存储起来作为特征输入。以后的训练输入就是这些特征值,下面可以看到这样做加速的训练大概6倍左右(改进前训练10000次要50min,改进后只需要8min)
微调不同层效果对比(用不能学习的网络层来提取特征):
可以看到训练1000*10次,总体来说各种方法的区别并不是很大。微调越多层的网络效果稍微好一点,但是也要花更多的时间训练。同时注意conv4-fc8方案,在训练到300次的时候表现大幅下滑,我觉得可能是因为学习率过高的关系。这也说明了微调越多层,就需要越多训练网络的技巧,训练出一个好的网络也越困难。
结论:
1.对于AlexNet模型对于没有在训练中将的图片也是有用的,特别是网络越靠近输入,其提取的特征就越具有普适性。表现在这次试验中的是微调越多的网络,得到的效果就越好
2.如果不是微调整个模型,就不要将整个模型拿来训练。也就是用不训练的层拿来做特征提取,对所有的图片只前向运算一次,将运算得到的特征作为后面网络层的输入。在本次试验中可以看到这样子做可以大大的加快训练过程。
3.关于Inception-v3与AlexNet模型在同样的一种训练集上的迁移学习效果对比:
可以看到Inception模型的效果确实是比AlexNet的效果好很多,用Inception模型提取最后一层网络的特征再重新分类,在1000次循环(大概用时1min)就能达到90%的准确率(测试集),而对于AlexNet,即使是改进后的网络训练10000次(大概8min)大概准确率(测试集)在83%左右.但是两个网络只单纯的增加训练时间是不能再提高准确率了(AlexNet维持在85%左右)