迁移学习-用inception model实现新的分类器
利用google的inception-v3模型作为图片的特征提取器,将想要分类的图片输入到这个已经训练好的model里面,输出提取的信息。然后再自己建立一个MLP网络对这些信息进行分类训练。
例子中用了flower data,这里面有5种类型的花,没有作为训练集出现在inception-v3模型中。从网上下载了这个花的数据后,会发现这些数据都是以jpeg格式存储的,而且每个图片的大小不一,所以第一步是要建立一个索引函数,将花图片的地址都提取出来
参考程序是:
TensorFlow实战Google深度学习框架》6.5.2小节 卷积神经网络迁移学习
但是这个程序的结构弄的比较复杂,而且在每次得到一张图片的时候会在文件内查找是否遇到过这个图片,这种o(n^2)的查找会使得图片转成特征的时间非常的长。
在我的程序中,并不查找是否计算过这些图片,实际上,我的做法是直接将数据集内的所有图片输入到model中转换成特征矩阵,然后把这个矩阵存起来。后面的步骤就和处理MNIST数据一样简单了
1.提取目录下的花图片的地址
下面的函数将目录下的花的图片按 8:2的比例分成训练集和测试集,注意里面的内容是图片的地址,并不是图片
2.将图片地址转换成绝对地址
因为上面的函数执行后的到的地址是各自的文件夹里面图片的名称,如果要读取这些图片的话需要得到图片的绝对地址,下面这个函数就是执行这样的功能的
3.得到图片的绝对地址后,就可以读取这张图片并将内容送入inception model里面提取特征。
因为图片的大小不一,没有办法以矩阵的形式输入。当然可以对图片进行一下data augment同时统一一下图片的大小。这样就可以按batch来读取图片并输入到model里面去,加快运算
4.上面的函数出现了两个tensor,image_tensor是在inception 的图里面定义的输入节点,bottleneck_tensor是倒数第二层的输出,当然我们需要在程序里面定义这些tensor来自哪里。这里就用到了网络上下载的inception 模型了
5.将得到的特征矩阵保存下来
因为每张图片输出的特征都是1*2048,可以将这些特征组成矩阵,然后用pickle储存。这样就可以得到处理好的特征数据,然后自己建立一个MLP网络对这些特征进行训练就可以得到很好的效果
6.总结
实际上程序的逻辑是很简单的:得到所有图片的绝对地址 ->一张张的读取图片,送入inception model里面计算特征 ->将所有计算出来的特征保存下来
在得到了所有花图片的特征矩阵后,建立一个两层的MLP对这些特征进行分类,在经过不到1分钟的迭代(GPU上运行)就可以达到90%的准确率,但是即使增加训练时间,准确率也是维持在90%左右。提高准确率的方向有:
1.数据增强,对图片进行翻转,调色,随机截取等增大训练集
2.得到更高层的inception model输出,在采用其他模型来训练分类。在这个例子中,是用的倒数第二层的输出作为特征,可以去更加上层的输出作为特征,一般来说,越往上的tensor提取的是更广义的图片特征(如图片的轮廓特征等),越靠近输出的tensor是越针对分类目标的特征。