背景
FPN的训练模型跑出来之后,实际上并未成功地进行测试,其中辛酸就不一一赘述。同时也实在不想花再多无用时间在上面,所以按照学长指示转战Detectron,来玩玩caffe2了,估计又是一场硬战,这次学聪明了,一步一步都要在csdn上记录下来。
首先来看看FAIR在github上发布的关于Detectron的内容(https://github.com/facebookresearch/Detectron)
Detectron总的来说就是FAIR的一个软件系统,它基本上实现了现有的state-of-art的目标识别算法,比如Mask R-CNN,基于python,框架是caffe2。
下面进入详细且苦逼的安装步骤,由于是借用实习公司的服务器,公司的方向是对于不同的项目不同的方法,都不直接在服务器上进行搭建,而是借用docker的形式,这样一方面的好处就是使得相互之间不受影响以及各种版本可以同时存在。
要求:
- NVIDIA GPU, Linux, Python2
- Caffe2, various standard Python packages, and the COCO API
关于这些的具体细节下面会详细介绍,需要注意的是Detectron目前只有GPU版本,而且当前Detectron主要被广泛运用到CUDA 8.0 and cuDNN 6.0.21的环境上。
步骤
1.安装caffe2(参考页面https://caffe2.ai/docs/getting-started.html)
caffe2的一个优点就是它提供了docker images,虽然它还在测试之中,而且用户也完全可以建立自己的镜像,但对于我这种小白我还是乖乖选择官方镜像了。
根据以上,我刚开始选择的是Caffe2 v0.8.0, CUDA 8, cuDNN 6这个版本,因此如下:
docker pull caffe2ai/c2v0.8.0.cuda8.cudnn6.ubuntu16.04
后来出现了以下问题:
Error response from daemon: Get https://registry-1.docker.io/v2/caffe2ai/c2v0.8.0.cuda8.cudnn6.ubuntu16.04/manifests/latest: Get https://auth.docker.io/token?account=19940608&scope=repository%3Acaffe2ai%2Fc2v0.8.0.cuda8.cudnn6.ubuntu16.04%3Apull&service=registry.docker.io: net/http: TLS handshake timeout
因此我还是选择了,
docker pull caffe2ai/caffe2
接下来就是静静等待镜像被pull完就好....
基于调研任务,我去github上看了一下这个镜像的Dockerfile(地址为https://github.com/caffe2/caffe2/blob/master/docker/ubuntu-16.04-cuda8-cudnn7-all-options/Dockerfile),基础镜像是nvidia/cuda:8.0-cudnn7-devel-ubuntu16.04,
首先是安装了一些依赖裤,然后从github上clone了caffe2,接着就是进行编译,最后设置了python的环境变量。
2.镜像pull完之后,进行测试
sudo nvidia-docker run -it caffe2ai/caffe2:latest python -m caffe2.python.operator_test.relu_op_test
# python -m (run library module as a script)意思是将库中的python模块用作脚本去运行
因此这句命令的意思就是
在镜像中运行relu_op_test这个模块,这个模块的主要用处应该是建立了relu这个operator,测试完之后输出如下:
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.02702401, 0.28464913, -0.55612934, -0.92631721, -0.36132056], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.02702395, -1. , 1. , -0.92631721, -0.36132056], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-0.02702395, -0.63771999, -0.15014511, 0.04865182], dtype=float32), gc=, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 1. , -0.68229383, 0.10905557, 0.99516845], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-1. , 1. , -1. , -0.04864699, -0.43967751], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-1. , -0.89327866, 1. , -0.0486775 ], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[[ 1. , -1. , -1. , 0.33157265],
[-0.45288479, -0.47827476, -0.40042537, -0.28126821],
[ 0.32894734, -0.68930191, -0.66700363, -0.209318 ]]], dtype=float32), gc=, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-1., 1.], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[[[-0.36056292, -0.13926618, -0.87617463, -0.35388893],
[-0.53116637, 0.92684942, 0.36650687, 0.28731996],
[-0.07220242, 0.07996514, -0.18307142, 0.05794483],
[ 0.10387799, -0.68529892, -0.94291747, 0.78173691]],
[[-0.85354322, 0.04950143, -0.72084546, 0.03790003],
[-0.28991255, -0.74402875, 0.43428981, -0.94968903],
[-0.43630224, 0.58815843, -0.24724399, 0.65797031],
[-0.50542712, -0.86659753, -0.69410872, -0.59403723]],
[[-0.58117718, -0.88710588, 0.85125881, -0.9455089 ],
[ 0.18088157, -0.11528537, -0.48710421, -0.71784741],
[-0.15499614, -0.53055173, 0.96348375, -0.41575626],
[-0.78340203, -0.58124751, 0.95865548, 0.74002224]],
[[ 0.57483822, -0.3043654 , -0.34368685, 0.76285833],
[-0.56132567, -0.66502804, 0.41430417, 0.63449377],
[-0.84852797, -0.60450375, 0.36859968, 0.76559591],
[-0.5770967 , 0.55792671, 0.42604479, -0.72375369]],
[[ 0.67973304, 0.89612186, -0.23801449, 0.51893455],
[ 0.83861935, -0.63839215, -0.24674335, 0.35054007],
[-0.9914096 , -0.74423301, 0.22639263, 0.43088418],
[ 0.1196689 , -0.41419604, -0.9801597 , -0.82656491]]]], dtype=float32), gc=device_type: 1, dc=[, device_type: 1], engine=u'CUDNN')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([-1. , -1. , -0.13732712], dtype=float32), gc=, dc=[, device_type: 1], engine=u'')
.
----------------------------------------------------------------------
Ran 1 test in 4.376s
OK
随后我们可以进入这个镜像一探究竟,
sudo nvidia-docker run -it caffe2ai/caffe2:latest /bin/bash
可以看到caffe2就处于主目录下方,
bin boot caffe2 dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
接着我就继续跟随github上的文档打算继续Detectron调研,官方是这么说的:To install Caffe2 with CUDA support, follow the installation instructions from the Caffe2 website. If you already have Caffe2 installed, make sure to update your Caffe2 to a version that includes the Detectron module.
然后我一进我的镜像,
sudo nvidia-docker run -it caffe2ai/caffe2 /bin/bash
令人尴尬的事情发生了,我怀疑dockerhub上这个镜像太老了,caffe2下面根本没有modules这个文件夹的存在。然后我再执行了文档中所说的两条命令,即
# To check if Caffe2 build was successful
python2 -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"
# To check if Caffe2 GPU build was successful
# This must print a number > 0 in order to use Detectron
python2 -c 'from caffe2.python import workspace; print(workspace.NumCudaDevices())'
输完第一条之后,人告诉我:
Success
输完第二条之后,它又告诉我:
1
然后我去看了看dockerhub上更新的时间,上次更新是7个月之前(emmm
所以我毅然决然决定,copy github上面的Dockerfile自己建新的镜像.....又是一场和网速的对抗,能否在下班之前建完是个很严重的问题....(再次进入等待阶段
后来是公司的前辈新做的一个镜像,具体是怎么做的我需要到时候去问具体细节,总之现在的镜像主目录下面除了caffe2还有detectron...像这样子
=3.0 boot cocoapi dev home lib64 mnt proc run srv tmp var
bin caffe2 detectron etc lib media opt root sbin sys usr
因为时间比较紧,其实更好的方法是每次不同的训练都建立不同的文件夹,然后里面存放每次不同的训练配置文件以及数据等等,这次我选择的方法是直接修改镜像里面的配置文件了。参考的文章是http://blog.csdn.net/meccaendless/article/details/79457330
从调研caffe2到真正上手发现数据实际上是比较困难的一个点,那时候头疼的不行,可能是我找资源的能力太差,前辈找到了上面那篇文章之后,几个人一小时不到就完成了数据的annotations转化,正所谓团结就是力量啊~
--------------------------训练自己的模型----------------------------
1.其实无论是VOC2007还是自己的数据(包括用labelImg打标签制作而成的xml文件)都首先需要将其转化成Caffe2适合的Annotation,可以通过一下脚本对我们自己的数据或者是VOC2007的数据进行转换(https://github.com/shiyemin/voc2coco
)注意:需要将所有id变为int格式。
之后文件的安置方式如下结构所示:主目录为VOC2007
.
|-- devkit
|-- JPEG
| `-- images
|-- json
| `-- annotations
`-- VOCdevkit2007
|-- annotations_cache
|-- local
| |-- VOC2006
| `-- VOC2007
|-- results
| |-- VOC2006
| | `-- Main
| `-- VOC2007
| |-- Layout
| |-- Main
| `-- Segmentation
|-- VOC2007
| |-- Annotations
| |-- ImageSets
| | `-- Main
| `-- JPEGImages
`-- VOCcode
其中比较重要的是VOC2007/json/annotations其中包括四个json文件,即pascal_test2007.json pascal_train2007.json pascal_trainval2007.json val.json,他们存储着测试、训练等图片的信息,也就是我们之前转换得到的json结构的数据;然后VOCdevkit2007主要就是同我们在网上一版下载的VOCdevkit2007的结构一样,但里面一个需要修改的地方是,VOCdevkit2007/VOCcode/ VOCinit.m,将其中的% VOC2007 classes后面的VOCopts.classes中的标签修改成我们自己的标签,其实我并不是很懂训练的过程中是否使用到了VOCinit.m这个文件。我这边的VOC2007/devkit以及/VOC2007/JPEG/images都是空的,因为我是用镜像的形式,之后会做相应的映射。
我新建了一个文件夹叫做train_with_battery_caffe2,结构如下:
.
|-- configs
| `-- getting_started
|-- detectron-visualizations
|-- lib
| `-- modeling
`-- output
|-- test
| `-- voc_2007_test
| `-- generalized_rcnn
`-- train
`-- voc_2007_train
`-- generalized_rcnn
其中configs/getting_started/下面存放的是tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml这个模型定义文件,我们这次训练的目标是想看看fpn对于小目标检测的效果是否真的像它所说的那样,因为是训练自己的数据,我对配置文件中的内容进行相应地修改,类别数改为11种(10个class+1个bg),如果网速不好建议把train下面的weights的pkl文件先下载到某个地方,然后再映射到/tmp/detectron-download-cache/ImageNetPretrained/MSRA/文件夹上去,这样就免去了训练的时候下载预训练模型文件的困扰;除此之外train部分的DATASETS:需要改为DATASETS: ('voc_2007_train',),test部分的DATASETS: 需要改为DATASETS: ('voc_2007_test',),此时模型配置文件就算修改好了。
Lib文件可有可无,因为我总怕在docker中遇到问题再修改比较麻烦,所以lib也想建立一个映射,但实际上我还是在镜像里面修改。
Output是最后训练输出的结果,detectron-visualizations文件夹也没有什么存在的必要。Emmmmmmm
最后我的训练命令如下:
sudo nvidia-docker run -it -v /media/hongpu/DATA2/yypeng/VOC2007/VOCdevkit2007:/detectron/lib/datasets/data/VOC2007/VOCdevkit2007 -v /media/hongpu/DATA2/yypeng/train_with_battery_caffe2/configs/getting_started:/detectron/configs/getting_started -v /media/hongpu/DATA2/yypeng/train_with_battery_caffe2/output:/tmp/detectron-output -v /media/hongpu/DATA2/ImageDatas/leqi_battery:/detectron/lib/datasets/data/VOC2007/JPEGImages -v /media/hongpu/DATA2/yypeng/VOC2007/json/annotations:/detectron/lib/datasets/data/VOC2007/annotations caffe2ai/caffe2:detectron_test /bin/bash -c "cd detectron && python2 tools/train_net.py --cfg configs/getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR /tmp/detectron-output"
建立的几个主要映射是VOCdevkit2007、config文件夹、最后输出文件夹的文件夹、图片数据文件夹以及annotations文件夹,然后运行train_net.py 的参数同官网一样。在网络情况良好的情况下,6w次迭代大概花费了两个半小时(1块gpu),可见caffe2的速度之快!!
最后我们可以看到在output/train/voc_2007_train/generalized_rcnn有以下输出:model_final.pkl model_iter19999.pkl model_iter39999.pkl model_iter59999.pkl net.pbtxt param_init_net.pbtxt
--------------------------------------那就跑个demo看看吧------------------------------
实际上测试自己的模型的时候,我遇到了很多问题,所以在将测试自己的模型之前,我还是尝试了一下官网的demo测试。
首先依然是建立了一个名为demo_caffe2的文件夹,结构如下:
|-- configs
| `-- getting_started
|-- detectron-download-cache
| `-- ImageNetPretrained
| `-- MSRA
|-- detectron-visualizations
`-- output
这次的模型配置文件是不需要修改的,其余的文件夹也要么是已经下载好的预训练的模型,而detectron-visualizations是为了输出而建立的文件夹。最后的跑demo的命令为:
sudo nvidia-docker run -it -v /media/hongpu/DATA2/yypeng/demo_caffe2/detectron-visualizations:/tmp/detectron-visualizations -v /media/hongpu/DATA2/yypeng/demo_caffe2/detectron-download-cache/ImageNetPretrained/MSRA:/tmp/detectron-download-cache/ImageNetPretrained/MSRA caffe2ai/caffe2:detectron_test /bin/bash -c "cd detectron && python2 tools/infer_simple.py --cfg configs/12_2017_baselines/e2e_mask_rcnn_R-101-FPN_2x.yaml --output-dir /tmp/detectron-visualizations --image-ext jpg --wts /tmp/detectron-download-cache/ImageNetPretrained/MSRA/model_final.pkl demo"
主要做了以下几个映射:detectron-visualizations——输出文件夹映射,MSRA——预训练模型文件夹映射,demo文件下是自己测试的图片,这个detectron下面已经自带了几张图片,最后测试的结果输出的格式是pdf格式。
跑完demo之后我大概明白了用infer_simple.py跑demo的原理,于是就着手开始了自己的模型的测试。
--------------------------------------测试自己的模型---------------------------------------
同样第一步新建一个文件夹test_with_battery_caffe2,结构如下:
|-- configs
| `-- getting_started
|-- demo
|-- detectron-download-cache
| `-- ImageNetPretrained
| `-- MSRA
|-- detectron-visualizations
`-- results
其中模型配置文件同训练自己的模型时候的配置文件是一模一样的,demo下面存放自己需要测试的图片,稍后会映射到容器里面去,detectron-download-cache/ ImageNetPretrained/ MSRA下面放的依然是预训练文件,results文件夹是我用来输出图片以及bbox信息的文件夹。
接下来看看我的测试命令吧:
sudo nvidia-docker run -it -v /media/hongpu/DATA2/yypeng/test_with_battery_caffe2/results:/tmp/results -v /media/hongpu/DATA2/yypeng/test_with_battery_caffe2/detectron-visualizations:/tmp/detectron-visualizations -v /media/hongpu/DATA2/yypeng/test_with_battery_caffe2/detectron-download-cache/ImageNetPretrained/MSRA:/tmp/detectron-download-cache/ImageNetPretrained/MSRA -v /media/hongpu/DATA2/yypeng/train_with_battery_caffe2/output/train/voc_2007_train/generalized_rcnn:/tmp/output -v /media/hongpu/DATA2/yypeng/test_with_battery_caffe2/demo:/detectron/demo caffe2ai/caffe2:Detectron_test /bin/bash -c "cd detectron && python2 tools/infer_simple.py --cfg configs/getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml --output-dir /tmp/detectron-visualizations --image-ext bmp --wts /tmp/output/model_final.pkl demo"
其中做的映射主要是,输出results的映射;输出打框图片结果的映射detectron-visualizations;预训练模型的映射ImageNetPretrained/MSRA;训练模型的映射output/train/voc_2007_train/generalized_rcnn以及测试图片的映射test_with_battery_caffe2/demo。最后大致解释一下输入的参数吧,cfg指向模型配置文件,output-dir指向测试图片结果输出的pdf文件夹,image-ext指定测试图片的后缀(即格式),wts指向我们训练的模型输出的pkl文件,demo指向待测试图片。
这样就完成了模型的测试!!终于!!撒花!!