Cascade RCNN.
选择Cascade RCNN来进行下面的将迁移学习用到目标检测任务中的实验, 即将新的检测任务融合到原始的检测任务中.
Cascade RCNN模型目前有几大实现项目, 具体可见https://github.com/zhaoweicai/Detectron-Cascade-RCNN. 但是mmdetection和tensorpack都是很多检测模型的融合, 这和Tensorflow Detection API类似, 因此暂不使用.
1. 数据集
准备数据集时, 可以借助cascade-rcnn_Pytorch的Data Preparation流程.
2. 安装
cd lib
sh make.sh
根据作者项目介绍, Pytorch版本使用的是0.2.0, 如果版本大于0.4.0, 那么会报错: ImportError: torch.utils.ffi is deprecated. Please use cpp extensions instead.
可以安装pytorch0.3.0, 支持CUDA9.0, 需要
export C_INCLUDE_PATH=/usr/local/cuda-9.0/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=/usr/local/cuda-9.0/include:$CPLUS_INCLUDE_PATH
安装Pytorch 0.2.0, 仅支持CUDA 8, 新建pyt tmux.
export PATH=/home/ly/cuda-8.0/bin:$PATH
export LD_LIBRARY_PATH=/home/ly/cuda-8.0/lib64:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=/home/ly/cuda-8.0/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=/home/ly/cuda-8.0/include:$CPLUS_INCLUDE_PATH
https://pytorch.org/get-started/previous-versions/ 下载历史版本.
3. 利用Cascade RCNN来做迁移学习.
-
该项目训练集使用的是PASCAL VOC2007+2012. 只可以做20类的目标检测. 虽然效果可能不好, 但是可以先实验一下. 按照方法(1)的思路, 修改模型相应的代码已经完成.
-
准备所需的数据集格式. cascade_rcnn_Pytorch项目, 数据集的准备可以参考PASCAL VOC2007/2012或COCO数据集的样子进行准备即可. 只要数据集和的准备的形式和PASCAL VOC2007/2012或者COCO数据集的类似即可.
目前迁移数据, 即新任务的检测数据集使用WIDER FACE数据集, 根据/home/ly/git/Transfer_Learning_Object_Detection/scripts/data-to-pascal-xml.py代码, 准备好的xml文件和PASCAL VOC2007/2012的标注xml文件是一致的. 因此, 将/home/ly/git/Transfer_Learning_Object_Detection/datasets的tf_wider_train按照PASCAL VOC2007/2012的目录结构安排即可. -
将/home/ly/git/Transfer_Learning_Object_Detection/datasets的tf_wider_train拷贝到./datasets下, 并按照PASCAL VOC目录格式准备.
-
修改/home/ly/git/Cascade_RCNN_Pytorch/lib/datasets下的factory.py, 加进WIDER FACE数据集的支持.
copy pascal_voc.py为wider_face.py, 并修改一些东西. -
修改trainval_net.py. 开始训练.
python trainval_net.py --exp_name object_face_detection --dataset wider_face --net detnet59 --bs 2 --nw 4 --lr 1e-3 --epochs 5 --save_dir weights --cuda --cag --cascade --r True --checkepoch 3 --checkpoint 7389
1> 训练时出现的问题: mismatch between the batch size of input (254) and that of target (256)
解决方案:
(1) 将bbox的值都加一个固定的小数, 如0.01, 解决mismatch问题. Deprecated!!! 不是根本原因.
(2) 根本原因出在fpn.py下面: roi_level = torch.log(torch.sqrt(h * w) / 224.0) / np.log(2), 开方的数据可能出现负数, 因此出现了nan, 因此就会出现mismatch问题. 可以将开方设置成正数即可. -
修改demo.py. 开始测试.
原始检测任务demo: python demo.py --net detnet59 --cuda --cag --image_dir demo_images --cascade --result_dir vis_cascade/cascade_rcnn
迁移学习检测demo: python trans_demo.py --net detnet59 --cuda --cag --image_dir demo_images --cascade --result_dir vis_cascade/trans
4. 当用迁移学习训练完之后, 在测试的过程中. 会对原有的检测模型造成损坏. 通过检查后发现:
- 原有的Cascade RCNN模型中layer的参数和迁移学习训练后相同layer的参数是一样的, 这就证明原有模型的layer没有学习.
- 造成破坏的原因应该在这: 对于模型中存在Dropout, BatchNorm层时, 由于在训练和测试阶段的操作是不一样的. 在测试时会调用到训练中的一些数值, 如在训练中保存的均值方差等. 但是在做迁移学习训练时, 并没有将Dropout, BatchNorm层的mode设置为eval!!!
在做迁移学习的训练时, 按照原有代码的设置的mode进行设置!!!
按照原有代码进行设置layer的mode后, 貌似训练过程也比之前好了!!! 果然是这个问题!!!
设置成原有的mode之后, 不仅精度提升了, 而且速度也得到了大幅提升!!!
这个问题已经解决了. 当在训练或测试时, 要调用的全局变量设置在./cfg/*.yml中, .yml会再次设置./lib/model/utils/config.py下的变量. 例如对于cfg.POOLING_MODE, 使用的就是"align". 因为在.yml中, 已经定义了POOLING_MODE.