caffe新手常遇到的三个问题

  刚刚训练完了mnist数据集,不过大多数人肯定都是按照网上的博客一步一步跟着操作的吧!其实也不是很懂。不知道你的心里是否有以下三个问题呢?

  1.怎么进行数据格式处理?/怎么生成LMDB/LEVELDB格式数据?

  2.怎么编写网络结构文件?

  3.怎么编写网络求解文件?

  这篇文章,我们就来回答一下这三个问题。为以后自己熟练的训练模型打下一个坚实的基础!

一、怎么进行数据格式处理?/怎么生成LMDB/LEVELDB格式数据?

  在caffe中,作者为我们提供了这样一个文件:convert_imageset.cpp,存放在根目录下的tools文件夹下。编译之后,生成对应的可执行文件放在 buile/tools/ 下面,这个文件的作用就是用于将图片文件转换成caffe框架中能直接使用的lmdb文件。

  通用步骤:

  1. 获取数据集
  (如果网上有的可以下载,也可以自己进行制作)数据集就是图片,目前数据集格式可能是png,jpg,bmp或二进制文件等等

  2. 为自己的数据制作标签(label)
  在caffe中,标签制作比较麻烦,但也有方法可循。标签文本文件的内容就是图片的位置后加图片的类别。例如(/home/user/1.jpg 1)。标签的文件制作,后面会专有一篇博客去谈论,感兴趣的朋友可以写出来后去参考。(ps:对于mnist数据集因为是caffe本身自带,就让标签这部分透明了,使用者不需要去管。但要想搞自己的东西,这步还是必不可少滴!)

  3. 调用caffe工具(图像格式转换):
  以mnist数据集为例:Minst数据集转换工具位置:caffe/examples/minst/convert_cifar_data.cpp。运行.examples/minst/create_minsh.sh(不过数据集转换的脚本需要我们自己编写,后面的博客我也会详细介绍滴!)生成lmdb格式的位置是自己定义的。比如mnist数据集中就会在caffe/examples/minst/下生成的。

二、怎么编写网络结构文件?

  打开网络结构的文件,会发现都是Layer。Layer是什么呢?(我在此简单的介绍下,更为详细的还要去看caffe的语法书)
  Layer是一个大类:主要包含NeuronLayer类,LossLayer类,数据。
基本格式:
Layer{
  xxx:”xxx”
  xxx:”xxx”
}
Layer的结构是:
layers {
  bottom: “decode1neuron” // 该层底下连接的第一个Layer,代表输入
  bottom: “flatdata” // 该层底下连接的第二个Layer
  top: “l2_error” // 该层顶上连接的一个Layer,代表输出
  name: “loss” // 该层的名字
  type: EUCLIDEAN_LOSS // 该层的类型
  loss_weight: 0
}
  注意
  bottom是上面的层,个数不唯一,top是下面的层。可理解为bottom是输入,top是输出。后面的内容就是每层的name

  type是层数的种类,是基本固定的。类型种类如下(具体情况见caffe/proto):

  1)vision 5层:Convolution,Deconvolution,Im2col,LRN,Pooling

  2)激活 9层:AbsVal,BNLL,Dropout,Power,ReLU,Sigmoid,TanH, Threshold ,EXP

  3)common 10层:ArgMax,Concat,Eltwise,Flatten,InnerProduct,MVN,Silence,Softmax,Split,Slice

  4)data 7层:Data,DummyData,HDF5Data,HDF5Output,ImageData,MemoryData,WindowData

  5)loss 8个:Accuracy,ContrastiveLoss,EuclideanLoss,HingeLoss,InfogainLoss,MultinomialLogisticLoss,SigmoidCrossEntropyLoss,SoftmaxWithLoss

  Param中包含本层的参数,参数不止一个,各个独立的参数之间使用{}分隔。独立参数内包括各个超参数。整体格式为:

Param{
  超参数类型:超参数数值
}
  (什么是超参数呢?为什么会有一个“超”字呢?(cool!)其实所谓的超参数,就是模型中那些可以人为设定的参数,通过修改超参数可进行模型的微调。为了与一般的参数区别,即谓之超参数。~哦,原来是这样!)

  卷积层超参数类型包括:num_output(卷积核个数), pad, kernel_size, stride等(超参数类型取决于param的类型,我猜应该有张表,但我未找到)
  大家可以从下面这位博主的这篇博客里见一见卷积层,激活层的示例,会更深刻的理解:https://blog.csdn.net/wendygelin/article/details/88405871[]link](https://blog.csdn.net/wendygelin/article/details/88405871)

  下面开始正式回答第二个问题:
  答案就是:基本不用自己写。只需要每次改变下train和test两个Layer中lmdb的位置就行。(当然了,此方法只适用于新手。到了后期肯定要开发出自己的模型。但那个时候水平相比很高了,就不是我能说的了~)

三、怎么编写网络求解文件(solver文件)?

  Slover作为控制模型的核心,我理解为整个模型的头文件。

  Slover文件中包括写程序的人设置的一些超参数(学习率,优化器类型,迭代次数等等)

  对于solver文件的介绍给大家推荐一篇博客,感觉写的比我好多了(我不再献丑了~):https://blog.csdn.net/qq_26898461/article/details/50445392link
  不过我给大家介绍一下目前为止,我经历过solver文件中常修改的参数:
  因为我们的模型大多是从网络上下载的——对对对!就是那个面向github编程。关于优化器的一些参数都是已经调好的,不再修改。当然,路过大神请无视,当听了个玩笑。
  常修改的参数包括网络文件参数net、测试集迭代次数test_iter(有需要的修改)、终端间隔显示display(这个我建议CPU的选手可以初始设定为1,看迭代1次需要花多长时间,再判断迭代多少次比较合适)、最大迭代数max_iter、训练多少次保留caffemodel的snapshot、caffemodel保留位置参数snapshot_prefix、决定训练方式的solver_mode。例如mnist数据集的solver文件如下:

# The train/testnet protocol buffer definition
net:"examples/mnist/lenet_train_test.prototxt"

# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
#测试集迭代100次:共10000/100 = 100,每次100个样本
test_iter: 100

# Carry out testing every 500 training iterations.
#每训练500次迭代,进行一次测试
test_interval: 500

# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01

#冲量,在SGD优化器中可以达到避免震荡的作用
momentum: 0.9

#权值衰弱常数,防止过拟合。在训练期间,将正则化项添加到网络的损失中以计算后向梯度。 weight_decay值确定该正则化项在梯度计算中的优势
weight_decay:0.0005

# The learningrate policy
#学习率计算的方法,共有七种,根据base_lr和learning_rate_lr计算。inv计算公式是 base_lr * (1 + gamma * iter) ^ (- power)所以之后两个参数是gamma和power
lr_policy:"inv"

gamma: 0.0001

power: 0.75

#每100次迭代在终端中显示一次xxx
# Display every 100 iterations
display: 100

# The maximumnumber of iterations
max_iter: 10000

# snapshotintermediate results
#snapshot用来保存模型,每经过指定次数会形成一个模型,以后再训练时可在其基础上训练
snapshot: 5000

snapshot_prefix:"examples/mnist/lenet"

# solver mode: CPUor GPU
solver_mode: CPU

  买三送一,再来一个!

  迭代和epoch的区别?
  迭代是进行完一次batch_size,一个epoch是进行完一个数据集内所有的数据,一个epoch中有个total/batch_size次迭代。

  学习就是慢慢解决问题的过程,希望以后遇到的问题越来越多,解决的问题也越来越多。不过这三个问题(哦,四个)你也解决了吗?

由于本文作者水平有限,如有不足之处,请下方评论区指正,谢谢!

猜你喜欢

转载自blog.csdn.net/gls_nuaa/article/details/107622645