当前位置:   article > 正文

【深度学习】笔记6:使用caffe中的CIFAR10网络模型和自己的图片数据训练自己的模型(步骤详解)_深度学习——caffe之经典模型详解与实战

深度学习——caffe之经典模型详解与实战

(一)准备自己的图片数据库

     

1)我的训练图片图片和测试图片的来源:

      

       我的图片来源于徐其华的博客,(http://www.cnblogs.com/denny402/p/5083300.html).这是一个小型的图片数据库,这个图片数据库有500张图片;训练样本400张,测试样本100张;分为5类:bus,dinosaur,elephant,rose,horse(大巴,恐龙,大象,鲜花,马)。

     图片的size==(384*256);图片格式为JPG格式.由于我在此块使用的是CIFAR-10模型,而在CIFAR10模型中,训练样本和测试样本的图片size==(32*32)(pixel),因此在我们开始训练自己的模型之前,我们首先需要对所有的图片进行预处理.其中最重要的预处理操作就是:图片尺寸的归一化.

    在此块,我基于OpenCv写了一个预处理Demo程序,具体的程序如下所示:

  1. /*******************************************************************************************************************
  2. *文件功能:
  3. * 1--针对CIFRA-10模型,进行的图片处理程序,将图片处理成32*32的大小
  4. * 2--用于更改图片的图片名,后缀图片格式,图片的大小
  5. * win10+vs2013+OpenCv2.4.8
  6. *时间地点:
  7. * 陕西师范大学 2016.10.28
  8. ********************************************************************************************************************/
  9. #include<stdio.h>
  10. #include<iostream>
  11. #include<opencv2/core/core.hpp>
  12. #include<opencv2/highgui/highgui.hpp>
  13. #include<opencv2/imgproc/imgproc.hpp>
  14. #include<opencv2/core/core_c.h>
  15. #include<opencv2/imgproc/imgproc_c.h>
  16. using namespace std;
  17. using namespace cv;
  18. int main()
  19. {
  20. char strFilename[100]; //【1】定义一个字符数组保存----图片的存储路径
  21. char strWindowname[100]; //【2】定义一个字符数组保存----用于动态更新窗口的窗口名
  22. char strFilenameAft[100]; //【3】定义一个字符数组保存----用于给处理之后的图片动态的命名
  23. int j = 1;
  24. for (int i = 720; i <=799; i++)
  25. { //【4】将图片的路径名动态的写入到strFilename这个地址的内存空间
  26. sprintf_s(strFilename, "D:\\mydata\\train\\%d.jpg", i);
  27. sprintf_s(strFilenameAft, "D:\\mydata\\aft_train\\horse%d.jpeg", j);
  28. sprintf_s(strWindowname, "srcImg%d", j);
  29. //===========================================================================================
  30. //【模块1】将图片读入内存,并显示
  31. //===========================================================================================
  32. IplImage* pImg = cvLoadImage(strFilename); //【1】从指定的路径,将图片加载到内存中
  33. cvNamedWindow(strWindowname, CV_WINDOW_AUTOSIZE); //【2】创建一个显示图片的窗口
  34. cvMoveWindow(strWindowname, 200, 200); //【3】将显示窗口固定在(200,200)这个位置显示都进来的图片
  35. cvShowImage(strWindowname, pImg); //【4】显示图片
  36. //===========================================================================================
  37. //【模块2】高斯金字塔下采样
  38. // 1----将图片size调节到32*32左右,并显示
  39. // 2----384*256:经过连续三次下采样,变为48*32
  40. //============================================================================================
  41. IplImage* pPyrDownImg = cvCreateImage(cvSize(pImg->width / 2, pImg->height / 2), pImg->depth, pImg->nChannels);
  42. IplImage* pPyrDownImg1 = cvCreateImage(cvSize(pPyrDownImg->width / 2, pPyrDownImg->height / 2), pPyrDownImg->depth, pPyrDownImg->nChannels);
  43. IplImage* pPyrDownImg2 = cvCreateImage(cvSize(pPyrDownImg1->width / 2, pPyrDownImg1->height / 2), pPyrDownImg1->depth, pPyrDownImg1->nChannels);
  44. cvPyrDown(pImg, pPyrDownImg, CV_GAUSSIAN_5x5); //【1】384*256--->192*128
  45. cvPyrDown(pPyrDownImg, pPyrDownImg1, CV_GAUSSIAN_5x5);//【2】192*128--->96*64
  46. cvPyrDown(pPyrDownImg1,pPyrDownImg2, CV_GAUSSIAN_5x5);//【3】96*64----->48*32
  47. cvNamedWindow("【PyrDown】", CV_WINDOW_AUTOSIZE);
  48. cvMoveWindow ("【PyrDown】", 500, 200);
  49. cvShowImage("【PyrDown】", pPyrDownImg2);
  50. //============================================================================================
  51. //【模块3】设置ROI区域裁剪图片----利用ROI区域将图片裁剪为:32*32
  52. //============================================================================================
  53. cvSetImageROI(pPyrDownImg2, cvRect(8, 0, 32, 32));//【1】设置一个32*32的ROI区域
  54. cvNamedWindow("【ROI_Img】");
  55. cvMoveWindow ("【ROI_Img】", 700, 200);
  56. cvShowImage ("【ROI_Img】", pPyrDownImg2);
  57. cvSaveImage (strFilenameAft, pPyrDownImg2); //【2】将修改图片size之后的图片保存在指定的文件夹下
  58. ++j;
  59. cv::waitKey(10);
  60. //============================================================================================
  61. //【模块4】释放内存空间
  62. //============================================================================================
  63. cvReleaseImage(&pPyrDownImg);
  64. cvReleaseImage(&pImg); //【1】释放掉存储图片的内存
  65. cvDestroyWindow(strWindowname); //【2】销毁窗口的内存
  66. cvDestroyWindow("【ROI_Img】");
  67. cvDestroyWindow("【PyrDown】");
  68. }
  69. return 0;
  70. }

       

        使用上面程序对Image进行图片尺寸归一化,命名的统一等操作.

        没有使用程序处理之前的图片(384*256),图片的命名也不统一,如下图所示:



       

       使用程序处理之后的图片,全部变为32*32的JPEG格式的图片,并且图片的命名也进行了统一:




      2)建立自己的数据文件夹

      在./caffe/data/目录下建立自己的数据文件夹myself,并且在myself文件夹下建立train文件夹和val文件夹.train文件夹用于存放训练样本,val文件夹用于存放测试样本(验证集),如下图所示:

     

     

     然后,将你处理好的训练样本图片放在./caffe/data/myself/train/这个文件夹下面,测试样本放在./caffe/data/myself/val/这个文件夹下面.

3)编写train.txt和val.txt文本

    1----train.txt----存放训练图片的图片名和类别标签,一行一张图片,如下所示:

          (这块要特别注意的一点是:在下面这两个文本文件中,图片名和标签之间的距离,只能是一个空格键),如果这两者之间的距离多于或者少于一个[空格键的话],那么,在图片数据---》LMDB数据格式这一步一般不会报错,但是,当计算均值的时候,会出现错误或者问题)

         (比如下面文本文档,我使用了4个空格,就出现了这种问题,现在大家把他们之间的距离调整为一个空格,就可以运行了)


    2----val.txt------存放测试样本的图片名和类别标签,一行代表一张图片,如下图所示:

(二)将图片数据转换为LMDB格式的数据:

           在./caffe/examples/文件夹下面,建立myself文件夹,并且将:./caffe/examples/imagenet/文件夹下面的create_imagenet.sh这个shell脚本copy到myself文件夹下,打开,将里面的内容更改为下面的形式,如图所示:


  1. #!/usr/bin/env sh
  2. # Create the myself lmdb inputs
  3. # N.B. set the path to the myself train + val data dirs
  4. set -e
  5. EXAMPLE=examples/myself
  6. DATA=data/myself
  7. TOOLS=build/tools
  8. echo "Creating train lmdb..."
  9. GLOG_logtostderr=1 $TOOLS/convert_imageset.bin \
  10. --resize_height=32 \
  11. --resize_width=32 \
  12. --shuffle \
  13. /home/wei/caffe/data/myself/train/ \
  14. $DATA/train.txt \
  15. $EXAMPLE/myself_cifar10_train_lmdb
  16. echo "Creating val lmdb..."
  17. GLOG_logtostderr=1 $TOOLS/convert_imageset.bin \
  18. --resize_height=32 \
  19. --resize_width=32 \
  20. --shuffle \
  21. /home/wei/caffe/data/myself/val/ \
  22. $DATA/val.txt \
  23. $EXAMPLE/myself_cifar10_val_lmdb
  24. echo "Done."
      并且,将这个shell脚本的文件名改为:create_cifar_lmdb.sh,使用下面的命令运行,则会产生两个数据库文件:

         产生的连个数据库文件,如下图所示:

(三)计算图像的均值(减均值操作)

        在./caffe/examples/myself/文件夹下面,创建make_myself_mean.sh这个shell脚本,并且编辑内容如下所示:

  1. #!/usr/bin/env sh
  2. # Compute the mean image from the myself training lmdb
  3. # N.B. this is available in data/myself
  4. TOOLS=./build/tools
  5. DATA=./data/myself
  6. EXAMPLE=./examples
  7. $TOOLS/compute_image_mean.bin $EXAMPLE/myself/myself_cifar10_train_lmdb $EXAMPLE/myself/myself_cifar10_mean.binaryproto
  8. echo "Done."

     在终端执行这个脚本文件,则会产生一个名为:myself_cifar10_mean.binaryproto的均值文件,如下所示:




(四)创建网络模型,编写配置文件,编写训练脚本

        1)创建网络模型

          此快,我们使用CIFAR10网络模型,因此,将./examples/cifar10/文件夹下的cifar10_quick_train_test.prototxt网络模型配置文件copy到我们的文件夹./examples/myself/下面,并且进行如下的修改:

  1. name: "CIFAR10_quick"
  2. layer {
  3. name: "cifar"
  4. type: "Data"
  5. top: "data"
  6. top: "label"
  7. include {
  8. phase: TRAIN
  9. }
  10. transform_param { //【第1块修改的地方】下面是均值文件所在的路径,改为你自己的均值文件所在的路径
  11. mean_file: "examples/myself/myself_cifar10_mean.binaryproto"
  12. }
  13. data_param { //【第2块修改的地方】下面改为训练样本生成的数据库所在的目录[注意:是训练样本数据库]
  14. source: "examples/myself/myself_cifar10_train_lmdb"
  15. batch_size: 10 //【第3块修改的地方】由于我们的训练样本只有400张图片,所以我们一次读入10张图片就可以了
  16. backend: LMDB
  17. }
  18. }
  19. layer {
  20. name: "cifar"
  21. type: "Data"
  22. top: "data"
  23. top: "label"
  24. include {
  25. phase: TEST
  26. }
  27. transform_param { //【第4块修改的地方】下面是均值文件所在的路径,改为你自己的均值文件所在的路径
  28. mean_file: "examples/myself/myself_cifar10_mean.binaryproto"
  29. }
  30. data_param { //【第5块修改的地方】下面改为测试样本生成的数据库所在的目录[注意:是测试样本数据库]
  31. source: "examples/myself/myself_cifar10_val_lmdb"
  32. batch_size: 10 //【第6块修改的地方】由于我们的测试样本只有100张图片,所以我们一次读入10张图片就可以了
  33. backend: LMDB
  34. }
  35. }
  36. layer {
  37. name: "conv1"
  38. type: "Convolution"
  39. bottom: "data"
  40. top: "conv1"
  41. param {
  42. lr_mult: 1
  43. }
  44. param {
  45. lr_mult: 2
  46. }
  47. 中间的省略.......
  48. layer {
  49. name: "ip2"
  50. type: "InnerProduct"
  51. bottom: "ip1"
  52. top: "ip2"
  53. param {
  54. lr_mult: 1
  55. }
  56. param {
  57. lr_mult: 2
  58. }
  59. inner_product_param {
  60. num_output: 5 //【第7块修改的地方】我们现在是5分类问题,所以将第二个全连接层改为5
  61. weight_filler {
  62. type: "gaussian"
  63. std: 0.1
  64. }
  65. bias_filler {
  66. type: "constant"
  67. }
  68. }
  69. }
  70. layer {
  71. name: "accuracy"
  72. type: "Accuracy"
  73. bottom: "ip2"
  74. bottom: "label"
  75. top: "accuracy"
  76. include {
  77. phase: TEST
  78. }
  79. }
  80. layer {
  81. name: "loss"
  82. type: "SoftmaxWithLoss"
  83. bottom: "ip2"
  84. bottom: "label"
  85. top: "loss"
  86. }

        (2)编写超参数配置文件:

         我们也是用同样的方法,直接将./examples/cifar10/文件夹下的cifar10_quick_solver.prototxt这个超参数配置文件

copy到我们的目录下,然后,进行下面的修改就可以了:

  1. #!/usr/bin/env sh
  2. set -e
  3. TOOLS=./build/tools
  4. $TOOLS/caffe train \
  5. --solver=examples/myself/cifar10_quick_solver.prototxt $@

  1. //【1】改为你自己的网络模型配置文件的目录
  2. net: "examples/myself/cifar10_quick_train_test.prototxt"
  3. test_iter: 10 //【2】预测阶段迭代次数,我们设为10,这样就可以覆盖我们的100张测试样本
  4. test_interval: 50 //【3】由于我们只有400张训练样本,所以我们将此改为50,每迭代50次,进行一次测试
  5. base_lr: 0.001 //【4】权值学习率,其实就是在反向传播阶段,权值每次的调整量的程度
  6. momentum: 0.9
  7. weight_decay: 0.004
  8. lr_policy: "fixed" //【5】在整个过程中,我们使用固定的学习率,当然,你也可以试一下可变学习率
  9. display: 20
  10. max_iter: 500 //【6400张训练样本,所以我就将最大的迭代次数设为400
  11. snapshot: 400
  12. snapshot_format: HDF5
  13. snapshot_prefix: "examples/myself/cifar10_quick"
  14. solver_mode: CPU //【7】我用的是CPU,所以将此快设置为CPU

(3)编写训练脚本

  1. #!/usr/bin/env sh
  2. set -e
  3. TOOLS=./build/tools
  4. $TOOLS/caffe train \
  5. --solver=examples/myself/cifar10_quick_solver.prototxt $@

然后,运行命令,训练自己的模型:如下图所示:

sudo sh ./examples/myself/train_quick.sh

     训练过程,如下所示:

     训练结果显示,正确率为90%,accuracy==0.9,如下图所示:


(五)训练结果的可视化

1---Accuracy曲线的可视化:

      我们以迭代次数为X轴,以准确率为Y轴,输出的曲线如下所示:

2---Loss曲线的可视化:

        我们同样以迭代次数为X轴,以损失率为Y轴,可视化结果如下所示:


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/133358
推荐阅读
相关标签
  

闽ICP备14008679号