由于科研要求,我必须要进行跑实验,本来想着在window10系统上跑实验的,一方面是win10系统的环境太难配了,另一方面,Faster RCNN的实验教程大部分都是Ubuntu上的。最后还是在ubuntu上来进行实验。

参考:




1. 模型代码下载:

github地址:https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0

网上都说这个模型比较简单运行,还有说不支持python3.6以上版本的,但是我在配置环境时,忘记了切换相应的虚拟环境,在基环境下也运行成功了。

我的环境是:ubuntu16.04+CUDA9+torch1.3.1+python3.7.5

由于实验环境是以前配置的,在这里我就不在详细的介绍环境的配置过程。

首先下载上面的那个源码,不管是用命令还是自动下载,自己看着办。

命令:

git clone -b pytorch-1.0 --single-branch --depth=1 --recursive https://github.com/jwyang/faster-rcnn.pytorch.git

其中:-b是分支名,--single-branch是clone指定分支的命令,--depth==1是只克隆最近一次更改,--recursive用于循环递归克隆子项目。 

fastrcnn训练自己的数据集linux_github

2.创建数据文件夹

把下载到本地的压缩文件解压到一个位置,然后cd 到文件夾内,并在内部创建一个名为data空文件夾

cd faster-rcnn.pytorch-pytorch-1.0
mkdir data

3.下载数据

cd 到data文件夾中

下载压缩的数据集文件

wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar

执行下方命令解压数据到data/VOCdevkit(其实解压后会自动生成一个名为VOCdevkit的文件夾)

tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar

zui在data文件夹内,用下命令创建软链接(其实哇创建软链接后面还是会出现路径问题,在这直接把VOCdevkit改为VOCdevkit2007最好不过 )

ln -s VOCdevkit的绝对路径 VOCdevkit2007

4. 首先在data中创建一个名为pretrained_model文件,

下载预训练模型到/data/pretrained_model中,

上面那个链接中有VGG16,ResNet101的预训练模型

fastrcnn训练自己的数据集linux_github_02

 

fastrcnn训练自己的数据集linux_python_03

 

 

代码faster-rcnn.pytorch-1.0\lib\model\faster_rcnn\resnet.py中

self.model_path = 'data/pretrained_model/resnet101_caffe.pth'

是resnet的预训练模型存放地址;

fasterRCNN = resnet(imdb.classes, 101, pretrained=True, class_agnostic=args.class_agnostic)

pretrained=True表示训练时使用预训练模型
 

5.编译

需要返回工程根目录中如我的是../faster-rcnn.pytorch-pytorch-1.0下

使用pip安装所有python依赖包

pip install -r requirements.txt

编译CUDA依赖环境

cd lib
python setup.py build develop

6. 训练

在训练之前需要根据自己的环境将trainval_net.py和test_net.py中的save_dir和load_dir参数进行更改。(这一步我没有操作)
使用VGG16在pascal_voc上训练faster R-CNN使用如下命令:(中断的话,重新使用训练命令就行)

CUDA_VISIBLE_DEVICES=0,1 python trainval_net.py --dataset pascal_voc --net res101 --cuda

或(意思一样)

CUDA_VISIBLE_DEVICES=$GPU_ID python trainval_net.py \
                   --dataset pascal_voc --net vgg16 \
                   --bs $BATCH_SIZE --nw $WORKER_NUMBER \
                   --lr $LEARNING_RATE --lr_decay_step $DECAY_STEP \
                   --cuda
  • “CUDA_VISIBLE_DEVICES”指代了gpu的id,这得看你实验室服务器哪块gpu是闲置的。(命令: nvidia-smi)
  • “–dataset”指代你跑得数据集名称,我们就以pascal-voc为例。
  • “–net”指代你的backbone网络是啥,我们以vgg16为例。
  • "–bs"指的batch size。
  • “–nw”指的是worker number,取决于你的Gpu能力,我用的是1050ti,所以选择4。稍微差一些的gpu可以选小一点的值。
  • “–cuda”指的是使用gpu。

训好的model会存到models文件夹底下,此处暂时使用默认的训练参数。

如我的命令为

CUDA_VISIBLE_DEVICES=0 python trainval_net.py \
                   --dataset pascal_voc --net vgg16 \
                   --bs 1 --nw 4 \
                   --lr 0.00001 \
                   --cuda

fastrcnn训练自己的数据集linux_github_04

####踩坑点###

训练的时候出现

ImportError: cannot import name 'imread' from 'scipy.misc'问题的解决办法

解决方案:是因为自己现在的版本太高,需要降低版本

两种解决方法:

参考链接:

pip install scipy==1.2.0
from imageio import imread
  1. #使用imageio库同样能够完成此功能

#####踩坑点#####

RuntimeError: cuda runtime error (38) : no CUDA-capable device is detected.....

解决方法:

1、首先检查显卡驱动版本号和cuda版本号是否兼容,结果兼容。

2、我是单卡训练,将DEVICE_ID由‘2’改成‘0’后,问题解决。

 

 

运行以上的的训练命令我是运行成功了,但是忘记来截图。

7. 测试

如果想评估VGG16预训练模型在pascal_voc测试集上的表现,在根目录下,使用如下命令:

python test_net.py --dataset pascal_voc --net vgg16 \
                   --checksession $SESSION --checkepoch $EPOCH --checkpoint $CHECKPOINT \
                   --cuda

@@可以根据生成训练得到模型的名称给checksession、checkepoch、checkpoint赋值。 

 注意,这里的三个check参数,是定义了训好的检测模型名称,我训好的名称为faster_rcnn_1_3_10021,代表了checksession = 1,checkepoch = 3, checkpoint = 10021,这样才可以读到模型“faster_rcnn_1_3_10021”。训练中,我设置的epoch为20,但训练到第3批就停了,所以checkepoch选择3,也就是选择最后那轮训好的模型,理论上应该是效果最好的。当然着也得看loss。

fastrcnn训练自己的数据集linux_CUDA_05

8.运行demo

将待检测的图片放到/images文件夹中,使用如下命令:

python demo.py --net vgg16 \
               --checksession $SESSION --checkepoch $EPOCH --checkpoint $CHECKPOINT \
               --cuda --load_dir + 模型存放文件夹

参数的意义:

    –dataset pascal_voc:用pascal数据集
    –net res101:用res101作为特征提取网络,可选vgg16
    –cfg cfgs/res101.yml:加载res101的配置
    –load_dir models --checksession 1 --checkepoch 28 --checkpoint 2813:这四个参数共同决定读取models/文件夹中训练好的faster_rcnn_1_28_2813.pth权重文件
    –image_dir path/to/your/image:需要批量检测的图像文件路径
    –bs 1:batch_size=1
    –cuda:使用cuda
    测试好的图片输出在与images相同的文件夹内,其命名为原图名字+_det。

python demo.py --net vgg16  --checksession 1  --checkepoch 20 --checkpoint 1291 --cuda --load_dir models

demo测试会检测images路径下的图片,images从官网下载后的图片有12个,但其中×××_det.jpg的8张都是作者在测试的结果,因此需要删除这8张再进行测试
 

得到如下图所示的结果:

fastrcnn训练自己的数据集linux_CUDA_06

遇到的问题及解决

1.出现can not import _mask

# 进入faster rcnn项目的data文件夹
cd data
 
git clone https://github.com/pdollar/coco.git 
 
cd coco/PythonAPI
 
make
 
cd ../../..

1.##下载cocoapi代码
git clone https://github.com/cocodataset/cocoapi.git
 
2.##单独编译PythonAPI
cd PythonAPI
python setup.py build_ext --inplace
 
3.##删除faster-rcnn.pytorch/lib/下的pycocotools,将编译后的pycocotools文件夹复制到faster-rcnn.pytorch/lib/下
4.##现在可以在faster-rcnn中按原来的方法编译了
cd lib
python setup.py build develop

 

参考https://github.com/cocodataset/cocoapi/issues/59#issuecomment-469859646中的讨论

2、Training阶段修改:(cfg中默认roi crop)

在trainval.net种设置args.imdb_name等参数;

3、在factory.py种添加下列own-datasets的相关code,用于读取相关数据集的类文件;

4、注意在自己的数据类py脚本中修改相应的路径和类别class,注意类别一定是小写,因为在类别xml读取时都是按照小写比较的,如pascal_voc.py中:

一般voc的话路径self._devkit_path设置成了项目主目录的/data/vocdevkit+year/下,self._data_path就是/data/vocdevkit+year/voc+year/下;

5、通过将所有训练图片的format转成jpg,就不用改self._image_ext

6、pascal_voc.py中self._image_index = self._load_image_set_index()函数是读取voc相应的txt种的训练或指定测试的图片的名称,不带后缀;因此这里自己的数据集得得到这样得txt文件;

7、pascal_voc.py中self._roidb_handler = self.gt_roidb的修改,读取xml,跳过不需要的类别,可以借鉴DA_detection(strong-weak)的代码(https://github.com/VisionLearningGroup/DA_Detection)修改def _load_pascal_annotation(self, index)函数:

8、模型最终保存在output_dir = args.save_dir + "/" + args.net + "/" + args.dataset下面;默认存在model(args.save_dir)下面

9、将misc读取改成cv读取,注意rgb和bgr转换;训练时用的bgr顺序;misc读取是4通道,cv读取是3通道;misc读取时在通道减去均值出现维度不匹配问题,4通道减去3通道均值出错;

10、注意检查自己的数据集标注是否存在越界的问题,如读取时候的坐标是负数,flip时横坐标越界的问题;不然在flip时assert x2>=x1时会出错;添加get_heights()函数,得到数据的heights,用于辅助判断坐标越界问题;

11、注意sh mask.sh时sm_arch要和gpu匹配,不然cudastackerror,P100的GPU用的是sm60;

12、程序会在filter roidb时去除没有gt的图片,即训练时不需要纯负样本;