caffe的步骤:1)数据源
2)定义一个网络(包含数据层、卷积层、池化层、激活层、全连接层等)
3)定义solver(里面有很多参数)
4)训练网络
定义网络
数据层
layer {
name: "cifar"
type: "Data"
top: "data" #一般用bottom表示输入,top表示输出,多个top代表有多个输出
top: "label"
include {
phase: TRAIN #训练网络分为训练阶段和自测试阶段,如果没写include则表示该层即在测试中,又在训练中
}
transform_param {
mean_file: "examples/cifar10/mean.binaryproto" #用一个配置文件来进行均值的操作
transform_param {
scale: 0.00390625
mirror: 1 # 1表示开启镜像,0表示关闭,也可用ture和false来表示
# 剪裁一个 227*227的图块,在训练阶段随机剪裁,在测试阶段从中间裁剪
crop_size: 227
}
}
data_param {
source: "examples/cifar10/cifar10_train_lmdb" #数据库来源路径
batch_size: 64 #每次批处理图像的个数,一般取2^n,与GPU相关
backend: LMDB #选用数据的名称
}
}
scale: 0.00390625
scale表示归一化,像素范围为0~255,归一化为0~1,而1/255 = 0.0039
mirror 作用:数据增强,通过对图像做翻转或镜像来丰富数据
crop_size:277
在train时会对大于crop_size的图片进行随机裁剪,而在test时只是裁剪图像的中间区域。代码如下图所示
//We only do random crop when we do training.
if (phase_ == TRAIN) {
h_off = Rand(datum_height - crop_size + 1);
w_off = Rand(datum_width - crop_size + 1);
} else {
h_off = (datum_height - crop_size) / 2;
w_off = (datum_width - crop_size) / 2;
}
}
backend: LMDB
数据源一般有2种格式: LMDB —— 用作分类
HDF5 —— 用作回归
卷积层
layer {
name: "conv1" #这层的名字
type: "Convolution" #表示此层为卷积层
bottom: "data" #输入数据层的数据
top: "conv1" #输出卷积后的结果
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20 #卷积核(filter)的个数,可得到20个特征图
kernel_size: 5 #卷积核的大小,实际中为5*5*deep,此深度与上一层深度一致
stride: 1 #卷积核的步长,每次移动一格,默认为1
pad: 0 #扩充边缘,默认为0,不扩充。当为n时在原图外圈加n层0
weight_filler {
type: "xavier" #权值初始化。
}
bias_filler {
type: "constant" #偏置项的初始化。一般设置为"constant",值全为0
}
}
}
输入:n*c0*w0*h0
输出:n*c1*w1*h1
其中,c1就是参数中的num_output,生成的特征图个数
w1=(w0+2*pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
lr_mult: 1
lr表示learning rate,设置当前层的学率,可以与solver中的学习率不同。最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。
weight_filler {
type: "xavier" #权值初始化。
}
默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian"。实际中可试试多种权值初始化方法,看哪个效果好,即令log下降的低、快
池化层
pool: MAX 池化方法,默认为MAX。目前可用的方法有MAX, AVE
kernel_size: 3 池化的核大小
stride: 2 池化的步长,默认为1。一般我们设置为2,即不重叠。
激活层
一般有这三种方法:
1)sigmod
2)ReLU 是目前使用最多的激活函数,主要因为其收敛更快,并且能保持同样效果。标准的ReLU函数为f(x)=max(x, 0),当x>0时,输出x; 当x<=0时,输出0
3)tan
全连接层
输出的是一个简单向量 参数跟卷积层一样,相当于把之前提取的特征再总结一遍,之后就可进行分类或回归等任务
name: "accuracy"
type: "Accuracy"
bottom: "ip2" #全连接层的数据
bottom: "label" #给定的label,即ground truth
top: "accuracy" #输出当前迭代的准确率
softmax-loss
#softmax-loss layer:输出loss值
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip1"
bottom: "label"
top: "loss"
}
#softmax layer: 输出似然值,概率值
layers {
bottom: "cls3_fc"
top: "prob"
name: "prob"
type: “Softmax"
}
reshape层
在不改变数据的情况下,改变输入的维度。
例:32×3×28×28 32×3×14×56 32为批处理32张图像 × 3个通道 × h × w
shape {
dim: 0 # 维度不变
dim: 0
dim: 14 # 将维度指定为14
dim: -1 # 从其它维度推断,因为总数不变
}
Dropout
#Dropout是一个防止过拟合的层
#只需要设置一个dropout_ratio就可以了。
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7-conv"
top: "fc7-conv"
dropout_param {
dropout_ratio: 0.5 # 杀死50%的神经元
}
}
solver超参数配置文件
caffe提供了六种优化算法来求解最优参数,在solver配置文件中,通过设置type类型来选择:
Stochastic Gradient Descent (type: "SGD"), 随机梯度下降
AdaDelta (type: "AdaDelta"),
Adaptive Gradient (type: "AdaGrad"),
Adam (type: "Adam"),
Nesterov’s Accelerated Gradient (type: "Nesterov") and
RMSprop (type: "RMSProp")
net: "examples/mnist/lenet_train_test.prototxt" #指明net的位置
test_iter: 100 #让 batch * test_iter = 测试样本个数,用来跑遍所有测试样本
test_interval: 500 #每迭代500次测试一下loss或准确率
base_lr: 0.01 #基础学习率
momentum: 0.9 #动量
type: SGD
weight_decay: 0.0005 #权值衰减,防止过拟合
lr_policy: "inv" #学习率调整策略,还有step,multistep等
gamma: 0.0001
power: 0.75
display: 100 #每训练100次,在屏幕上显示一次,若设置为0则不显示
max_iter: 20000 #最大迭代次数,迭代20000次停止
snapshot: 5000 #每迭代5000次保存一下模型,建议选小点,因为loss呈浮动下降趋势
snapshot_prefix: "examples/mnist/lenet" #模型保存的位置
solver_mode: CPU #运行模式,CPU或GPU