centos7 caffe入门与实践-LeNet MNIST
官网提供了大量案例。一般把数据源放在 $CAFFE_ROOT/data 文件夹下面。处理后的数据和模型文件等放在 $CAFFE_ROOT/examples文件夹下。($CAFFE_ROOT 表示你电脑上的caffe代码路径。)
因此LeNet涉及两个文件夹 $CAFFE_ROOT/data 和 $CAFFE_ROOT/examples :
一,准备数据
MNIST数据: $CAFFE_ROOT/data/mnist/ 存放数据源,但是你会发现 只有一个 get_mnist.sh 脚本,运行它就可以帮我们下载数据。
cd $CAFFE_ROOT 安装的caffe路径
./data/mnist/get_mnist.sh #得到MNIST数据
转换格式为 LMDB(上篇文章已经提到过caffe支持的几种数据格式)
cd $CAFFE_ROOT
./examples/mnist/create_mnist.sh #官方给出的专门转换MNIST数据格式的脚本
得到下面两个文件
二,配置网络结构
官网提供了定义好的网络文件 $CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt 其内容如下:
name: "LeNet"
layer {
name: "mnist"
type: "Data" #数据层
top: "data"
top: "label"
include {
phase: TRAIN #训练时才加载
}
transform_param {
scale: 0.00390625 #每个像素乘以改值做归一化(1/255 = 0.00390625)
}
data_param {
source: "examples/mnist/mnist_train_lmdb" #前面生成的训练数据集
batch_size: 64 # 每一批训练集大小
backend: LMDB #数据格式
}
}
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
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution" #卷积层
bottom: "data"
top: "conv1"
param {
lr_mult: 1 #weights学习率
}
param {
lr_mult: 2 #bias学习率
}
convolution_param {
num_output: 20 #输出多少个特征图(对应卷积核数量)
kernel_size: 5 #卷积核大小
stride: 1 #步长
weight_filler {
type: "xavier" #权重初始化算法
}
bias_filler {
type: "constant" #基值初始化算法
}
}
}
layer {
name: "pool1"
type: "Pooling" #池化层
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX #池化方法
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 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"
top: "ip1"
param {
lr_mult: 1 #weights学习率
}
param {
lr_mult: 2 #bias学习率
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU" #relu层
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy" #输出精度
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss" #输出损失
bottom: "ip2"
bottom: "label"
top: "loss"
}
可以用 官方自带的python绘图工具绘制出网络图:
三,配置网络求解文件
官网给出了一个求解文件:$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt:
# The train/test net 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.
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
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations 设置每100次迭代训练显示当前状态 lr loss
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results 中间结果快照每5000次保存一次
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU
四,训练
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
其内容如下:
#!/usr/bin/env sh
set -e
./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt $@
可见只是调用前一篇文章 (caffe入门时间-简介) 已经提到过的 命令行接口。
然后得到一堆的输出信息:
#solver文件设置每100次迭代训练显示当前状态 lr loss
I1203 solver.cpp:204] Iteration 100, lr = 0.00992565 #学习率
I1203 solver.cpp:66] Iteration 100, loss = 0.26044 #损失
...
#solver文件设置每500次测试一下网络 精度 损失
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9785 #精度
I1203 solver.cpp:111] Test score #1: 0.0606671 #损失
训练结束后,输出信息可以看到最终的精度和损失。 在 $CAFFE_ROOT/examples/mnist 文件夹下可以看到 如下文件。 迭代5000次的中间状态快照 (.solverstate文件,可用于恢复网络训练)和模型 (.caffemodel文件,可用于下一步测试),迭代10000次的中间状态快照和模型
备注:由于我们在solver中设置了每500做一下测试。所以实际上上面 ./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt 的过程包含了训练和间隔测试。这样做有助于我们对网络训练的中间过程有直观感受。
五,测试
# 参数包括:网络结构模型文件(.prototxt 注意不是求解文件solover) 训练好的模型参数(.caffemodel) 迭代测试100次(前面训练和间隔测试时是在solver文件中定义的 此处则用命令行写明)
cd $CAFFE_ROOT
build/tools/caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -iterations 100
测试可以达到 0.9948的精度,0.0182697的损失率。
实战二: 用python接口调用训练号的模型识别数字。
图片:
#编写python调用模型预测图片是数字几:
import os
import sys
import numpy as np
import matplotlib.pyplot as plt
caffe_root = '你的caffe路径'
sys.path.insert(0, caffe_root + 'python') #把pycaffe所在路径添加到环境变量
import caffe
#指定网络结构 与 lenet_train_test.prototxt不同
MODEL_FILE = '你的caffe路径/examples/mnist/lenet.prototxt'
PRETRAINED = '你的caffe路径/examples/mnist/lenet_iter_10000.caffemodel'
#图片已经处理成 lenet.prototxt的输入要求(尺寸28x28)且已经二值化为黑白色
IMAGE_FILE = '你的caffe路径/examples/images/test4.bmp'
input_image = caffe.io.load_image(IMAGE_FILE, color=False)
net = caffe.Classifier(MODEL_FILE, PRETRAINED)
prediction = net.predict([input_image], oversample = False)
caffe.set_mode_cpu()
print 'predicted class:', prediction[0].argmax()
结果预测为数字 4:
相关代码和图片在https://github.com/andylei77/Learning-caffe/tree/master/Lenet-mnist
适用于本Linux (适用于一次执行)
#编写python调用模型预测图片是数字几:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import os
import numpy as np
import matplotlib.pyplot as plt
caffe_root = 'caffe'
sys.path.insert(0, caffe_root + 'python') #把pycaffe所在路径添加到环境变量
import caffe
#指定网络结构 与 lenet_train_test.prototxt不同
MODEL_FILE = 'caffe/examples/mnist/lenet.prototxt'
PRETRAINED = 'caffe/examples/mnist/lenet_iter_10000.caffemodel'
#图片已经处理成 lenet.prototxt的输入要求(尺寸28x28)且已经二值化为黑白色
IMAGE_FILE = 'caffe/examples/images/test4.bmp'
input_image = caffe.io.load_image(IMAGE_FILE, color=False)
net = caffe.Classifier(MODEL_FILE, PRETRAINED)
prediction = net.predict([input_image], oversample = False)
caffe.set_mode_cpu()
print 'predicted class:', prediction[0].argmax()