如上图,如果我们初始化W=3,那么使其往W=1的位置移动的次数就要少很多了(2/0.001次),这样相比随机初始化W的做法要好很多了。
迁移学习的做法其实说白了就是上面提到初始化W的过程。如果从零开始训练一个网络,那么W可能初始化为5(甚至更大w=10),如果使用迁移学习的方法训练一个网络,那么W可以初始化为3,这个3就是预训练好的参数,然后我们根据实际情况看是否需要再继续调整W(甚至直接使用初始化的W即可,不用再调了)。
迁移学习的前提是,这个预训练的模型要和我们待解决的问题有一定的联系,比如预训练的模型使用的数据集是各种自然花朵的照片,主要用于花型识别,而我们要解决的问题是手工绘图分类,那么这两种任务其实联系不是很大(自然花朵和手工绘图特征相差明显),这时候迁移学习没什么意义(或者说价值不大),这个时候如果使用迁移学习,那么上面W初始化的值可能就不是3了,很可能是20,那么还不如随机初始化W那种方法有效。
Tensorflow2.0中迁移学习的实现过程很简单,有很多内置的网络结构,比如ResNet、Inception系列等等,实例化对应网络类型的对象,加载预训练的权重值,然后截取该网络的一部分(主要是前面提取特征的卷积层),然后在截取的网络之上再新增自定义的分类层,主要是全连接层就行了。最后冻结截取下来的层(不用更新参数),直接用小型数据集训练新增的层参数即可。根据实际情况,我们有时候还需要解冻截取下来的若干层,让其参与一起训练,这个要看具体情况。
使用简单网络
对于我们本篇文章的二分类问题,我们只需要定义一个相对简单的网络结构就可以了,比如类似AlexNet的网络结构(甚至LeNet-5可能也可以),然后我们使用已有的小型数据集从零开始训练这个网络即可。因为网络足够简单,所以相对更容易训练好。
本次任务中,我们判断道路拥堵与否,是不需要颜色信息的,因此在自定义的简单网络结构中,我们增加了一个Lambda层,该层能将输入进行一些变换,产生输出,不需要训练任何参数。这里Lambda层主要负责去色功能,将输入的RGB图片转成灰度图片,然后再参与后面的特征提取环节。下面是我自定义的简单网络结构:
如上图所示,网络开始一个Lambda层,直接将输入的RGB图片(224*224*3)转换成灰度图片(224*224*1),然后紧接着5个卷积层(包含其他池化、归一化等层),最后加2个全连接层(神经元分别为4096和1000),最后是我们的输出层,包含2个神经元,输出一个2维向量,代表每个分类的概率。注意这里的二分类,我们也可以使用一个神经元,但是需要将输出层的softmax激活函数换成sigmoid函数,后者能将任何输入映射到0~1之间,0和1分别代表2个不同分类,同时在模型训练时我们需要选择另外一个损失函数binary_crossentropy(二分交叉熵损失函数)代替现在的categories_crossentropy损失函数(分类交叉熵损失函数)。机器学习中损失函数主要是用来衡量损失大小,也就是实际值和预测值之间的误差。再看看我们训练过程,loss值和accuracy的变化过程:
效果还不错,验证准确率最后可以到达95%,再来看看100多张测试集上的效果:
可以看到测试集上的准确率在95.8%,已经不错了。