前言:上一节简单介绍了Facebook的开源检测平台Detectron的conda安装过程以及安装的相关注意事项。本节承接前文,对Detectron的初级使用流程和相关的注意事项进行汇总,希望有所帮助。
一、Detectron Model Zoo
Detectron中的使用的主干网络主要为ResNet,ResNeXt,FPN和VGG16;实现的网络类型主要包括RPN,Fast,Mask,Faster,RetinaNet,Kps;能够进行的检测任务主要为3类:物体检测,Mask相关物体检测,关键点检测。
Detectron model zoo中的主干网络由ImageNet数据集进行预训练。平台中集成的各类算法通过MS Coco数据集进行再训练得到提供的模型和在coco验证集上的各类检测结果,供用户下载在此基础上继续训练。详细解释请参照官网页面。在调用平台的算法时,如果本地没有提前下载好对应配置文件需要的预训练模型,会在线下载;如果没有网络,或者网速不好可以提前下载好模型放在本地,Model Zoo中部分模型和对应的预训练结果如下图所示:
二、Detectron 目录
Detectron 文件目录的解析也有很多博客进行汇总,本人由于还没有开始阅读源码,因此暂时不进行深层次的介绍。这里就普通用户来使用该平台应该了解的几个主要目录进行一下简单的解释。
configs
该文件夹中包含了训练和测试采用的配置文件,在文件中可以设置采用的数据集、迭代次数等各种关于模型、优化器、训练过程和测试过程等相关的参数。
tools
该文件中包含了平台的主要功能代码文件,包括训练文件,测试文件,推理文件,可视化文件,保存pb文件等主要功能的调用模板。
detectron/datasets
该文件夹中包含数据结构的定义和数据的存放。dataset_catalog.py文件中定义了coco,voc,cityscapes三类数据格式的预定义结构;data文件夹为预定义的存放数据位置;data/README.md文件中解释了三类数据的存放目录方式。
在不了解平台源码的情况下,只要先了解以上三个目录就可以顺利的训练自己的数据了。
三、Detectron 使用
数据准备(官方)
根据detectron/datasets/data/README.md文件中对数据目录的解释,平台提供的三种数据目录结构依次如下:
coco数据集
coco
|_ coco_train2014
| |_ <im-1-name>.jpg
| |_ ...
| |_ <im-N-name>.jpg
|_ coco_val2014
|_ ...
|
|_ annotations
| |_ instances_train2014.json
| |_ instances_val2014.json
| |_ ...
voc数据集
VOC<year>
|_ JPEGImages
| |_ <im-1-name>.jpg
| |_ ...
| |_ <im-N-name>.jpg
|
|_ annotations
| |_ voc_<year>_train.json
| |_ voc_<year>_val.json
| |_ ...
|
|_ VOCdevkit<year>
|_ VOC<year>
|_ Annotations
| |_ <im-1-name>.xml
| |_ ...
| |_ <im-N-name>.xml
|
|_ ImageSets
|_ Main
|_ test.txt
|_ ...
cityscapes(略)
按照平台训练的要求,以上数据必须存放在detectron/datasets/data文件夹下,如果放在其他路径,则需要通过软链接的形式将本地相同目录结构的数据链接到data文件夹中,以上详细内容参考README.md。
json格式数据是detectron平台采用的训练格式,因此如果采用除coco数据的其他类型的例如voc的xml格式数据,也需要将训练用数据转换成json格式。从以上三种官方规定的数据可以看出,coco数据结构是最简单清晰的;如果使用voc格式的数据,那么需要将训练数据通过转换脚本转换为json格式的数据,需要注意的是,采用VOC格式数据在测试的时候依然用xml进行准确率的测试,因此原VOC数据集的文件夹目录必须给出,并且提供测试用xml和对应的txt文件列表;cityscapes类型数据由于本人不接触相关任务,因此略过,如有相关的研究参照官网解释即可。
之所以必须按照以上的要求部署数据,甚至是用自己的数据也要把数据的名字换成以上三种规定的方式,因为detectron中对这三种类型的数据读取方式写死在了dataset_catalog.py文件中。在测试的时候,代码会查询你的数据集名称中是否包含‘coco’、‘voc’或者是‘cityscapes’,然后调用对应的评估函数去进行训练模型的评估。由于还有深入的研究测试代码,这里猜测detectron中给定的三种固定名字和路径的数据存放方式只是为了固定调用三种不同的评估方式(如有错误,欢迎批评指出),如果没有特殊要求,直接把个人的数据都做成json格式然后按照coco数据集的目录格式存放命名,利用coco评价标准即可。
数据准备(个人)
经过实践,发现其实可以按照dataset_catalog.py中定义数据集的方式来定义自己的数据集,而不用要一定按照官方规定的名字,路径和结构。我们只要把我们的数据按照coco数据集的结构进行存放即可,路径和名字完全可以自己定义,下面具体讲一下如何操作:
dataset_catalog.py数据结构定义
首先我们看一下dataset_catalog.py中的coco数据集结构定义方式:
'coco_2014_train': {
_IM_DIR:
_DATA_DIR + '/coco/coco_train2014',
_ANN_FN:
_DATA_DIR + '/coco/annotations/instances_train2014.json'
},
'coco_2014_val': {
_IM_DIR:
_DATA_DIR + '/coco/coco_val2014',
_ANN_FN:
_DATA_DIR + '/coco/annotations/instances_val2014.json'
}
其训练集和验证集的名字、路径和对应的路径都是固定好的,我们可以按照这样的方式来构建个人数据集,假如我们手里有自己制作的二次元的人头检测数据集cartoon,并且划分了训练图片,训练xml,测试图片,测试xml的文件夹。那么首先需要将xml标注文件转化为detectron使用的json格式,代码已上传,供参考。然后建立个人数据集的在detectron中的参数设置,如下:
'cartoon_train': {
_IM_DIR:
'/home/my_data/cartoon/train_imgs',
_ANN_FN:
'/home/my_data/cartoon/train.json'
},
'cartoon_test': {
_IM_DIR:
'/home/my_data/cartoon/test_imgs',
_ANN_FN:
'/home/my_data/cartoon/test.json'
}
名字和路径根据自己数据的真实存放路径设置即可,接下来需要修改配置文件中数据集相关设置
config配置文件修改
首先我们展示configs文件夹下随便一个yaml配置文件中的关于TRAIN和TEST的参数配置代码:
TRAIN:
WEIGHTS: https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/MSRA/R-50.pkl
DATASETS: ('coco_2014_train',)
SCALES: (500,)
MAX_SIZE: 833
BATCH_SIZE_PER_IM: 256
RPN_PRE_NMS_TOP_N: 2000 # Per FPN level
TEST:
DATASETS: ('coco_2014_minival',)
SCALE: 500
MAX_SIZE: 833
NMS: 0.5
RPN_PRE_NMS_TOP_N: 1000 # Per FPN level
RPN_POST_NMS_TOP_N: 1000
其中,DATASETS 键值即为设置数据索引的地方,参照我们设置的数据名称分别为 ‘cartoon_train’ 和 ‘cartoon_test’,分别替换 ‘coco_2014_train’ 与 ‘coco_2014_minival’ 理论上就可以了。
实际上,通过这两步的操作,detectron 可以完成训练,但是在测试的时候就会报错,如果细心的同学已经发现原因了。前文提到,在测试的时候,代码会根据设置的数据集名字里是否含有 ‘coco’、‘voc’ 等关键字来查找对应的评估函数,这里我们设置的测试数据集为 ‘cartoon_test’,当然不行了。那怎样修改呢,这就需要我们在配置文件的TEST代码段里添加设置默认评估器的参数 ‘FORCE_JSON_DATASET_EVAL: True’,即采用默认的coco评价标准,修改过的 yaml 配置文件中对应部分如下:
TRAIN:
WEIGHTS: https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/MSRA/R-50.pkl
DATASETS: ('cartoon_train',)
SCALES: (500,)
MAX_SIZE: 833
BATCH_SIZE_PER_IM: 256
RPN_PRE_NMS_TOP_N: 2000 # Per FPN level
TEST:
DATASETS: ('cartoon_test',)
SCALE: 500
MAX_SIZE: 833
NMS: 0.5
RPN_PRE_NMS_TOP_N: 1000 # Per FPN level
RPN_POST_NMS_TOP_N: 1000
FORCE_JSON_DATASET_EVAL: True
其中,’DATASETS‘字段中数据集是可以设置多个的,系统会自动进行合并。此外,不论是添加字段或者是修改本来字段的值,字段后的冒号:与键值之间一定不要不要把空格省略了,不然会报错。到此,数据相关的问题解决了,如果没有特殊要求的话,按照官方的配置把自己的数据固定命名并存放到固定位置也是推荐的,毕竟这样更不容易出现错误。接下来就可以用自己的数据来进行训练了。
训练
根据tools文件夹中的 train_net.py文件进行训练,执行代码如下:
python tools/train_net.py
--cfg configs/12_2017_baselines/e2e_faster_rcnn_X-101-64x4d-FPN_1x.yaml
当然,训练之前还是需要根据实际情况先设置采用的yaml配置文件,例如需要修改NUM_CLASSES、NUM_GPUS、BASE_LR、MAX_ITER、MAX_SIZE等参数。
训练的时候注意一点,如果NUM_GPUS选择 1,并且有多显卡的时候,可以指定运行显卡;如果NUM_GPUS大于1,那么不支持选择显卡运行,系统会从第一个开始选择,这个时候如果第一张卡显存已经被其他程序占满了,有可能引起程序错误。
在detectron中的测试代码中默认是训练之后进行一次测试的,也可以设置‘ –skip-test ’不进行测试。
测试
根据tools文件夹中的 test_net.py文件进行测试,执行代码如下:
python tools/test_net.py
--cfg configs/12_2017_baselines/e2e_faster_rcnn_X-101-64x4d-FPN_1x.yaml
TEST.WEIGHTS models/model_final.pkl
NUM_GPUS 1
这里也没有多解释的,TEST.WEIGHTS 为训练完成保存的参数文件。
推理
根据tools文件夹中的 infer_simple.py文件进行推理,执行代码如下:
python tools/infer_simple.py
--cfg configs/12_2017_baselines/retinanet_R-50-FPN_1x.yaml
--wts models/model_final.pkl
--output-dir result
--image-ext jpg
/home/my_data/cartoon/test_imgs
这里需要注意一下,在推理的时候需要修改 detectron/dataset/dummy_datasets.py 文件中的如下位置:
这里是写好的训练数据的类别字典,默认是coco数据集的80类类别名称,当训练自己的数据的时候,可以直接把 ‘classes’字典里的类目换成自己数据的类目,或者参照 ‘get_coco_dataset()’ 函数增加一个自己数据集的函数,例如添加‘get_cartoon_dataset()’。如果是采用第二种方式增加新的映射函数,那么还需要在infer_simple.py调用文件中修改调用的函数名,将
dummy_coco_dataset = dummy_datasets.get_coco_dataset()
替换为
dummy_coco_dataset = dummy_datasets.get_cartoon_dataset()
当然了,如果想把变量 dummy_coco_dataset 也更换了也没问题,只要后续调用一致就可以了,这个应该好理解。
到这里,应该可以顺利的运行自己的代码进行一系列操作了,完成这篇笔记之前也参考了很多篇博客,由于看的比较乱,比较杂,没有进行记录,因此这里没有一一引用,如果有重复的地方可以指出,我会添加引用,日后如果翻到之前的博客也会同样添加引用,本篇detectron的使用笔记记录如果哪里有错误误导了大家,欢迎批评指正!
四、错误处理
训练时报错1
error == cudaSuccess. 2 vs 0. Error at: /opt/conda/conda-bld/pytorch-nightly_1542878060625/work/caffe2/core/context_gpu.cu:342: out of memory
这就是内存不够了,如果不是用错显卡之类的错误,代码本身的问题请先尝试修改训练的batchsize,默认配置在 detectron/core/config.py 中 _C.TRAIN.IMS_PER_BATCH = 2,可以直接修改这里,也可以在采用的yaml配置文件的TRAIN中添加修改 IMS_PER_BATCH: 1
训练时报错2
Exception: Loss is NaN
解决方式是修改yaml配置文件中 ‘SOLVER:‘ 部分的字段 ‘BASE_LR’,例如默认设置为 BASE_LR: 0.02,修改为 BASE_LR: 0.001