使用Caffe对图像做训练、分类的流程总结

1. 环境

操作系统:windows7, 显卡:NVIDIA GTX 780

Caffe是直接从官方GitHub上down下来的,之前安装教程推荐了Happynear的版本,但不知道为什么,我只要使用GPU模式电脑就直接黑屏重启,折腾了好久还以为显卡坏了(有人说是供电不足),但用官方的版本则没问题。


2. 数据准备

1)将带标签图像数据按6:2:2(根据Andrew机器学习课程笔记(2)——神经网络、机器学习Tips中的推荐)分为 train,test,validate 3类,train和test在模型训练中使用,validate在模型精度测试中使用

../../../FaceDetection_CNN-master/crop_images/face/image12155_8.jpg 1
../../../FaceDetection_CNN-master/crop_images/face/image12155_9.jpg 1
../../../FaceDetection_CNN-master/crop_images/non-face/image04210_10.jpg 0
../../../FaceDetection_CNN-master/crop_images/non-face/image04210_13.jpg 0
../../../FaceDetection_CNN-master/crop_images/non-face/image04210_14.jpg 0
../../../FaceDetection_CNN-master/crop_images/face/image04210_16.jpg 1

如上所示为train.list的部分内容,后面的数字表示该样本所属类别(从0开始)。

根据实际情况可能还需要对train和test正负样本的比例做调整(我都调整为1:1,直接用copy的方式做填充),之后再将记录随机打乱以避免同类样本扎堆的情况

数据准备这块推荐使用Python实现,太方便了


2)Caffe接受直接图像数据(jpg,png等)、LevelDB和LMDB 3中数据格式,如果要使用后两种,还需将上一步的数据做转换

转换代码在 ./tools/convert_imageset.cpp,直接将其作为工程main文件即可

LMDB格式似乎在windows上没法用


3)一般来说还需生成一个mean.binaryproto的均值文件,其实就是统计所有训练样本的均值,将其作为样本的背景,以后在训练和测试中首先将样本减去该均值以排除背景干扰

相应代码在 ./tools/compute_image_mean.cpp,但这里只接受LevelDB或LMDB作为原始数据输入,因此如果要均值文件首先必须将数据转为LevelDB或LMDB格式


我在训练自己的数据时使用jpg格式,因此也就没有用均值文件(主要是之前测试发现数据格式基本不影响训练速度,而转为LevelDB格式所占的空间大很多,此外,没有用mean文件似乎对最终精度影响也不大,虽然从理论上mean是必要的)

Fine-tuning时使用初始模型对应的mean文件


3. 训练

需要用到 solver.prototxt 和 train.prototxt 两个定义文件,前者决定训练的一些参数,后者决定训练采用的CNN网络结构

solver.prototxt文件示例:

net: "../../../FaceDetection_CNN-master/train_val.prototxt"


#test迭代次数 如果batch_size =100,则100张图一批,训练157次,则可以覆盖15700张图的需求  
test_iter: 157


#训练迭代500次,测试1次
test_interval: 500

base_lr: 0.01          #<span style="color: rgb(68, 68, 68); font-family: 'Source Code Pro', monospace; font-size: 14px; line-height: 20.3px; white-space: pre; background-color: rgba(128, 128, 128, 0.0470588);">开始学习速率</span>
lr_policy: "step"      #<span style="color: rgb(68, 68, 68); font-family: 'Source Code Pro', monospace; font-size: 14px; line-height: 20.3px; white-space: pre; background-color: rgba(128, 128, 128, 0.0470588);">学习策略: 每stepsize次迭代之后,将α乘以gamma</span>
gamma: 0.1             #<span style="color: rgb(68, 68, 68); font-family: 'Source Code Pro', monospace; font-size: 14px; line-height: 20.3px; white-space: pre; background-color: rgba(128, 128, 128, 0.0470588);">学习速率变化因子</span>
stepsize: 20000
display: 20            #训练20次显示一次精度
max_iter: 100000       #<span style="color: rgb(68, 68, 68); font-family: 'Source Code Pro', monospace; font-size: 14px; line-height: 20.3px; white-space: pre; background-color: rgba(128, 128, 128, 0.0470588);">训练的最大迭代次数</span>
momentum: 0.9
weight_decay: 0.0005
snapshot: 10000        #每训练10000次保存一次模型
snapshot_prefix: "../../../FaceDetection_CNN-master/tune_model/gpu_alexNet_"
solver_mode: GPU

如果训练时发现精度发散,可以尝试减小学习率base_lr(默认为0.01),同样对于fine-tuning,也应设置个较低的base_lr(0.001)

对于fine-tuning,还应适当降低stepsize的值(20000),其实就是避免初始模型变得太快而导致发散


train.prototxt部分示例:

name: "CaffeNet"
layer {
  name: "data"
  type: "ImageData"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    #crop_size: 227
    #mean_file: "../../../IMG/img_mean.binaryproto"
  }
#  data_param {
#    source: "../../../IMG/trainLevelDB"
#    batch_size: 80
#    backend: LEVELDB
#  }
<span style="white-space:pre">	</span>image_data_param {
    source: "../../../IMG/train.list"
    batch_size: 50
    new_height: 250
    new_width: 340
  }
}
layer {
  name: "data"
  type: "ImageData"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    #crop_size: 227
    #mean_file: "../../../IMG/img_mean.binaryproto"
  }
#  data_param {
#    source: "../../../IMG/testLevelDB"
#    batch_size: 50
#    backend: LEVELDB
#  }
<span style="white-space:pre">	</span>image_data_param {
    source: "../../../IMG/test.list"
    batch_size: 30
    new_height: 250
    new_width: 340
  }
}
...
layer {
  name: "fc8"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
...

这里以官方的caffeNet网络结构做细微修改

输入数据格式改为imagedata,相应的data_param也改为image_data_param,mean_file也不用了,此外由于图像尺寸较大(340*250),需要适当缩小batch_size的值,否则使用GPU时可能超出其缓存大小而报错

最后一层的全连接层的输出改为2(因为这个例子是2元分类),对于fine-tuning,这一层的lr_mult需要适当增加(10),因为这一层在fine-tuning中需要变的最多


主程序部分

./tools/caffe.cpp,无需修改,直接拿来用就成。

在slover.cpp里添加了误差记录代码,每次test画出其误差曲线(图1)


图1. 误差曲线


4. 分类(验证)

需要用到deploy.prototxt,其主体与train.prototxt类似,都是定义CNN模型结构,但输入形式不一样(这里只是针对一个样本,而train这对一批样本),此外train最后的accuracy层和loss层也需换成prob层


deploy.prototxt部分示例:

name: "CaffeNet"
input: "data"
input_dim: 10
input_dim: 3
input_dim: 250  #height
input_dim: 340  #width
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 96
    kernel_size: 11
    stride: 4
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
...
layer {
  name: "prob"
  type: "Softmax"
  bottom: "fc8"
  top: "prob"
}


主程序部分

主要参考 ./examples/cpp_classification/classification.cpp
如果是用作模型精度测试,建议添加查全率和查准率的计算,避免测试样本不平衡的影响


P.S. 训练和分类都要用同一种计算模式(CPU或GPU),否则会出错(估计是两种模式生成的caffemodel文件不同)

P.P.S 一个不错的参考:Caffe学习:Solver

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值