为了熟悉一下caffe的网络结构的配置、训练和测试采用mnist来进行学习。
mnist的训练网络也是caffe自带的一个example,只是需要自己下载mnist的数据。具体步骤如下:
(1)安装好caffe,具体过程可以参考其他教程。
(2)准备数据
进入caffe的根目录,大部分的模型网络结构、配置文件等都是caffe自带的,在exmamples/mnist下,一部分在data/mnist下。
运行:
cd $CAFFE_ROOT#切换到caffe的根目录
./data/mnist/get_mnist.sh#下载数据
./examples/mnist/create_mnist.sh#转换为lmdb格式
然后就下载好mnist数据了。实际操作我是将之前下好的数据放到mnist文件夹下,直接进行lmdb格式转换的。
(3)训练
新建或找到lenet网络结构文件:$CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt
其中的source:也即lmdb格式数据的路径,需要按照实际来修改
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 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
}
param {
lr_mult: 2
}
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
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "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"
}
新建或找到lenet的训练配置文件:$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt
其中的网络模型net:路径,和网络权重snapshot_prefix:需要修改
# 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.
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
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU
然后新建或找到train_lenet.sh,其中的内容:
#!/usr/bin/env sh
set -e
./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt $@
并进行训练:
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
待训练好后,新建或找到test_lenet.sh,其中的内容:
#!/usr/bin/env sh
set -e
./build/tools/caffe.bin test \
--model=examples/mnist/lenet_train_test.prototxt \
--weights=examples/mnist/weights/lenet_iter_5000.caffemodel \
--iterations=100
进行测试:
./examples/mnist/test_lenet.sh
以上都是对mnist数据集中的数据进行训练和测试,只能看到一些结果,并未看到其中的过程,因此下面采用图片进行测试。
(4) 测试数字图片
准备配置文件deploy.prototxt:
将lenet_train_test.prototxt的头、尾部进行修改,得到配置文件deploy.prototxt:
Lenet_train_test头部 :
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 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
}
}
改为Deploy头部 :
name:"Lenet"
layer {
name: "data"
type: "Input"
top: "data"
input_param {
shape: {
dim:1 #batch_size
dim:1 # rgb 3,gray 1
dim:28
dim:28
}
}
}
Lenet_train_test的尾部
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"
}
改为Deploy尾部
layer {
name: "prob"
type: "Softmax"
bottom: "ip2"
top: "prob"
}
去掉了label层,因为测试时不需要实际的类别。
得到完整的deploy.prototxt如下:
name:"Lenet"
layer {
name: "data"
type: "Input"
top: "data"
input_param {
shape: {
dim:1 #batch_size
dim:1 # rgb 3,gray 1
dim:28
dim:28
}
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
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
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "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: "prob"
type: "Softmax"
bottom: "ip2"
#bottom: "label"
top: "prob"
}
测试图片如下,背景为黑色,
新建测试函数mnist_detect.py:
#encoding=utf8
import sys
import numpy as np
import cv2
sys.path.insert(0,'/$caffe-root/python')
import caffe
MEAN = 128
SCALE = 0.00390624 # 1/256
#imgPath = sys.argv[1]
imgPath = '/$caffe-root/examples/mnist_2/test/bmp/6.jpg' #测试图片路径
caffe.set_mode_gpu()
caffe.set_device(0)
net = caffe.Net('/$caffe-root/examples/mnist_2/deploy.prototxt','/$caffe-root/examples/mnist_2/weights/lenet_iter_5000.caffemodel',caffe.TEST) #配置文件和权重文件路径
net.blobs['data'].reshape(1,1,28,28)
img0 = cv2.imread(imgPath,cv2.IMREAD_GRAYSCALE)
img1 = cv2.resize(img0,(28,28)) #图片缩放到28×28
image = img1.astype(np.float) - MEAN
print(image.shape)
image *= SCALE
#cv2.imwrite('rewrite.jpg',image)#image/SCALE+MEAN)
net.blobs['data'].data[...]=image
output = net.forward()
#print(output)
pred_label = np.argmax(output['prob'][0]) #预测结果
print('\nPredicted digit for {} is {}'.format(imgPath,pred_label))
参考
windows下使用caffe识别mnist图片,csdn:wuzebiao2016
Caffe-mnist别手写数字,cnblog:北海盗
关于测试自己的单张图片所需要的lenet.prototxt(deploy)文件,csdn:kele_imon
caffe中mnist中 lenet_train_test.prototxt和lenet.prototxt(deploy文件)区别,csdn,redfivehit
等等
后续还要再做一下mnist数据解析的工作,把其中的图片和识别结果一个个对比,直观的看一看识别结果,再尝试一下如何提高测试其他手写数字图片的识别率的问题。