Caffe 学习系列(六):MobileNet-SSD 安装与训练

Caffe 学习系列(六):MobileNet-SSD 安装与训练

Mobile Platform

https://github.com/chuanqi305/rscnn

1. 数据集转换

VOC数据集制作在yolo 学习系列(二):训练自己的数据集中已经介绍过了,
但是 caffe 使用的是 LMDB 数据集格式,使用 caffe 框架实现SSD与mobilenets-ssd训练,还需要将 VOC 数据集转换为 lmdb 格式。

1.1 说明

SSD提供了VOC数据到LMDB数据的转换脚本 ,位于caffe/data/VOC0712目录下的 create_list.sh 和 create_data.sh,这两个脚本是完全针对VOC0712目录下的数据进行的转换。

实现中为了不破坏VOC0712目录下的数据内容,针对我们自己的数据集,修改了上面这两个脚本,
将脚本中涉及到VOC0712的信息替换成我们自己的目录信息。
在处理我们的数据集时,将VOC0712替换成indoor

1.2 实现步骤
  1. 在 home/chris/data/VOCdevkit 目录下创建 cucumber 目录,该目录中存放自己转换完成的VOC数据集,即Annotation/ImageSets/JPEGImages 等多个文件夹;
  2. 在 home/chris/ssd/caffe/examples 目录下创建 cucumber 目录;
  3. 在 home/chris/ssd/caffe/data 目录下创建 cucumber 目录,同时将data/VOC0712下的 create_list.sh,create_data.sh,labelmap_voc.prototxt
    这三个文件copy到 cucumber 目录下,分别重命名为create_list_cucumber.sh,create_data_cucumber.sh, labelmap_voc_cucumber.prototxt
  4. 对上面新生成的两个create文件进行修改,主要修改是将 VOC0712 相关的信息替换成 cucumber

labelmap_voc_cucumber.prototxt 修改内容:

item {
  name: "none_of_the_above"
  label: 0
  display_name: "background"
}
item {
  name: "sea cucumber"
  label: 1
  display_name: "cucumber"
}

create_list_cucumber.sh 修改内容:

  for name in cucumber  # 修改此处
  do
    if [[ $dataset == "test" && $name == "VOC2012" ]]
    then
      continue
    fi

create_data_cucumber.sh 修改内容:

data_root_dir="$HOME/data/VOCdevkit"  # 数据集路径
dataset_name="cucumber" 
mapfile="$root_dir/data/$dataset_name/labelmap_voc_cucumber.prototxt"
1.3 运行脚本

在 home/chris/ssd/caffe/ 目录下分别运行:

./data/indoor/create_list_indoor.sh
./data/indoor/create_data_indoor.sh

生成的数据集位于 home/chris/ssd/caffe/examples/cucumber 和 /home/chris/data/VOCdevkit/cucumber/lmdb 两个目录下。

2. MobileNet-SSD 安装与测试

2.1 安装 Caffe-SSD

其中,makefile.config 修改参考caffe里的makefile.config文件

git clone https://github.com/weiliu89/caffe.git 
cd caffe 
git checkout ssd 
cp Makefile.config.example Makefile.config 
mkdir build 
cd build 
cmake .. 
make all -j16 
make install 
make runtest 
make pycaffe
2.2 Mobilenet-SSD下载测试
git clone https://github.com/chuanqi305/MobileNet-SSD.git

文件结构

template 存放4个网络定义的公用模板,可以由gen.py脚本修改并生成 
MobileNetSSD_deploy.prototxt 运行网络定义文件 
solver_train.prototxt 网络训练超参数定义文件 
solver_test.prototxt 网络测试超参数定义文件 
train.sh 网络训练脚本 
test.sh 网络测试脚本 
gen_model.sh 生成自定义网络脚本(调用template文件夹内容) 
gen.py 生成公用模板脚本(暂不用) 
demo.py 实际检测脚本(图片存于images文件夹) 
merge_bn.py 合并bn层脚本,用于生成最终的caffemodel

最后打开 demo.py 脚本,根据个人情况修改以下路径:

caffe_root = '/home/chris/ssd/caffe/' 
net_file= 'MobileNetSSD_deploy.prototxt' 
caffe_model='MobileNetSSD_deploy.caffemodel' 
test_dir = "images"

若报错,应该是 python 路径问题

gedit ~/.bashrc   # 在最后添加使用的caffe路径
source ~/.bashrc
2.3 训练自己的数据集
2.3.1 运行gen_model.sh脚本

由于VOC数据集是21类(加上背景),而这里只有1类,因此,我们需要重新生成训练、测试和运行网络文件,这里就要用到gen_model.sh脚本,它会调用template文件夹中的模板,按照我们指定的参数,生成所需的训练网络模型。

    # usage: ./gen_model.sh CLASSNUM 
    ./gen_model.sh 2 

执行之后,得到 Mobilenet-SSD/examples 文件夹里面的3个prototxt就是从模板生成的正式网络定义,根据作者设置,其中的deploy文件是已经合并过bn层的,需要后面配套使用。

2.3.2 路径修改

将 Mobilenet-SSD/examples 下网络文件的路径修改为自己的路径.

MobileNetSSD_test.prototxt:

  data_param {
    # 第 24 行
    source: "/home/chris/data/VOCdevkit/cucumber/lmdb/cucumber_test_lmdb/"
    batch_size: 8
    backend: LMDB
  }
  annotated_data_param {
    batch_sampler {
    }
      # 第 31 行
    label_map_file: "/home/chris/ssd/caffe/data/cucumber/labelmap_voc_cucumber.prototxt"

MobileNetSSD_train.prototxt:

  data_param {
  # 第 49 行
    source: "/home/chris/data/VOCdevkit/cucumber/lmdb/cucumber_trainval_lmdb/"
    batch_size: 24
    backend: LMDB
..........................
      max_sample: 1
      max_trials: 50
    }
  # 第 136 行
    label_map_file: "/home/chris/ssd/caffe/data/cucumber/labelmap_voc_cucumber.prototxt"
  }

Mobilenet-ssd目录下的 solver_train.prototxt 和 solver_test.prototxt

solver_mode: CPU
2.3.3 开始训练

运行 train.sh 脚本

#!/bin/sh
if ! test -f example/MobileNetSSD_train.prototxt ;then
	echo "error: example/MobileNetSSD_train.prototxt does not exist."
	echo "please use the gen_model.sh to generate your own model."
        exit 1
fi
mkdir -p snapshot
../ssd/caffe/build/tools/caffe train -solver="solver_train.prototxt" \
-weights="mobilenet_iter_73000.caffemodel" \
2.3.4 合并bn层

运行以下命令,得到 no_bn.prototxt 和 no_bn.caffemodel

python2 merge_bn.py --model ./example/defults/MobileNetSSD_deploy.prototxt --weights ./snapshot/defults-A/mobilenet_iter_14000.caffemodel 

最终使用的是没有 BN 层的模型,在 CPU 模式下,含有 BN 层的模型检测帧数为 8 帧,而去除 BN 层的模型检测帧数为 20 帧

2.3.5 耗时测试
 ./build/tools/caffe time -gpu 0 -model examples/MobileNet-SSD/squeezenet-ssd/defults/squeezenet_ssd_voc_deploy.prototxt 

问题
理论上Mobilenet的运行速度应该是VGGNet的数倍,但实际运行下来并非如此,即使是合并bn层后的MobileNet-SSD也只比VGG-SSD快那么一点点,主要的原因是Caffe中暂时没有实现depthwise convolution,目前都是用的group。这里group相当于一个for循环,需要依次计算,如果能使用深度卷积,那就可以一次性计算完,节省不少时间。

用上了depthwise convolution layer,对于mobilenet的提速十分明显,可以说是立竿见影。下面简单介绍使用方法.
1.下载项目

$ git clone https://github.com/yonghenglh6/DepthwiseConvolution.git

注意到项目中的caffe文件夹,将其中的depthwise_conv_layer.hpp,depthwise_conv_layer.cpp和depthwise_conv_layer.cu这三个文件放到SSD(即caffe)的相应位置中,这里的操作是从基础卷积类中派生了深度卷积这个类,此处并不需要对caffe.proto文件进行修改。稍后,需要重新编译Caffe,这样才能识别新增的depthwise convolution layer。
2.修改deploy.prototxt文件
接下来我们需要修改MobileNetSSD_deploy.prototxt,将其中所有名为convXX/dw(XX代指数字)的type从”Convolution”替换成”DepthwiseConvolution”,总共需要替换13处,从conv1/dw到conv13/dw,然后把“engine: CAFFE”都注释掉,这个新的网络文件可以另存为MobileNetSSD_deploy_depth.prototxt。在运行网络的时候,caffemodel模型不用动,只需要指定新的prototxt文件和含有depthwise convolution layer的Caffe即可。

你可能感兴趣的:(Caffe,深度学习)