Faster-rcnn环境搭建与训练自己的数据

Faster-RCNN环境搭建与训练自己的数据

0 前言

之前整理过一篇关于fasterrcnn的文章,文中详细介绍了fasterrcnn原理分析,近期由于工作需要利用fasterrcnn进行模型训练,故记录如下。

1.环境搭建与demo运行

1).配置环境

环境配置可参考:https://github.com/rbgirshick/py-faster-rcnn/blob/master/README.md,作者提供了较详细的安装步骤。

(1)在进行这一步之前,需已经在自己的机器上配置好caffe环境以及各种依赖项的安装,在配置之前,需确保已经安装以下几个python包:cython、easydict和python-opencv。安装命令如下:

pip install cython 
pip install easydict 
apt-get install python-opencv

(2)从github上clone项目,注意!一定要在clone时加入–recursive参数,不然会很麻烦,也不要直接下载,在机器上装个git来clone,这样会省去很多时间,下载的话caffe环境相关内容不能下载下来。

git clone –recursive https://github.com/rbgirshick/py-faster-rcnn.git

(3)Cython模块编译

cd $FRCN_ROOT /lib
make

(4)caffe和pycaffe的编译

在编译之前,需要复制$FRCN_ROOT/caffe-fast-rcnn 的Makefile.config.example,然后重命名为Makefile.config。

需要注意的是里面有几个配置需要添加
打开USE_CUDNN=1,这个选项默认情况下是关闭的,需要打开让CUDA支持DNN
打开WITH_PYTHON_LAYER=1,默认关闭,需打开,因为FasterRCNN需要支持Python接口。
执行以下命令进行编译

cd $FRCN_ROOT/caffe-fast-rcnn
make all -j && make pycaffe
2).运行demo

(1).下载训练好的模型,下载后这个faster_rcnn_models文件夹在$FRCN_ROOT/data下面,可以从data/README.md中查看关于这个的详细介绍。这些模型是在VOC 2007 上训练的。(可在data/scripts/fetch_faster_rcnn_models.sh文件中复制URL用迅雷下载)

(2)运行demo

cd $FRCN_ROOT

./tools/demo.py

2.训练PASCAL VOC 2007的数据集

(1)下载训练、验证以及测试集和VOCdevkit

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

(2)解压

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

文件结构如下:

$VOCdevkit/   # 开发工具包
$VOCdevkit/VOCcode/   # VOC实用代码
$VOCdevkit/VOC2007# 图片集, 注释, 等等
# 一些其他的目录

将VOCdevkit改名为VOCdevkit2007,然后放到data文件夹下,亦可以使用软连接的方式,

cd $FRCN_ROOT/data
ln -s $VOCdevkit VOCdevkit2007   

(3)下载预训练模型

cd $FRCN_ROOT
./data/scripts/fetch_imagenet_models.sh

(4)训练模型

a.使用交替优化(alternating optimization)算法来训练和测试Faster R-CNN,输出的结果在 $FRCN_ROOT/output下

cd $FRCN_ROOT
./experiments/scripts/faster_rcnn_alt_opt.sh [GPU_ID] [NET] [--set ...]
# GPU_ID是你想要训练的GPUID
# 你可以选择如下的网络之一进行训练:ZF, VGG_CNN_M_1024, VGG16
# --set ... 运行你自定义fast_rcnn.config参数,例如.
#   --set EXP_DIR seed_rng1701 RNG_SEED 1701
#例如命令
./experiments/scripts/faster_rcnn_alt_opt.sh 0 ZF pascal_voc

b.使用近似联合训练( approximate joint training),输出的结果在 $FRCN_ROOT/output下,这个方法是联合RPN模型和Fast R-CNN网络训练。而不是交替训练。用此种方法比交替优化快1.5倍,但是准确率相近。所以推荐使用这种方法。

cd $FRCN_ROOT
./experiments/scripts/faster_rcnn_alt_opt.sh [GPU_ID] [NET] [--set ...]
# GPU_ID是你想要训练的GPUID
# 你可以选择如下的网络之一进行训练:ZF, VGG_CNN_M_1024, VGG16
# --set ... 运行你自定义fast_rcnn.config参数,例如.
#   --set EXP_DIR seed_rng1701 RNG_SEED 1701
#例如命令
./experiments/scripts/faster_rcnn_alt_opt.sh 0 ZF pascal_voc

使用end2end的训练方式训练VGG16,使用指令如下:

./experiments/scripts/faster_rcnn_end2end.sh 0 VGG16 pascal_voc

3.训练自己的数据集

1)工程目录简介

由于需要训练自己的数据集,所以需要对这个工程各个目录的作用有所了解

  1. caffe-fast-rcnn:caffe框架目录
  2. data:用来存放pretrained模型以及读取文件的cache缓存,还有一些下载模型的脚本
  3. experiments:存放配置文件以及运行的log文件,另外这个目录下有scripts,里面存放end2end和alt_opt两种训练方式的脚本
  4. lib:用来存放一些python接口文件,如其下的datasets主要负责数据库读取,config负责一些训练的配置选项
  5. models:里面存放了三个模型文件,小型网络ZF,中型网络VGG_CNN_M_1024以及大型网络VGG16,根据你的硬件条件来选择使用哪种网络,ZF和VGG_CNN_M_1024需要至少3G内存,VGG16需要更多的内存,但不会超过11G。
  6. output:这里存放的是训练完成后的输出目录,这是运行了训练后才会出现的目录
  7. tools:里面存放的是训练和测试的Python文件

2)准备数据集

利用labelImg工具进行数据标注,标注文件放在VOC2007/Annotations,图像文件放在VOC2007/JPEGImages目录下,这样做的目的是减少代码的修改量。生成生成ImageSet\Main里的四个txt文件,分别是:trainval.txt(训练和验证集总和)、train.txt(训练集)、val.txt(验证集)、test.txt(测试集),trainval集占整个数据集的70%,train集占trainval集的70%,val集占trainval集的30%,test集占整个数据集的30%。

可参考如下代码进行划分:

%%
%该代码根据已生成的xml,制作VOC2007数据集中的trainval.txt;train.txt;test.txt和val.txt
%trainval占总数据集的70%,test占总数据集的30%;train占trainval的70%,val占trainval的30%%上面所占百分比可根据自己的数据集修改
%注意修改下面两个路径
xmlfilepath='/home/linbiyuan/py-faster-rcnn/data/VOCdevkit2007/VOC2007/Annotations';
txtsavepath='/home/linbiyuan/py-faster-rcnn/data/VOCdevkit2007/VOC2007/ImageSets/Main/';

xmlfile=dir(xmlfilepath);
numOfxml=length(xmlfile)-2;%减去...  总的数据集大小

trainval=sort(randperm(numOfxml,floor(numOfxml*0.7)));%trainval为数据集的50%
test=sort(setdiff(1:numOfxml,trainval));%test为剩余50%

trainvalsize=length(trainval);%trainval的大小
train=sort(trainval(randperm(trainvalsize,floor(trainvalsize*0.7))));
val=sort(setdiff(trainval,train));

ftrainval=fopen([txtsavepath 'trainval.txt'],'w');
ftest=fopen([txtsavepath 'test.txt'],'w');
ftrain=fopen([txtsavepath 'train.txt'],'w');
fval=fopen([txtsavepath 'val.txt'],'w');

for i=1:numOfxml
    if ismember(i,trainval)
        fprintf(ftrainval,'%s\n',xmlfile(i+2).name(1:end-4));
        if ismember(i,train)
            fprintf(ftrain,'%s\n',xmlfile(i+2).name(1:end-4));
        else
            fprintf(fval,'%s\n',xmlfile(i+2).name(1:end-4));
        end
    else
        fprintf(ftest,'%s\n',xmlfile(i+2).name(1:end-4));
    end
end
fclose(ftrainval);
fclose(ftrain);
fclose(fval);
fclose(ftest);

3)修改代码

(1)修改prototxt配置文件

这些配置文件都在models下的pascal_voc下。里面有三种网络结构:ZF、VGG16、VGG_CNN_M_1024,本文选择的是VGG16 。每个网络结构中都有三个文件夹,分别是faster_rcnn_end2end、faster_rcnn_alt_opt、faster_rcnn。使用近似联合训练,比交替优化快1.5倍,但是准确率相近,所以推荐使用这种方法。更改faster_rcnn_end2end文件夹下的train.prototxt和test.prototxt.

train.prototxt中需要更改的地方有4处,分别在 input_data、roi_data、cls_score、bbox_pred层:

layer {
  name: 'input-data'
  type: 'Python'
  top: 'data'
  top: 'im_info'
  top: 'gt_boxes'
  python_param {
    module: 'roi_data_layer.layer'
    layer: 'RoIDataLayer'
    param_str: "'num_classes': 2" #这里改为训练类别数+1
  }
}


layer {
  name: 'roi-data'
  type: 'Python'
  bottom: 'rpn_rois'
  bottom: 'gt_boxes'
  top: 'rois'
  top: 'labels'
  top: 'bbox_targets'
  top: 'bbox_inside_weights'
  top: 'bbox_outside_weights'
  python_param {
    module: 'rpn.proposal_target_layer'
    layer: 'ProposalTargetLayer'
    param_str: "'num_classes': 2" #这里改为训练类别数+1
  }
}	

layer{
  name:"cls_score"
  inner_product_param {
    num_output: 2 #这里改为训练类别数+1
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer{
name:"bbox_pred"
  inner_product_param {
    num_output: 8 #这里改为(类别数+1)*4
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

test.prototxt修改2处,分别为cls_score、bbox_pred

layer {
  name: "cls_score"
  type: "InnerProduct"
  bottom: "fc7"
  top: "cls_score"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 2 #改为训练类别数+1


layer {
  name: "bbox_pred"
  type: "InnerProduct"
  bottom: "fc7"
  top: "bbox_pred"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 8 #改为(训练类别数+1)*4

(2)修改lib/datasets/pascal_voc.py,将类别改成自己的类别

​ 这里有一个注意点就是,这里的类别以及你之前的类别名称最好是全部小写,假如是大写的话,则会报keyError的错误,这时只需要在pascal_voc。py中第218行的lower去掉即可。

datasets目录下主要有三个文件,分别是
(1) factory.py:这是一个工厂类,用类生成imdb类并且返回数据库供网络训练和测试使用;
(2) imdb.py:是数据库读写类的基类,封装了许多db的操作;
(3) pascl_voc.pyRoss用这个类来操作

(3)修改lib/datasets/imdb.py修改

imdb.py文件修改为如下,修改2部分中的三行代码,是为了防止出现下面提到的问题1。

def append_flipped_images(self):
    num_images = self.num_images
    #widths = self._get_widths()
    widths = [PIL.Image.open(self.image_path_at(i)).size[0]
              for i in xrange(num_images)]
    for i in xrange(num_images):
        boxes = self.roidb[i]['boxes'].copy()
        oldx1 = boxes[:, 0].copy()
        oldx2 = boxes[:, 2].copy()
        boxes[:, 0] = widths[i] - oldx2 - 1
        boxes[:, 2] = widths[i] - oldx1 - 1
        for b in range(len(boxes)):      # 修改2
            if boxes[b][2] < boxes[b][0]:#
                boxes[b][0] = 0          #
        assert (boxes[:, 2] >= boxes[:, 0]).all()
        entry = {'boxes' : boxes,
                 'gt_overlaps' : self.roidb[i]['gt_overlaps'],
                 'gt_classes' : self.roidb[i]['gt_classes'],
                 'flipped' : True}
        self.roidb.append(entry)
    self._image_index = self._image_index * 2

(4)开始训练

可将输出过程重定向输入到log文件中。

./experiments/scripts/faster_rcnn_end2end.sh 0 VGG16 pascal_voc > /home/***/test.log 2>&1

注意:训练前需要将data/cache中的pki文件以及VOCdevkit2007中annotations_cache的缓存删掉。

4)测试结果

(1)修改class

根据自己的label将class修改

(2)增加训练的模型

NETS = {'vgg16': ('VGG16',
                  'VGG16_faster_rcnn_final.caffemodel'),
        'zf': ('ZF',
                  'ZF_faster_rcnn_final.caffemodel'),
        'vgg16_test':('VGG','vgg_cnn_m_1024_faster_rcnn_iter_70000.caffemodel')}

(3)修改prototxt,如果用的是VGG,就不用修改

prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                            'faster_rcnn_end2end', 'test.prototxt')

(4)检测

./tools/demo.py –net vgg_test

结果会出现带边框的图像。

5)重新验证

可以使用tools/reval.py文件,对训练过程中的测试结果进行重新测试,可用matlab code测试(需配置相关环境)

python tools/reval.py output/faster_rcnn_end2end/voc_2007_test/vgg16_faster_rcnn_iter_50000/

6)出现问题:

1. 训练时出现assert (boxes[:, 2] >= boxes[:, 0]).all()的问题

原因分析:检查自己数据发现,左上角坐标(x,y)可能为0,或标定区域溢出图片
而faster rcnn会对Xmin,Ymin,Xmax,Ymax进行减1操作,如果Xmin为0,减一后变为65535

解决方法:

1、修改lib/datasets/imdb.py,append_flipped_images()函数
数据整理,在一行代码为 boxes[:, 2] = widths[i] - oldx1 - 1下加入代码:

for b in range(len(boxes)):
  if boxes[b][2]< boxes[b][0]:
    boxes[b][0] = 0

2、修改lib/datasets/pascal_voc.py,_load_pascal_annotation(,)函数
将对Xmin,Ymin,Xmax,Ymax减一去掉

2.训练过程中出现overlaps = entry[‘max_overlaps’],KeyError: 'max_overlaps’问题

解决方法:

删除data文件夹和VOCdevkit2007文件夹中的cache文件

3.linux下执行shell脚本时报错:-bash: ./a.sh: /bin/bash^M: bad interpreter: No such file or directory。

原因分析:原因是windows下的文件是dos格式,即每一行结尾以\r\n来标识,而linux下的文件是unix格式,行尾则以\n来标识。

cat -A ,如果输出结果中行末尾是^M , 则 是 d o s 格 式 , 如 果 行 末 尾 只 是 ,则是dos格式,如果行末尾只是 dos,则是unix格式。

解决方法:

vim ,编辑文件,执行“: set ff=unix”,将文件设置为unix格式,然后执行“:wq”,保存退出

4.ImportError: No module named rpn.proposal_layer

原因可能是没有将faster-rcnn中的某些库包含到库中,打开~/.bashrc文件:

export PYTHONPATH="$PYTHONPATH:~/py-faster-rcnn/caffe-fast-rcnn/python:~/py-faster-rcnn/lib"
5.训练过程中出现Check failed:proto.SerializeTOstream(&output)错误,训练终止

问题分析:snapshot保存路径问题

后续会参考代码进行阅读理解,会进行一些记录,方便后续查看
Faster-rcnn 源码学习(一)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值