使用caffe框架进行深度学习训练的流程如下:
1、数据预处理(建立数据库)
2、网络结构与模型训练的配置
3、训练与再训练
4、训练日志分析
5、预测检验与分析
6、性能测试
下面分别来分析各个流程的处理过程:
1、数据预处理(建立数据库)
训练数据与测试数据的预处理阶段,一般是 把待分析识别的图像进行简单的预处理,然后保存到数据库中。为什么要进行这一步而不是直接从图片读入呢?因为实际任务中的训练数据的数量非常大,从图像文件中读取数据并进行初始化效率非常低,所以很有必要把数据预先保存在数据库中来加快训练的节奏。
将图片下载到本地,通过脚本文件将图片转换成leveldb或lmdb格式,这两种数据库在存储数据和操纵上有所不同。
(1)数据组织方式不同,leveldb生成的文件比较多;lmdb的文件更紧凑,只有两个
(2)读取数据的接口不同
2、网络结构与模型训练的配置
caffe采用读入配置文件的方式进行训练,其配置文件一般由两部分组成:solver.prototxt和net.prototxt(有时有多个net.prototxt),分别对应caffe系统架构中两个十分关键的实体——求解器(Solver)和网络结构(Net)。
下面讲解一下相对简单的solver.prototxt文件:
#网络配置的位置
net: "examples/mnist/net.prototxt"
#要使用GPU进行训练
solver_mode: GPU
#本次训练共迭代5000次
max_iter: 5000
#测试每500轮跑一遍,一遍跑100个迭代
test_iter: 100
test_interval: 500
#每50次输出一些信息
display: 50
#基础的学习速率为0.01
base_lr: 0.01
lr_policy: "step"
gamma: 0.1
stepsize: 50000
#动量衰减率是0.9,正则项的权重是0.0005
momentum: 0.85
weight_decay: 0.0005
#每1000轮保存一下进度
snapshot: 1000
snapshot_prefix: "examples/mnist/net_train"
基本回答了以下几个问题:
(1)网络文件在哪
(2)用什么计算资源训练?CPU还是GPU?
(3)训练多久?训练和测试比例是如何安排的?什么时候输出一些东西?
(4)优化的学习速率怎么设定?动量和正则的设置
(5)要时刻记得存档,不然得从头来过。
net.prototxt文件说明
name: "LeNet" 网络名
layer {
name: "mnist" 本层名称
type: "Data" 层类型
top: "data" 下一层接口
top: "label" 下一层接口
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625 #1/256,预处理如减均值,尺寸变换,随机剪,镜像等
}
data_param {
source: "examples/mnist/mnist_train_lmdb" 训练数据位置
batch_size: 64 一次训练的样本数
backend: LMDB 读入的训练数据格式,默认leveldb
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100 一次测试使用100个数据
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution" 卷积层
bottom: "data" 上一层名“data”
top: "conv1" 下一层接口“conv1”
param {
lr_mult: 1 (weights的学习率与全局相同)
}
param {
lr_mult: 2 (biases的学习率是全局的2倍)
}
convolution_param {
num_output: 20 卷积核20个
kernel_size: 5 卷积核尺寸5×5
stride: 1 步长1
weight_filler {
type: "xavier" (随机的初始化权重和偏差)
}
bias_filler {
type: "constant" bias用0初始化
}
}
}
layer {
name: "pool1"
type: "Pooling" 池化层
bottom: "conv1" 上层“conv1”
top: "pool1" 下层接口“pool1”
pooling_param {
pool: MAX 池化函数用MAX
kernel_size: 2 池化核函数大小2×2
stride: 2 步长2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50 卷积核50个
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct" 全连接层
bottom: "pool2" 上层连接“pool2”
top: "ip1" “下层输出接口ip1”
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500 输出数量500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU" 激活函数
bottom: "ip1"
top: "ip1" (这个地方还是ip1,底层与顶层相同减少开支,下一层全连接层的输入也还是ip1)
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10 输出结果10个
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2" 上层连接ip2全连接层
bottom: "label" 上层连接label层
top: "accuracy" 输出接口为accuracy
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss" 损失函数
bottom: "ip2"
bottom: "label"
top: "loss"
}
caffe提供了一套接口,net.prototxt文件可通过写代码生成。
3、训练与再训练
准备好了数据,确定了训练相关的配置,就可以正式训练了。启动训练脚本train_lenent.sh,经过一段时间的训练,命令行产生了大量的日志训练过程也宣告结束,这时目录中多了如下目录:
net_train_iter_1000.caffemodel
net_train_iter_1000.solverstate
……
caffemodel文件中保存了caffe模型中的参数,solverstate文件中保存了训练过程中的一些中间结果。
再训练包含两种模式:
(1)断点训练,solverstate中存储了训练的历史信息,这些信息能够帮助模型继续训练;
(2)迁移学习,这个模式会在之前训练的基础上,对模型结构做一定的修改,然后应用到其他模型中,这种模式称为迁移学习。
4、训练日志分析
训练过程caffe产生了大量的日志,这些日志包含很多训练过程的信息,很值得分析。其中之一就是分析目标函数Loss的变化曲线,和测试环节的精确度。
正常的训练过程中,日志中只会显示每一组迭代后模型训练的整体信息,如果想了解更多信息就要将solver.prototxt中的调试信息打开。
5、预测检验与分析
模型完成训练后,要对它的训练表现做验证,看它在其他测试数据上的正确性。除此之外,还可以将每一层的中间结果可视化出来,进行分析。
6、性能测试
除了测试数据上的准确率,模型的运行时间也非常值得关心。
以上就是在caffe上训练数据的整个过程。
参考《深度学习轻松学》