R-CNN:使用自己的数据训练 Faster R-CNN 的 VGG-16 模型

573 阅读3分钟

最近在学习 Faster R-CNN 模型,为了了解其中网络的结构,利用 PascalVOC 数据集,来扩展网络的类别(原来有 20 类)。过程分为:数据准备 ==> 相关文件修改 ==> 训练网络 ==> 测试


一、数据准备

(一)下载数据集:

官网数据集镜像:pjreddie.com/projects/pa… Pascal VOC 数据集中有训练时需要的图片、对应的标注文件(xml)和指定正负样本的文本文件(txt),分别放在 VOC2007 或 VOC2012 目录中的 JPEGImage、Annotations 和 ImageSets 的 Main 目录中。

(二)数据标注:

本次训练的目的是在原有 20 类的基础上,扩展 3 类,分别是 cup、window、glasses 标注工具使用 LabelImage :github下载地址

需要安全 PyQt 和其他相关依赖项才能运行。

下载完后运行 LabelImage.py 文件即可,界面如下:

「Open Dir」 指定文件的路径;「Change Save Dir」 指定保存的 xlm 文件路径。 默认常用快捷键为:「w」 为画框,「a」 为上一张图片,「d」 为下一张图片,「ctrl + s」 为保存 xml 文件。

如果想要修改快捷键,可以打开 LabelImage.py 文件,在以下代码中(大概在213到276行)修改:

...
        openNextImg = action('&Next Image', self.openNextImg,    //里面有快捷键的功能和快捷键
                             'd', 'next', u'Open Next')          //第三个参数('d')就是快捷键,可以修改

        openPrevImg = action('&Prev Image', self.openPrevImg,
                             'a', 'prev', u'Open Prev')

        verify = action('&Verify Image', self.verifyImg,
                        'space', 'verify', u'Verify Image')

        save = action('&Save', self.saveFile,
                      'ctrl+s'', 'save', u'Save labels to file', enabled=False)
...

每画完一个框后,会让你选择所属类别:

如果想要修改预选类别,可以在 $LabelImage_ROOT/data 里面的 predefined_classes.txt 里修改。

数据标注完后,需要生成四个 txt 文件,分别为 class_train.txt、class_trainval.txt、class_val.txt、class_test.txt。

内容格式为下:

2008_000008 -1
2008_000015 -1
2008_000019 -1
2008_000023 -1
2008_000028 -1
2008_000033  1
2008_000036 -1
2008_000037  1
2008_000041 -1
2008_000045 -1
2008_000053 -1
2008_000060 -1
...

(三)数据存放地址:

数据准备完后, jpg 文件放在 \py-faster-rcnn\data\VOCdevkit2007\VOC2007\JPEGImage\ 里面 xml 文件放在 \py-faster-rcnn\data\VOCdevkit2007\VOC2007\Annotations\ 里面 txt 文件放在 \py-faster-rcnn\data\VOCdevkit2007\VOC2007\ImageSets\Main\ 里面 注意 txt 里面每一个类别都有对应的 train、val、trainval、test 文件,按照原来的数据格式去做,需要自己生成。

二、训练网络

在训练开始之前,需要修改一些网络文件和下载 ImageNet 预训练模型。

(一)修改相关配置文件

1. cd $FRCN_ROOT/lib/datasets,修改 pascal_voc .py,添加自己的类

        self._classes = ('__background__', # always index 0
                         'aeroplane', 'bicycle', 'bird', 'boat',
                         'bottle', 'bus', 'car', 'cat', 'chair',
                         'cow', 'diningtable', 'dog', 'horse',
                         'motorbike', 'person', 'pottedplant',
                         'sheep', 'sofa', 'train', 'tvmonitor', 'cup', 'window', 'glasses')

2. cd $FRCN_ROOT/lib/datasets,修改 imdb.py, 在 boxes[:, 2] = widths[i] - oldx1 -1 后面添加三行,如下:

...
    boxes[:, 2] = widths[i] - oldx1 -1
    for b in range(len(boxes)):
        if boxes[b][2] < boxes[b][0]:
            boxes[b][0] = 0 
...

3. 修改 train.prototxttest.prototxt 把所有的 21 替换为 24,这个数为 类别数 + 背景 = 23 + 1,按自己的类别数来改。然后把所有的 84 替换为 96,这个数为 (类别数 + 背景)× 4 = 96 ,也是按照自己的类别改。

4. 修改所有的 .pt 文件 如上,把所有的 21 替换为 24,把所有的 84 替换为 96

(二)下载 ImageNet 模型

训练的时候需要使用 ImageNet 的预训练模型,所以需要准备: cd $FRCN_ROOT 运行脚本文件: ./data/scripts/fetch_imagenet_models.sh 有可能需要翻墙才能下载或者下载速度慢。可以网上找网友下载。

(三)清除缓存

删除缓存文件:

$FRCN_ROOT/data/VOCdevkit2007/annotations_cache/annots.pkl $FRCN_ROOT/data/cache 下的 pkl 文件 如果不清除缓存可能会报错。

(四)开始训练

检查所有准备步骤没错后,就可以开始训练了。 命令如下:

cd $FRCN_ROOT ./experiments/scripts/faster_rcnn_end2end.sh [GPU_ID] [NET] [dataset]

第一个参数指定训练用的 GPU,第二个指定训练什么网络,这里使用 VGG16,第三个是指定数据集,这里为 pascal_voc

例如:

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

训练每次迭代大约为 0.2s ,迭代 70000 次,每 10000 次会生成一次 snapshot ,大概需要训练快 4 个小时训练完的网络保存在:

$FRCN_ROOT/output/faster_rcnn_end2end/voc_2007_trainval

(五)训练中遇到的问题

训练中还是会遇到各种各样的报错,我把我自己的遇到的问题汇总了以下,参考训练和测试 Faster R-CNN 模型中遇到的问题

三、测试网络

网络训练完成后如果有 test 集会自动开始测试,最后输出所有类的 Average Precision (AP) 及 mean AP:

==除了训练 VGG16 模型,我还再训练多一个 ResNet-50,在训练 ResNet-50 的时候我修改生成的 anchors 的尺度,增加了两个小的 anchors,提高了检测的精度,两个网络的 AP 做一个对比。==

可以发现,残差网络所有类别的 AP 都有提高,有一部分类有明显提高:

上:VGG16 网络的 mAP;下:ResNet-50 网络的 mAP

由于官方给的文件里面没有 ResNet 网络训练的文件,可以参考 使用自己的数据训练 Faster R-CNN 的 ResNet-50 模型