这篇博客主要是对上篇博客提到的文件作一个详解。
1.MNIST数据集
下载下来的数据集被分成两部分:60000张图片的训练数据集和10000张图片的测试数据集。
每张图片包含28*28个像素,图片里的每个像素都是8位的,也就是说每一个像素值的强度介于0-255之间。
2.下载的原始数据集为二进制文件,需要转换为LEVELDB或LMDB
LMDB-闪电般的内存映射型数据库管理器,在caffe中的主要作用是进行数据管理,将各种类型的原始数据(比如JPEG图片,二进制数据)都统一转换为Key-Value存储,以便于Caffe的DataLayer获取这些数据,而LEVELDB是Google开发的一种数据存储方式,在Caffe早期的版本中用得比较多,现在LMDB用得更多。
所以,LMDB的作用是统一数据类型并加快读取速度。
3.修改网络模型描述文件caffe-windows\examples\mnist\lenet_train_test.prototxt
name: "LeNet" #网络层的名字
layer { #定义一个层
name: "mnist" #层的名字是mnist
type: "Data" #层的类型是"Data",表名数据来源于LMDB或LevelDB.另外其他数据来源还可能来自内存,HDF5,图片等。
top: "data" #输出data
top: "label" #输出label
include {
phase: TRAIN #该层只在TRAIN训练的时候有效
}
transform_param { #数据的预处理
scale: 0.00390625 #1/256,将输入的数据0-255转换到0-1,每个数都乘以0.00390625
}
data_param {
source: "E:/graduate_student/deep_learning/caffe/new_Win_caffe/document/1/caffe-windows/caffe-windows/examples/mnist/lmdb/train_lmdb" #数据来源
batch_size: 64 #每个批处理64张图片
backend: LMDB #数据格式LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST #该层指在TEST测试的时候有效
}
transform_param {
scale: 0.00390625
}
data_param {
source: "E:/graduate_student/deep_learning/caffe/new_Win_caffe/document/1/caffe-windows/caffe-windows/examples/mnist/lmdb/test_lmdb"
batch_size: 100 #每个批处理100张图片
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution" #层的类型是卷积层
bottom: "data" #输入data
top: "conv1" #输出conv1
param { #这个是权值的学习率
lr_mult: 1 #学习率系数,最终的学习率是这个学习率系统lr_mult乘以solver.prototxt里面的base_lr
}
param { #这个是偏执的学习率
lr_mult: 2 #学习率系数,最终的学习率是这个学习率系统lr_mult乘以solver.prototxt里面的base_lr
}
convolution_param {
num_output: 20 #卷积核的个数为20,或者表示输出特征平面的个数为20
kernel_size: 5 #卷积核的大小5*5。如果卷积核长和宽不等,则需要用kernel_h和kernel_w分别设置
stride: 1 #步长为1。也可以用stride_h和stride_w来设置
weight_filler { #权值初始化
type: "xavier" #使用xavier算法(正则化初始化),也可以设置为"gaussian"
}
bias_filler { #偏执初始化
type: "constant" #一般设置为“constant",取值为0
}
}
}
layer {
name: "pool1"
type: "Pooling" #层的类型是池化层
bottom: "conv1" #输入conv1
top: "pool1" #输出pooll
pooling_param {
pool: MAX #池化方法,常用的方法有MAX,AVE或STOCHASTIC
kernel_size: 2 #池化核的大小2*2,如果池化核长和宽不等,则需要用kernel_h和kernel_w分别设置
stride: 2 #池化的步长,也可以用stride_h核stride_w来设置
}
}
layer {
name: "conv2"
type: "Convolution" #第2个卷积层
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50 #卷积核的个数为50,或者表示输出特征平面的个数为50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling" #第2个池化层
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct" #层的类型是全连接层
bottom: "pool2"
top: "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" #层的类型’ReLU',激活函数,可以解决梯度消失或梯度爆炸的问题
bottom: "ip1" #输入ip1
top: "ip1" #输出经过激活函数处理过的ip1
}
layer {
name: "ip2"
type: "InnerProduct" #第2个全连接层
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10 #10个输出,代表10个分类
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy" #层的类型是"Accuracy",用来判断准确率
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss" #层的类型是"SoftmaxWithLoss",输出误差值loss
bottom: "ip2"
bottom: "label"
top: "loss"
}
下图是激活函数:
4.修改超参数文件caffe-windows\examples\mnist\lenet_solver.prototxt
#网络模型描述文件
#也可以用train_net和test_net来对训练模型和测试模型分别设定,这里用同一个模型
net: "E:/graduate_student/deep_learning/caffe/new_Win_caffe/document/1/caffe-windows/caffe-windows/examples/mnist/lenet_train_test.prototxt"
#这个参数要跟test_layer结合起来考虑,在test_layer中一个batch是100,而总共的测试图片是10000张
#所以这个参数就是10000/100=100,我们测试100次,每次测试100张图片
test_iter: 100
# 每训练500次进行一次测试
test_interval: 500
# 学习率
base_lr: 0.01
#动力
momentum: 0.9
#type:SGD #优化算法的选择。这一行可以省略,因为默认值就是SGD,Caffe中一共有6中优化算法可以选择
#Stochastic Gradient Descent (type: "SGD"), 在Caffe中SGD其实应该是Momentum
#AdaDelta (type: "AdaDelta"),
#Adaptive Gradient (type: "AdaGrad"),
#Adam (type: "Adam"),
#Nesterov’s Accelerated Gradient (type: "Nesterov")
#RMSprop (type: "RMSProp")
#权重衰减项,其实也就是正则化项,作用是防止过拟合
weight_decay: 0.0005
# 学习率调整策略
#如果设置为inv,还需要设置一个power,返回base_lr * (1 + gamma * iter) ^ (- power),其中iter表示当前的迭代次数
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# 每训练100次屏幕上显示一次,如果设置为0则不显示
display: 100
# 最大迭代次数
max_iter: 10000
# 快照。可以把训练的model和solver的状态进行保存。每迭代5000次保存一次,如果设置为0则不保存
snapshot: 5000
snapshot_prefix: "E:/graduate_student/deep_learning/caffe/new_Win_caffe/document/1/caffe-windows/caffe-windows/examples/mnist/modle/"
# 选择运行模式
solver_mode: CPU
5.开始训练模型
6.等待模型训练好,准备要测试的图片
7.生成均值文件
图片减去均值后,再进行训练和测试,会提高速度和精度。因此,一般在各种图像识别的模型中都会有这个操作。实际上就是计算所有训练样本的平均值,计算出来后,保存为一个均值文件,在以后的测试中,就可以直接使用这个均值来相减,而不需要对测试图片重新计算。
8.准备标签
9.测试分类效果