原帖: http://www.cnblogs.com/edwardbi/p/5647522.html
原帖GitHub: https://github.com/edwardbi/DeepLearningModels/tree/master/RCNN
少量代码需要修改 尤其是缩进的问题!!
修改后的Github:https://github.com/UncleLLD/RCNN/ 修改地方可以参考下,也许是自己的版本问题,有过一些报错。
最后以修改缩进以及python3版本运行完成重现
两周多的努力总算写出了RCNN的代码,这段代码非常有意思,并且还顺带复习了几个Tensorflow应用方面的知识点,故特此总结下,带大家分享下经验。理论方面,RCNN的理论教程颇多,这里我不在做详尽说明,有兴趣的朋友可以看看这个博客以了解大概。
系统概况
RCNN的逻辑基于Alexnet模型。为增加模型的物体辨识率,在图片未经CNN处理前,先由传统算法(文中所用算法为Selective Search算法)取得大概2000左右的疑似物品框。之后,这些疑似框被导入CNN系统中以取得输出层前一层的特征后,由训练好的svm来区分物体。这之中,比较有意思的部分包括了对经过ImageNet训练后的Alexnet的fine tune,对fine tune后框架里输出层前的最后一层特征点的提取以及训练svm分类器。下面,让我们来看看如何实现这个模型吧!
代码解析
为方便编写,这里应用了tflearn库作为tensorflow的一个wrapper来编写Alexnet,关于tflearn,具体资料请点击这里查看其官网。
那么下面,让我们先来看看系统流程:
第一步,训练Alexnet,这里我们运用的是github上tensorflow-alexnet项目。该项目将Alexnet运用在学习flower17数据库上,说白了也就是区分不同种类的花的项目。github提供的代码所有功能作者都有认真的写出,不过在main的写作以及对模型是否支持在断点处继续训练等问题上作者并没写明,这里贴上我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
同时,我们希望可以检测模型是否运作正常。以下是检测Alexnet用代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
到此为止,我们跟RCNN还没有直接的关系。不过,值得注意的是,我们之前保存的那个训练模型model_save.model文件就是我们预训练的Alexnet。那么下面,我们开始正式制作RCNN系统了,让我们先编写传统的框架proposal代码吧。
鉴于文中运用的算法是selective search, 对这个算法我个人没有太接触过,所以从头编写非常耗时。这里我偷了个懒,运用python现成的库selectivesearch去完成,那么,预处理代码的重心就在另一个概念上了,即IOU, interection or union概念。这个概念之所以在这里很有用是因为一张图片我们人为的去标注往往只为途中的某一样物体进行了标注,其余的我们全部算作背景了。在这个概念下,如果电脑一次性选择了许多可能物品框,我们如何决定哪个框对应这物体呢?对于完全不重叠的方框我们自然认为其标注的不是物体而是背景,但是对于那些重叠的方框怎么分类呢?我们这里便使用了IOU概念,即重叠数值超过一个阀门数值我们便将其标注为该物体类别,其他情况下我们均标注该方框为背景。更加详细的讲解请点击这里。
那么在代码上我们如何实现这个IOU呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
之后,我们便可以在fine tune Alexnet时以0.5为IOU的threthold, 并在训练SVM时以0.3为threthold。达成该思维的函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
|
需要注意的是,这里输入参数的svm当为True时我们便不需要用one hot的方式表达label了。
在预处理了输入图片后,我们需要用预处理后的图片集来fine tune Alexnet。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
运用这两个函数可完成对Alexnet的fine tune。到此为止,我们完成了对Alexnet的直接运用,接下来,我们需要读取alexnet最后一层特征并用以训练svm。那么,我们怎么取得图片的feature呢?方法很简单,我们减去输出层即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
在得到features后,我们需要训练SVM。为何要训练SVM呢?直接用CNN的softmax就好不就是么?这个问题在之前提及的博客里有提及。简而言之,SVM适用于小样本训练,这里这么做可以提高准确率。训练SVM的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
在识别物体的时候,我们该怎么做呢?首先,我们通过一下函数得到输入图片的疑似物体框:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
该过程与预处理中函数类似,不过更简单,因为我们不需要考虑对应的label了。之后,我们将这些图片一个一个的输入网络以得到相对输出(其实可以一起做,不过我的电脑总是kill了,可能是内存或者其他问题吧),最后,应用cascaded的SVM就可以得到预测结果了。
大家对于试验结果一定很好奇。以下结果是对比了Alexnet和RCNN的运行结果。
首先,让我们来看看对于以下图片的结果:
对它的分析结果如下:在Alexnet的情况下,得到了以下数据:
判断为第四类花。实际结果在flower 17数据库中是最后一类,也就是第17类花。这里,第17类花的可能性仅次于第四类,为34%。那么,RCNN的结果如何呢?我们看下图:
显而易见,RCNN的正确率(1类)非常之高。
下面是本人的实践过程:
1.环境: Tensorflow version 0.7.1. Python version 2.7 ,scikit-learn dev distribution package.以及安装 tflearn( github at https://github.com/tflearn/tflearn),还记得要安装 selective search , pip install selectivesearch.
Training Input: 17 flowers 数据集下载: https://github.com/ck196/tensorflow-alexnet. 下载完毕后将数据集保存到本文GitHub位置处作为网络的预训练数据。
2.运行代码:终端目录进入github文件
1.运行train_alexnet.py 训练alexnet网络,会生成model_save.model等文件,注意由于tf的版本不同,生成的文件数量也不一样,大致都是model文件
2.运行fine_tune_RCNN.py文件,使用文件夹中自带的2flowers数据库微调,按照原作者的代码,这里会报错no file to load, error。在看相关解答后
原因是tflearn的save模型在tensorflow最新版本上无法正确保存成tflearn文件,而是保存成了三个文件(.data-0000-of-00001/index/meta)。
将fine_tune_RCNN中的fine_tune_Alexnet函数进行如下修改,会运行成功。
3.运行RCNN_output.py文件分类图像