我是靠谱客的博主 傻傻猎豹,最近开发中收集的这篇文章主要介绍MobileNet-SSD训练自己的数据集,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

仅作笔记整理搬运使用,没有任何程序原创部分,主要给自己提个醒,避免重复搜索工作

一、配置

ubuntu18.04 ,显卡驱动,cuda10.1,cudnn7.6.5
查看cuda版本:
cat /usr/local/cuda/version.txt
查看cudnn版本:
cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

二、安装配置caffe-ssd

annaconda下创建caffe环境:conda create -n caffe2 python=2.7

opencv安装:pip install opencv-python

安装配置caffe-ssd
https://blog.csdn.net/CAU_Ayao/article/details/84000151

make runtest -j16 的时候会出错!

三、制作VOC数据集

https://blog.csdn.net/Sunhansong/article/details/107281225

四、voc数据集转化成lmbd数据集

https://blog.csdn.net/la_fe_/article/details/84928958

caffe 使用的是 LMDB 数据集格式,使用 caffe 框架实现mobilenets-ssd训练,还需要将 VOC 数据集转换为 lmdb 格式。

(虽然用cucumber有点奇怪,但是就顺着人家作者来吧)

  1. 在 home/shs/data/VOCdevkit 目录下创建 cucumber 目录,该目录中存放自己转换完成的VOC数据集,即Annotation/ImageSets/JPEGImages 等多个文件夹,ImageSets中的Main中要生成好四个txt文件;
  2. 在 home/shs/caffe-ssd/examples 目录下创建 cucumber 目录;
  3. 在 home/shs/caffe-ssd/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 修改内容:
注意:"background"这个背景类别0标签不可以删掉

item {
name: "none_of_the_above"
label: 0
display_name: "background"
}
item {
name: "p"
label: 1
display_name: "p"
}
item {
name: "d"
label: 2
display_name: "d"
}
item {
name: "w"
label: 3
display_name: "w"
}

create_list_cucumber.sh 修改内容:


for name in cucumber
# 修改此处为自己数据集的名字
do
if [[ $dataset == "test" && $name == "VOC2012" ]]
then
continue
fi

create_data_cucumber.sh 修改内容:

root_dir=/home/shs/caffe-ssd
… …
data_root_dir="$HOME/data/VOCdevkit"
# 数据集路径
dataset_name="cucumber"
mapfile="$root_dir/data/$dataset_name/labelmap_voc_cucumber.prototxt"
  1. 运行脚本
    在 home/shs/caffe-ssd/ 目录下分别运行:
./data/cucumber/create_list_cucumber.sh
./data/cucumber/create_data_cucumber.sh
  1. 运行create_data_cucumber.sh会出现问题
    ImportError:No module named caffe.proto
    https://blog.csdn.net/wangduyang/article/details/78211126
gedit ~/.bashrc

加入

export PYTHONPATH=~/caffe-ssd/python:$PYTHONPATH
source ~/.bashrc

在每次执行creat_data.sh生成lmdb的时候都需要进行上述操作。

五、Mobilenet-SSD下载并训练

1.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

2.训练自己的数据集

  1. 运行gen_model.sh脚本
./gen_model.sh 4

**注意:**这里的用法是:# usage: ./gen_model.sh CLASSNUM,CLASSNUM是你的类别数,比如我的数据集有三类,应该再加上background这一类,所以CLASSNUM 类别数就为4

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

  1. 修改三个prototxt的路径
    将 Mobilenet-SSD/examples 下网络文件的路径修改为自己的路径.
    MobileNetSSD_test.prototxt:
data_param {
# 第 24 行
source: "/home/shs/data/VOCdevkit/cucumber/lmdb/cucumber_test_lmdb/"
batch_size: 8
backend: LMDB
}
annotated_data_param {
batch_sampler {
}
# 第 31 行
label_map_file: "/home/shs/caffe-ssd/data/cucumber/labelmap_voc_cucumber.prototxt"

MobileNetSSD_train.prototxt:

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

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

solver_mode: CPU

???为啥

  1. 开始训练
    先把train.sh修改地址
#../../build/tools/caffe train -solver="solver_train.prototxt" 
../caffe-ssd/build/tools/caffe train -solver="solver_train.prototxt" 
./train.sh

train.sh里的内容解析:(根据自己的路径实际情况做微调)

第2行是train.prototxt的路径,第7行是snapshot保存中间模型的路径,第8行是slover文件的路径,第9行是预训练权重,第10行是用到的gpu编号,这些都可以按需修改。笔者将最后一行的gpu从0修改为0,1,可利用双GPU训练

solver_train.prototxt文件内容:

rain_net:“example/MobileNetSSD_train.prototxt” #训练用的网络文件
test_net:“example/MobileNetSSD_test.prototxt” #测试用的网络文件
test_iter: 673 #测试时的迭代次数
test_interval: 1000 #每训练1000次迭代一次
base_lr: 0.0005 #基准学习率
display: 5 #每5次迭代屏幕显示一次信息
max_iter: 20000 #最大迭代次数
lr_policy: “multistep” #学习率调整策略
gamma: 0.5
weight_decay: 0.00005 #权重衰减
snapshot: 1000 #每1000次迭代抓取一次快照
snapshot_prefix:“snapshot_power/mobilenet” #快照保存的前缀
solver_mode: GPU #这里一定要GPU
debug_info: false
snapshot_after_train: true
test_initialization: false #不做测试初始化
average_loss: 10 #每10次迭代平均下loss
stepvalue: 10000
stepvalue: 20000
iter_size: 1
type: “RMSProp” #一种优化方法,挖坑,以后填
eval_type: “detection” #这里一定要写检测,默认为classification
ap_version: “11point” #计算AP的方法

  1. 训练时出错!
    (1)math_functions.cpp:250 Check failed: a (=b (0 vs -1.19209e-007)
    https://blog.csdn.net/house_s/article/details/82502938
    1.找到math_functions.cpp,并打开第一个路径为~/caffe/src/caffe/util的math_functions.cpp
    2.找到第250行出错的地方,双斜杠屏蔽
    3.重新在caffe-ssd路径下make py
    (2)training error: Data layer prefetch queue empty
    https://blog.csdn.net/LuohenYJ/article/details/88416180
    这种问题出现通常是注释掉 CHECK_LE(a, b) 出现Data layer prefetch queue empty。导致程序出现死循环。
    解决办法修改caffe-ssd/src/caffe/util/sampler.cpp,如下面修改代码所示//renew注释下,加入两个判断,使得bbox长宽不要越界。

// Figure out bbox dimension.
float bbox_width = scale * sqrt(aspect_ratio);
float bbox_height = scale / sqrt(aspect_ratio);
//renew
if(bbox_width>=1.0)
{
bbox_width=1.0;
}
if(bbox_height>=1.0)
{
bbox_height=1.0;
}
// Figure out top left coordinates.
float w_off, h_off;
caffe_rng_uniform(1, 0.f, 1 - bbox_width, &w_off);
caffe_rng_uniform(1, 0.f, 1 - bbox_height, &h_off);

!! 记得 make py
(3)Check failed: error == cudaSuccess (2 vs. 0) out of memory
https://blog.csdn.net/menglanzeng/article/details/97616685
我把train.prototxt中第50行的batch_size改为1


data_param {
source: "trainval_lmdb/"
batch_size: 1
backend: LMDB
}
  1. 继续训练
    https://blog.csdn.net/baidu_32173921/article/details/72470019
    复制train.sh并重命名为train_resume.sh。
更改
-weights="mobilenet_iter_73000.caffemodel" 
为:
-snapshot="snapshot/mobilenet_iter_XXXX.solverstate" 

这里XXXX是你以前停止训练的迭代次数。
如果您不知道要XXXX运行

ls -ltr snapshot/

则可以在底部找到最后的迭代。

然后接着上次训练

./train_resume.sh

理论上可以,但没成功。

3.测试

  1. 合并bn层
    在caffe根目录/examples/MobileNet-SSD下
python2 merge_bn.py --model ./example/MobileNetSSD_deploy.prototxt --weights ./snapshot/mobilenet_iter_10000.caffemodel

运行以下命令,MobileNet-SSD中多出 no_bn.prototxt 和 no_bn.caffemodel,这就是我们想要获得的模型文件和参数文件。

  1. 修改demo.py
caffe_root = '/home/shs/caffe-ssd/'
……
#net_file= 'deploy.prototxt'
net_file= 'no_bn.prototxt'
#caffe_model='mobilenet_iter_73000.caffemodel'
caffe_model='no_bn.caffemodel'
#test_dir = "images" #测试的就是images文件夹里的图片
test_dir = "images"
……
CLASSES = ('background','p','d','w')

注意:测试的时候,终端运行时按回车键切换下一张图片,测完images文件夹里所有图片就退出终端了,要是点叉号关窗口,终端就退不出去了,Ctrl+C也不好使。

  1. 查看mAP
    先把solver_test.prototxt修改地址
train_net: "example/MobileNetSSD_train.prototxt"
test_net: "example/MobileNetSSD_test.prototxt"

修改test.sh

#../../build/tools/caffe train -solver="solver_test.prototxt" 
../caffe-ssd/build/tools/caffe train -solver="solver_test.prototxt" 
./test.sh

查看loss值和detection_eval(mAP)评测模型效果

4.可视化

  1. 训练模型时保存log日志文件
    https://blog.csdn.net/zxyhhjs2017/article/details/84963012?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2
    https://blog.csdn.net/xunan003/article/details/73017436

修改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
export GLOG_logtostderr=0
export GLOG_log_dir='../MobileNet-SSD/' #log存放位置
#../../build/tools/caffe train -solver="solver_train.prototxt" 
../caffe-ssd/build/tools/caffe train -solver="solver_train.prototxt" 
-weights="mobilenet_iter_73000.caffemodel" 
-gpu 0

训练完成后发现在我们保存的目录下生成了两个上锁log文件caffe.INFO和caffe.ubuntu.root.log.INFO.20170611-103712.5383。点击打开后我们可以看到我们所训练的日志文件。

  1. 利用生成的log文件绘制accuary loss曲线图
    首先绘制图,caffe中其实已经自带了这样的小工具 caffe-master/tools/extra/parse_log.sh 和caffe-master/tools/extra/extract_seconds.py还有 caffe-master/tools/extra/plot_training_log.py.example;拷贝以上文件到当前训练模型的目录下。

    然后我们到你保存的log文件目录下将1中保存的log文件解锁,解锁命令:

sudo chmod -R 777 ./caffe.ubuntu.root.log.INFO.20170611-103712.5383

解锁后我们就可以更改该log文件名为123.log(注意:要画图一定是.log文件,所以不改名不可以画)。

然后复制该xxx.log文件到你训练模型所在目录下。

然后就可以利用命令画图了:在模型所在目录下命令: ./plot_training_log.py.example y 0.png 123.log

./plot_training_log.py.example y 0.png 123.log

0.png是你保存的绘制出的图片名称,123.log是你保存的log文件名称。
y表示的是你的所绘制的图片到底是什么图片,具体解释如下:


y的数字代表意义(0~7):
Supported chart types:
0: Test accuracy
vs. Iters
(准确率与迭代次数图)
1: Test accuracy
vs. Seconds
(准确率与时间图)
2: Test loss
vs. Iters
(测试损失与迭代次数图)
3: Test loss
vs. Seconds
(测试损失与时间图)
4: Train learning rate
vs. Iters
(学习率与迭代次数图)
5: Train learning rate
vs. Seconds
(学习率与时间图)
6: Train loss
vs. Iters
(训练损失与迭代次数图)
7: Train loss
vs. Seconds
(训练损失与时间图)
运行后生成的文件有:log-data.log.test和log-data.log.test和xxx.png
  1. test测试log日志文件保存与绘图类似过程

参考网址:
https://blog.csdn.net/la_fe_/article/details/84928958
https://blog.csdn.net/nimo_cap/article/details/82888196
https://cloud.tencent.com/developer/article/1020066
https://zhuanlan.zhihu.com/p/95904525?from_voters_page=true

最后

以上就是傻傻猎豹为你收集整理的MobileNet-SSD训练自己的数据集的全部内容,希望文章能够帮你解决MobileNet-SSD训练自己的数据集所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(99)

评论列表共有 0 条评论

立即
投稿
返回
顶部