项目作者: GuoJaw

项目描述 :
包含Caffe-SSD-Mobilenet(DepthwiseConvolution) 和 Caffe-SSD 和 Classification
高级语言: C++
项目地址: git://github.com/GuoJaw/caffe-ssd-mobilenet.git
创建时间: 2018-05-17T01:16:40Z
项目社区:https://github.com/GuoJaw/caffe-ssd-mobilenet

开源协议:Other

下载


caffe-mobilenet-ssd

测试前向网络速度

$ cd ~/caffe

$ ./build/tools/caffe time -gpu 0 -model examples/mobilenet/XXXX.prototxt

Intro

  1. 包含Caffe-SSD-Mobilenet

一、环境搭建:

  1. 1)和编译Caffe一样
  2. 1.应用 cudnn
  3. #USE_CUDNN := 1
  4. 修改成:
  5. USE_CUDNN := 1
  6. 2.应用 opencv 版本
  7. #OPENCV_VERSION := 3
  8. 修改为:
  9. OPENCV_VERSION := 3
  10. 3.使用 python 接口
  11. #WITH_PYTHON_LAYER := 1
  12. 修改为
  13. WITH_PYTHON_LAYER := 1
  14. 4.修改 python 路径
  15. INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
  16. LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib
  17. 修改为:
  18. INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial
  19. LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial
  20. 2)编译好caffe之后,运行报错caffe.proto找不到:
  21. caffe.proto 生成caffe.pb.cc caffe.pb.cc / caffe.pb.h,拷贝到相应位置(百度下即可)
  22. protoc src/caffe/proto/caffe.proto --cpp_out=.
  23. mkdir include/caffe/proto
  24. mv src/caffe/proto/caffe.pb.h include/caffe/proto

测试环境是否成功搭建:python2 demo.py

  1. cd caffe-ssd-mobile
  2. python2 demo.py

二、Caffe-SSD-Mobilenet 模型训练:

0.制作kitti数据集(voc格式):

  1. caffe-SSD生成的LMDB文件

1.建立数据集软连接

  1. $ cd ~/MobileNet-SSD
  2. $ ln s /home/gjw/data/KITTIdevkit/KITTI/lmdb/KITTI_trainval_lmdb trainval_lmdb
  3. $ ln s /home/gjw/data/KITTIdevkit/KITTI/lmdb/KITTI_test_lmdb test_lmdb
  4. 执行完命令,就能在项目文件夹下看到trainval_lmdbtest_lmdb软连接。

2.创建labelmap.prototxt文件

  1. item {
  2. name: "none_of_the_above"
  3. label: 0
  4. display_name: "background"
  5. }
  6. item {
  7. name: "car"
  8. label: 1
  9. display_name: "car"
  10. }
  11. item {
  12. name: "pedestrian"
  13. label: 2
  14. display_name: "pedestrian"
  15. }
  16. item {
  17. name: "cyclist"
  18. label: 3
  19. display_name: "cyclist"
  20. }

3.运行gen_model.sh脚本:用template中的prototxt,生成example中的prototxt(生成的prototxt是已经合并过bn层的)

  1. ./gen_model.sh 类别数+1 , 即./gen_model.sh 4
  2. 执行之后,得到examples文件夹,里面的3prototxt

4.修改训练和测试超参数

  1. 修改solver_train.prototxtsolver_test.prototxt
  2. test_iter=测试集图片数量/batchsize
  3. 初始学习率不宜太高,否则基础权重破坏比较严重;
  4. 优化算法是RMSProp,可能对收敛有好处,不要改成SGD,也是为了保护权重。

5.预训练模型(代码中已经存在):MobileNet_Pre_Train.caffemodel

6.开始训练,测试网络精度:sh train.sh

  1. 修改并运行train.sh脚本,中途可以不断调节参数。
  2. 训练结束后,运行test.sh脚本,测试网络的精度值。

三、(网络加速)训练完成之后,需要修改网络模型.prototxt:

1.修改merge_bn.py代码,合并bn层:

  1. 注解:snapshot/mobilenet_12000.caffemodel ---> snapshot/MobileNetSSD_deploy.caffemodel
  2. 打开merge_bn.py文件,然后注意修改其中的文件路径:
  3. caffe_root = '/home/gjw/caffe-ssd-mobile/'
  4. train_proto = 'example/MobileNetSSD_train.prototxt' #训练使用的example/MobileNetSSD_train.prototxt(不用修改)
  5. train_model = 'snapshot/mobilenet_12000.caffemodel' # 训练生成的caffemodel路径(需要修改)
  6. deploy_proto = 'example/MobileNetSSD_deploy.prototxt' #训练使用的example/MobileNetSSD_deploy.prototxt(不用修改)
  7. save_model = 'snapshot/MobileNetSSD_final.caffemodel' #合并后,caffemodel的保存路径
  8. 注解1:为了提高模型运行速度,作者在这里将bn层合并到了卷积层中,相当于bn的计算时间就被节省了,对检测速度可能有小幅度的帮助
  9. 注解2:运行merge_bn.py脚本后,就可以得到最终的检测模型,那这个模型由于合并了bn层,参数格式已经变化,就不能再用于训练了。
  10. 如果想继续训练,应该用合并前的。

2.depthwise convolution layer加速,修改example/MobileNetSSD_deploy.prototxt

  1. (1)将其中所有名为convXX/dwXX代指数字)的type从”Convolution”替换成”DepthwiseConvolution”,总共需要替换13处,从conv1/dwconv13/dw
  2. (2)把“engine: CAFFE”都注释掉
  3. 注释1caffemodel模型不用动,只修改example/MobileNetSSD_deploy.prototxt即可
  4. 注解2:下面三个是加入的注册DepthwiseConvolution层的代码
  5. epthwise_conv_layer.hpp
  6. depthwise_conv_layer.cpp
  7. depthwise_conv_layer.cu

四、(测试模型):

  1. 合并完成之后,用python2 demo.py代码进行测试:
  2. 调用example/MobileNetSSD_deploy.prototxt'snapshot/MobileNetSSD_final.caffemodel',就可以进行检测

============================================

ncnn

  1. (1)旧版caffe模型转新版caffe模型
  2. ~/caffe-ssd-mobile/build/tools/upgrade_net_proto_text model_kitti/old/MobileNetSSD_deploy.prototxt model_kitti/new/new_MobileNetSSD_deploy.prototxt
  3. ~/caffe-ssd-mobile/build/tools/upgrade_net_proto_binary model_kitti/old/MobileNetSSD_final.caffemodel model_kitti/new/new_MobileNetSSD_final.caffemodel
  4. (2)新版caffe模型转ncnn模型
  5. ~/ncnn/build/tools/caffe/caffe2ncnn ~/caffe-ssd-mobile/model_kitti/new/new_MobileNetSSD_deploy.prototxt ~/caffe-ssd-mobile/model_kitti/new/new_MobileNetSSD_final.caffemodel ~/caffe-ssd-mobile/model_kitti/new/mobilenet.param ~/caffe-ssd-mobile/model_kitti/new/mobilenet.bin
  6. 注意:生成的ncnn格式的模型中,.param可以理解为网络的配置文件,.bin可以理解为网络的参数(各种权重)文件。
  7. 注解:若需要对模型进行加密,可用如下命令
  8. $./ncnn2mem mobilenet.param mobilenet.bin mobilenet.id.h mobilenet.mem.h
  9. (3)最后可生成 mobilenet.param.bin 这样的二进制加密文件。ncnn对加密和非加密两种文件的读取方式不一样。
  10. //load非加密的ncnn模型
  11. ncnn::Net net;
  12. net.load_param("mobilenet.param");
  13. net.load_model("mobilenet.bin");
  14. //load加密的ncnn模型
  15. ncnn::Net net;
  16. net.load_param_bin("mobilenet.param.bin");
  17. net.load_model("mobilenet.bin");

============================================

Classification 二分类(Caffe+Alexnet)

一、训练数据集的准备

  1. 1)将数据集放在data/EyeData目录下
  2. 数据集目录结构:
  3. ~/data
  4. EyeData
  5. train
  6. open
  7. close
  8. val
  9. open
  10. close
  11. 说明:
  12. openclose分别存放不同类别的图像
  13. 2)新建/home/gjw/caffe-ssd/data/EyeData目录,“软连接”trainval数据集
  14. gjw@gjw:~/caffe-ssd/data/EyeData$ ln -s ~/data/EyeData/train train
  15. gjw@gjw:~/caffe-ssd/data/EyeData$ ln -s ~/data/EyeData/val val
  16. 3)制作数据集脚本,生成train.txtval.txt
  17. import os
  18. pwd_dir = os.getcwd()
  19. data = 'train'
  20. path = os.listdir(pwd_dir+'/'+ data)
  21. path.sort()
  22. file = open('train.txt','w')
  23. i = 0
  24. for line in path:
  25. str = pwd_dir+'/'+ data +'/'+line # /pwd/train/
  26. for child in os.listdir(str):
  27. str1 = data+'/'+line+'/'+child;
  28. d = ' %s' %(i)
  29. t = str1 + d
  30. file.write(t +'\n')
  31. i=i+1
  32. file.close()
  33. 执行 python2 train_txt.py,生成train.txt
  34. 执行 python2 val_txt.py,生成val.txt

二、生成leveldb数据集、均值文件

  1. 1】生成leveldb格式的数据集
  2. ./build/tools/convert_imageset --resize_height=256 --resize_width=256 --shuffle ./data/EyeData/ ./data/EyeData/train.txt ./data/EyeData/eye_train_leveldb --backend=leveldb
  3. ./build/tools/convert_imageset --resize_height=256 --resize_width=256 --shuffle ./data/EyeData/ ./data/EyeData/val.txt ./data/EyeData/eye_val_leveldb --backend=leveldb
  4. 2】生成均值文件
  5. ./build/tools/compute_image_mean ./data/EyeData/eye_train_leveldb ./data/EyeData/mean.binaryproto --backend=leveldb

三、网络配置文件(将bvlc_alexnet文件拷贝到caffe-ssd/data/EyeData目录下),修改网络配置文件

  1. (三/一)train_val.prototxt,修改见下:
  2. 1】均值文件,leveldb文件,batch_size
  3. name: "AlexNet"
  4. layer {
  5. name: "data"
  6. type: "Data"
  7. top: "data"
  8. top: "label"
  9. include {
  10. phase: TRAIN
  11. }
  12. transform_param {
  13. mirror: true
  14. crop_size: 227
  15. mean_file: "data/EyeData/mean.binaryproto" ###
  16. }
  17. data_param {
  18. source: "data/EyeData/eye_train_leveldb" ###
  19. batch_size: 32 ###256
  20. backend: LEVELDB ###
  21. }
  22. }
  23. layer {
  24. name: "data"
  25. type: "Data"
  26. top: "data"
  27. top: "label"
  28. include {
  29. phase: TEST
  30. }
  31. transform_param {
  32. mirror: false
  33. crop_size: 227
  34. mean_file: "data/EyeData/mean.binaryproto" ###
  35. }
  36. data_param {
  37. source: "data/EyeData/eye_val_leveldb" ####
  38. batch_size: 5 ####50
  39. backend: LEVELDB ###
  40. }
  41. }
  42. 2】最后一层fc8(重点)
  43. 2-1】修改num_output为自己的类别数2
  44. 2-2fc8层修改
  45. 修改fc8名字为fc8eye ####必须改名字
  46. lr_mult: 10 ##1
  47. decay_mult: 10 ##1
  48. lr_mult: 20 ## 2
  49. 修改见下:
  50. layer {
  51. name: "fc8eye"
  52. type: "InnerProduct"
  53. bottom: "fc7"
  54. top: "fc8eye"
  55. param {
  56. lr_mult: 10 ##1
  57. decay_mult: 10 ##1
  58. }
  59. param {
  60. lr_mult: 20 ## 2
  61. decay_mult: 0
  62. }
  63. inner_product_param {
  64. num_output: 2 ###1000
  65. weight_filler {
  66. type: "gaussian"
  67. std: 0.01
  68. }
  69. bias_filler {
  70. type: "constant"
  71. value: 0
  72. }
  73. }
  74. }
  75. (三/二)slover.prototxt修改
  76. net: "data/EyeData/bvlc_alexnet/train_val.prototxt" ##train_val.prototxt文件所在目录
  77. test_iter: 10 ###1000
  78. test_interval: 500 ###1000
  79. base_lr: 0.001 ### 学习率 0.01
  80. lr_policy: "step"
  81. gamma: 0.1
  82. stepsize: 5000 ###100000
  83. display: 20 ## 多少次显示一次
  84. max_iter: 1500 ### 最大迭代次数,最重要的参数----->坑死爹了,训练次数过多,过拟合
  85. momentum: 0.9
  86. weight_decay: 0.0005
  87. snapshot: 10000 ###多少次保存一次模型
  88. snapshot_prefix: "data/EyeData/bvlc_alexnet/model/alexnet" ## 模型保存路径model;模型名字alexnet_iter_1500.caffemodel
  89. solver_mode: GPU

四、训练

  1. ./build/tools/caffe train --solver=data/EyeData/bvlc_alexnet/solver.prototxt -gpu 0

五、进行测试单张图像类别预测

  1. 1deploy.prototxt修改(用于:预测图片class):只修改fc8层,修改与train_val.prototxtfc8层必须一致
  2. layer {
  3. name: "fc8eye"
  4. type: "InnerProduct"
  5. bottom: "fc7"
  6. top: "fc8eye"
  7. param {
  8. lr_mult: 10 ##1
  9. decay_mult: 10 ##1
  10. }
  11. param {
  12. lr_mult: 20 ## 2
  13. decay_mult: 0
  14. }
  15. inner_product_param {
  16. num_output: 2 ###1000
  17. weight_filler {
  18. type: "gaussian"
  19. std: 0.01
  20. }
  21. bias_filler {
  22. type: "constant"
  23. value: 0
  24. }
  25. }
  26. }
  27. 2】执行下面命令进行单张测试
  28. gjw@gjw:~/caffe-ssd$
  29. ./build/examples/cpp_classification/classification.bin data/EyeData/bvlc_alexnet/deploy.prototxt data/EyeData/bvlc_alexnet/model/alexnet_iter_10000.caffemodel data/EyeData/mean.binaryproto data/EyeData/bvlc_alexnet/labels.txt data/EyeData/test/0.jpg