1.caffe介绍
caffe是一种简单易用的机器学习框架。最大的特点是,网络结构层是使用配置文件设置的,而不需要编写代码。所以在训练网络模型阶段,甚至可以不用编写代码。
2.caffe配置文件说明
2.1文件说明
使用caffe时会用到以下文件,需要说明的是,文件名是自定义的,但一般会加上“train”,“solver”,”deploy”来用于区分作用。
train.prototxt:定义了训练时的网络结构
solver.prototxt:配置训练时所需要的一些超参数,如学习率等
deploy.prototxt:发布时使用的网络结构,最终使用网络模型来计算结果时使用,与tarin.prototxt差不多,修改了输入和输出层
xxxx.caffemodel:训练后的结果,里面保存了各个网络层的参数,搭配deploy.prototxt使用,用于最终的预测。
2.2 train.prototxt/deploy.prototxt:网络配置文件说明
在该文件中,用layer表示一个层,以下是一个数据层的表示
数据层
layer {
name: "train-data" # 层的名称
type: "Data" # 层的类型
top: "data" # 层的输出
top: "label" # 层的输出,可以有多个输出
include {
phase: TRAIN # 表示用于训练,如果是TEST,则表示用于测试
}
# 对数据进行预处理
transform_param {
mirror: true # 镜像变化,把输入进行镜像变化,可得到双倍的数据
crop_size: 227 # 将矩阵转化为227*227的大小
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" # 指定均值文件,用于标准化数值
}
# 对数据源的配置
data_param {
source: "examples/imagenet/ilsvrc12_train_lmdb" # 数据源路径
batch_size: 256 # 批次大小,每次训练的数量
backend: LMDB # 数据源格式
}
# 如果使用的是HDF5格式,hdf5可用于多标签数据
#hdf5_data_param{
# source: "./tain.txt" # 数据源,tain.txt的内容是train.h5的路径
# batch_size:10
#}
# 如果是直接使用图片
# layer{
# name:"data"
# type:"data"
# top:"data"
# top:"label"
# image_data_param{
# source:"list.txt" # 数据源 list.txt的内容是图片的路径+空格+图片标签
# batch_size:50
# new_height:256
# new_width:256
# }
}
疑问1:为什么要使用均值文件,而不自己计算均值?
这里使用的是imageNet数据集的均值文件,由于imageNet的数据量非常大,所以它的均值具有一定代表性,可以使用它来表示我们数据集的均值疑问2:各个数据源格式有什么不同?
- lmdb格式用于处理单标签的数据集,如图片分类任务,每个图片只有一个分类,所以标签只有一个
- hdf5格式用于处理多标签的数据集,如人脸关键点,人脸的关键点有很多个,所以必须有多个标签来表示
- 直接调用图片:由于系统做IO计算是一件非常慢的事,所以直接用图片,会严重拖慢训练速度,所以训练时一般不使用直接调用图片的方式。
- 疑问3:批次的作用是什么?
批次表示每次训练时,一次性调用多少张图像。调用的图像越多,训练的结果越具有代表性,但是同时对显存(如果使用的是GPU)的要求越大,如果批次的数量过大,超过系统的最大显存,可能会导致运行报错。
卷积神经网络
layer {
name: "conv1"
type: "Convolution" # 卷积网络的类型
bottom: "data" # 输入,输入为数据层
top: "conv1"
# 参数的学习率
param {
lr_mult: 1.0 # 学习率,最终的学习率需要乘于Solver.prototxt中的base_lr
decay_mult: 1.0 # 衰减系数
}
# 偏置的学习率,一般设置为参数学习率的两倍,能够加速收敛
param {
lr_mult: 2.0
decay_mult: 0.0
}
convolution_param {
num_output: 96 # 卷积核的个数
kernel_size: 11 # 卷积核的大小,如果核的长和宽不等,需要用 kernel_h 和 kernel_w 分别设定卷积
stride: 4 # 每次移动的步长,默认为1。也可以用stride_h和stride_w来设置
pad:1 # 扩充边缘填充,也可以通过pad_h和pad_w来分别设定
# 参数权重值初始化
weight_filler {
type: "gaussian" # 高斯初始化,也可以使用 "xavier","constant"
std: 0.01 # 高斯分布的标准差
}
# 偏置参数初始化
bias_filler {
type: "constant" # 常量值初始化
value: 0.0 # 常量的值
}
}
}
- 疑问1:decay_mult:权值衰减有什么用?
为了避免过拟合,对损失函数加入规范项(这里其实不是很明白?) - 疑问2:各种初始化参数的方法具体算法
- gaussian:高斯初始化
- constant:常量初始化
- xavier:http://blog.csdn.net/shuzfan/article/details/51338178
- 疑问3:pad的作用
增加对边缘像素的权重值。 - 卷积层的输出大小
- height_out=(height-kernel_size+2pad)/stride+1
- width_out=(width-kernel_size+2pad)/stride+1
池化层
layer{
name:"pool1"
type:"Pooling"
top:"pool1"
pooling_param{
pool:MAX #池化方法,默认为MAX,AVE(平均)
kernel_size:3# 池化的核大小
stride:2 #池化层步长
}
}
全连接层
layer{
name:"ip"
type:"InnerProduct"
buttom:"pool2"
inner_product_param{
num_output:500 # 输出的数量
weight_filler:{type:"xavier"}
bias_filler:{type:"constant"}
}
}
激活层
- relu:非线性层
layer{
name:"relu1"
type:"Relu"
buttom:""
top:""
relu_param{
negative_slope: [默认:0] #可选参数negative_slope,此参数使得x <0时,ReLU层的输出为negative_slope * x,类似于PReLU的功能
}
}
- PReLU: 非线性层,使用PReLU作为激活函数,在负半轴的输出乘以一个系数,而这个系数是可学习的(你可以为其指定学习率),其中value是系数的初始值,channel_shared指定是否在各个通道间共享这个系数。
prelu_param {
filler: {
value: 0.33 #: 默认为0.25
}
channel_shared: false
}
损失层
SigmoidCrossEntropyLoss:S形交叉熵损失,用于目标概率分布和多标签多分类任务,各概率相互独立
layer{
name:"loss"
type:" SigmoidCrossEntropyLoss"
bottom:"loss3/classifier"
bottom:"label"
top:"loss"
}
EuclideanLoss:欧式距离损失,适用于实数值回归问题
layer{
name:"loss"
type:" EuclideanLoss "
bottom:"loss3/classifiersigmoid"
bottom:"label"
top:"loss"
}
softmax 计算lose
layer{
name:"loss"
type:"SoftmaxWithLoss"
bottom:"ip"
bottom:"label"
top:"loss"
}
准确率层
softmax 输出似然值,准确率
layer{
name:"pro"
type:"Softmax"
bottom:"ip"
top:"pro"
}
Dropout层 防止过拟合,杀死一些神经元
防止模型过拟合;训练模型时,随机让网络某些隐含层节点的权重不工作
layer{
name:"drop7"
bottom:""
top:""
dropout_param{
dropout_ratio:0.5 # 杀死50%的神经元
}
}
reshape层,对图像进行reshape
layer{
name:"reshape"
type:"Reshape"
bottom:"imput"
top:"output"
reshape_param{
dim:0 #表示不变
dim:2
dim:3
dim:-1 # 自己推断
}
}
2.3 solver.prototxt配置文件说明
net: "/home/tas/code/learn/train.prototxt" #配置文件的路径
test_iter: 100 # 测试batch_size*test_iter个样本,尽量一次测试全部测试样本
test_interval: 500 #每迭代500次进行一次测试
# 基础学习率,刚开始尽可能的低。
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer to being done
stepsize: 20000
display: 100 # 每100次打印结果
max_iter: 100000 #训练的最大迭代次数
momentum: 0.9 # 动量,灵感来自于牛顿第一定律,基本思路是为寻优加入了“惯性”的影响,这样一来,当误差曲面中存在平坦区的时候,SGD可以更快的速度学习。
weight_decay: 0.0005 #权衰量
snapshot: 10000 #迭代snapshot次,打印一次快照,即保存一次*.caffemodel,*.solverstate
snapshot_prefix: "/home/tas/code/learn/model/" # 保存model的路径
solver_mode: GPU # 使用GPU或者cpu训练
lr_policy:
“fixed”:固定学习速率,始终等于base_lr
“step”:步进衰减,base_lr*gamma^(floor(iter/stepsize))
“exp”:指数衰减,base_lr*gamma^(iter)
“inv”:倒数衰减,base_lr*(1+gamma*iter)^(-power)
“multistep”:多步衰减,与步进衰减类似,允许非均匀步进值(stepvalue)
“ploy”:多项式衰减,在max_iter时达到0,base_lr*(1-iter/max_iter)^(power)
“sigmoid”:S形衰减,base_lr*(1/(1+exp^(-gamma*(iter-stepsize))))