tensorflow学习笔记十六:tensorflow官方文档学习 如何训练Inception v3模型最后一层

利用Tensorflow训练图像分类的模型

我在刚进行训练模型的时候,是想靠自己拆开一个模型,之后再进行训练的方法。后来发现在我不彻底弄清模型的原理并搞到模型的源码之前我是不可能去训练的。后来发现tensorflow就提供了这样一个工具,它虽然没有公开深度学习网络的模型源码,却给出了保存好的模型和训练的代码。这样就直接可以拿来训练了。

这个模型是谷歌的Inceptionv3http://arxiv.org/abs/1512.00567)。在2012年的imageNet上进行训练,并在2012ImageNet上取得了3.4%top-5准确率(人类的只有5%

 

这么一个复杂的网络若是直接自己训练,起码需要几天甚至十几天的时间。所以这里我采用迁移学习的方法。即前面的层的参数都不变,而只训练最后一层的方法。最后一层是一个softmax分类器,这个分类器在原来的网络上是1000个输出节点(ImageNet1000个类),所以需要删除网络的最后的一层,变为所需要的输出节点数量,然后再进行训练。

Tensorflow中采用的方法是这样的:将自己的训练集中的每张图像输入网络,最后在瓶颈层(bottleneck),就是倒数第二层,会生成一个2048维度的特征向量,将这个特征保存在一个txt文件中,再用这个特征来训练softmax分类器。

具体的方法如下:

1.编译和预处理

tensorflow的根目录下的命令行中输入编译retrian的命令:

bazel build tensorflow/examples/image_retraining:retrain。如果您的电脑比较新,建议用这个命令来编译:

bazel build -c opt --copt=-mavx tensorflow/examples/image_retraining:retrain

这两种方法我都试过,后面一种在提取bottleneck特征的时候比前面的一种快了10倍左右。

编译完成后,实际上就可以使用了,就是这么简单。但是建议还是改动一下tensorflow/examples/image_retraining目录下的retrainpython脚本,因为里面的默认路径是/tmp,这个文件夹一旦电脑关机所有数据都会清除。建议把里面所有的这个路径都改为另外的路径。之后在该路径下将自己的训练数据集放好。

训练数据集是有格式要求的:

a.数据集应该这样设置,训练集文件夹下放置多个子文件夹,每个子文件夹就是一个类,里面包含该类的所有图像。

b.图像应该是jpg或者jpeg格式。

 

2.训练

在设置好数据集后,运行

bazel-bin/tensorflow/examples/image_retraining/retrain --image_dir ~/XXX

image_dir ~/XXX是训练数据集的路径XXX是数据集的名称。

这时就开始训练了。训练过程中会首先下载原来的Inception网络,保存在ImageNet的文件夹下。

 

第一个文件是网络的图结构,第二个文件是一个测试图像,第三个一个映射,从最后1000个节点中的而每一个映射到一个编码,第四个也是一个映射,是从编码映射到人能够识别的名词,例如:节点的表示是第234个节点,而这个节点映射到的编码是nb20003,这个编码映射到的名词是熊猫(仅举例,数字和编码以及名词是随意假设的)。这些映射关系和编码是在ImageNet 2012测试集中定义的。

下载后开始提取每张训练图像的bottleneck特征。这个过程大概1s提取5张图像。在提取完成后就开始训练。训练过程比较快。下面是我的训练结果,我训练了8000(可以在retrain.py中设置)次,一开始很奇怪为什么不需要设置softmax的输出节点数目,后来看了代码才知道它是根据训练集中的类别数量来自动设置的。

下面是我的训练结果:

 

最后的测试结果是93.2%。这个成绩好么?其实并不好,这说明这个模型的15个类的Top5的准确率比ImageNet1000个类的Top5准确率还低。但是鉴于没有那么多的训练数据集和那么多的时间来从头训练整个网络,这个结果已经算是还不错。

 

这时候如果打开image_dir路径,可以在下面发现多处了两个文件,分别是output.pboutput.txt。第一个文件是训练后的图结构,第二个是从节点到名词的映射,这里不会给出中间的编码映射——除非您自己定义一个映射关系。

接下来怎么利用训练好的模型来进行训练呢?首先还是回到下载下来的ImageNet文件夹中,这时候如果运行tensorflow/model/ImageNet中的classify.py,会发现命令行中出现如下:

 

这是对文件夹中的测试图像进性预测的结果。

这时,我们将训练出的output_graph文件放到该文件夹下,替换掉原有的图文件(可以把output_graph文件重命名为原来的图文件名,这样就不需要改动代码了)。再运行classfy.py文件就可以用自己的模型来对图像进行分类了。给出的结果是Top5对应的节点数以及相应的概率。如果需要输出名词,需要自己定义映射关系。

但是这样还是只会对一张图像进行分类,我改动了classify_image的脚本,让它可以对多个文件分类。如果您想自己尝试改写脚本让它可以对多个文件分类,那可能您会遇到这样的情况:大概在预测10几个文件后,突然报错,说图的结构不能大于2G,这是因为每训练一个图,就会在图中增加一个点,当增加到一个程度,图的结构就会超过2G。这需要在每训练一个图片后重置图,在我改写的脚本中已经克服了这个问题,但是这也使得分类的速度变慢,大概1.5s一张图像。这个脚本会输出top-2的准确率,如下:

 

分别是文件名,top1结果,top1置信度,top2结果,top2置信度。

 

我改动后的,可以支持多图像输入的classify_image可以在:   http://pan.baidu.com/s/1qYq3yck中获得。

 

总结

 

这是我近十天来摸索tensorflow的心得(前面时间摸索Overfeat了)。Tensorflow的上手还是比较难得,它的一些思想理念(图和张量)还是很难理解的。比较重要的心得是Dont be a hero。有问题不要闭门造车,如果尝试了下没解决就第一时间找人交流,如果别人也没有解决方法,再想办法从网上搜,再实在没办法再去看源码和问题提示自己找问题所在。此外,还了解一些包括linux还有python的工具,相信这会对我后面的学术和工程都有帮助。

但是还是感觉走了很多的弯路,中间浪费了太多现在看起来可以避免浪费的时间,我想这就是因为我没有跟他人交流很多的原因吧。

展开阅读全文

没有更多推荐了,返回首页