官網(wǎng)提供了大量案例。一般把數(shù)據(jù)源放在 $CAFFE_ROOT/data 文件夾下面呀忧。處理后的數(shù)據(jù)和模型文件等放在 $CAFFE_ROOT/examples文件夾下涯捻。($CAFFE_ROOT 表示你電腦上的caffe代碼路徑吴叶。)
因此LeNet涉及兩個(gè)文件夾 $CAFFE_ROOT/data 和 $CAFFE_ROOT/examples :
一,準(zhǔn)備數(shù)據(jù)
MNIST數(shù)據(jù): $CAFFE_ROOT/data/mnist/ 存放數(shù)據(jù)源烟勋,但是你會(huì)發(fā)現(xiàn) 只有一個(gè) get_mnist.sh 腳本,運(yùn)行它就可以幫我們下載數(shù)據(jù)筐付。
cd $CAFFE_ROOT ? 安裝的caffe路徑
./data/mnist/get_mnist.sh #得到MNIST數(shù)據(jù)
轉(zhuǎn)換格式為 LMDB(上篇文章已經(jīng)提到過caffe支持的幾種數(shù)據(jù)格式)
cd $CAFFE_ROOT
./examples/mnist/create_mnist.sh #官方給出的專門轉(zhuǎn)換MNIST數(shù)據(jù)格式的腳本
得到下面兩個(gè)文件
二卵惦,配置網(wǎng)絡(luò)結(jié)構(gòu)
官網(wǎng)提供了定義好的網(wǎng)絡(luò)文件 $CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt 其內(nèi)容如下:
name: "LeNet"
layer {
name: "mnist"
type: "Data" #數(shù)據(jù)層
top: "data"
top: "label"
include {
phase: TRAIN #訓(xùn)練時(shí)才加載
}
transform_param {
scale: 0.00390625 #每個(gè)像素乘以改值做歸一化(1/255 = 0.00390625)
}
data_param {
source: "examples/mnist/mnist_train_lmdb" #前面生成的訓(xùn)練數(shù)據(jù)集
batch_size: 64 # 每一批訓(xùn)練集大小
backend: LMDB #數(shù)據(jù)格式
}
}
layer {
name: "mnist"
type: "Data" #數(shù)據(jù)層
top: "data"
top: "label"
include {
phase: TEST #測試時(shí)才加載
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb" #前面生成的測試數(shù)據(jù)集
batch_size: 100
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution" #卷積層
bottom: "data"
top: "conv1"
param {
lr_mult: 1 #weights學(xué)習(xí)率
}
param {
lr_mult: 2 #bias學(xué)習(xí)率
}
convolution_param {
num_output: 20 #輸出多少個(gè)特征圖(對應(yīng)卷積核數(shù)量)
kernel_size: 5 #卷積核大小
stride: 1 #步長
weight_filler {
type: "xavier" #權(quán)重初始化算法
}
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學(xué)習(xí)率
}
param {
lr_mult: 2 #bias學(xué)習(xí)率
}
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繪圖工具繪制出網(wǎng)絡(luò)圖:
三,配置網(wǎng)絡(luò)求解文件
官網(wǎng)給出了一個(gè)求解文件:$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. 設(shè)置每500次測試一下網(wǎng)絡(luò) 精度 損失
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? 設(shè)置每100次迭代訓(xùn)練顯示當(dāng)前狀態(tài) lr loss
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results 中間結(jié)果快照每5000次保存一次
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU
四瓦戚,訓(xùn)練
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
其內(nèi)容如下:
#!/usr/bin/env sh
set -e
./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt $@
可見只是調(diào)用前一篇文章 (caffe入門時(shí)間-簡介) 已經(jīng)提到過的 命令行接口沮尿。
然后得到一堆的輸出信息:
#solver文件設(shè)置每100次迭代訓(xùn)練顯示當(dāng)前狀態(tài) lr loss
I1203 solver.cpp:204] Iteration 100, lr = 0.00992565? #學(xué)習(xí)率
I1203 solver.cpp:66] Iteration 100, loss = 0.26044 #損失
...
#solver文件設(shè)置每500次測試一下網(wǎng)絡(luò) 精度 損失
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9785 #精度
I1203 solver.cpp:111] Test score #1: 0.0606671 #損失
訓(xùn)練結(jié)束后,輸出信息可以看到最終的精度和損失伤极。 在 $CAFFE_ROOT/examples/mnist 文件夾下可以看到 如下文件蛹找。 迭代5000次的中間狀態(tài)快照 (.solverstate文件姨伤,可用于恢復(fù)網(wǎng)絡(luò)訓(xùn)練)和模型 (.caffemodel文件,可用于下一步測試)庸疾,迭代10000次的中間狀態(tài)快照和模型
備注:由于我們在solver中設(shè)置了每500做一下測試乍楚。所以實(shí)際上上面 ./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt 的過程包含了訓(xùn)練和間隔測試。這樣做有助于我們對網(wǎng)絡(luò)訓(xùn)練的中間過程有直觀感受届慈。
五徒溪,測試
# 參數(shù)包括:網(wǎng)絡(luò)結(jié)構(gòu)模型文件(.prototxt 注意不是求解文件solover) 訓(xùn)練好的模型參數(shù)(.caffemodel) 迭代測試100次(前面訓(xùn)練和間隔測試時(shí)是在solver文件中定義的 此處則用命令行寫明)
cd $CAFFE_ROOT
build/tools/caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel? -iterations 100
測試可以達(dá)到 0.9948的精度,0.0182697的損失率金顿。
?實(shí)戰(zhàn)二: 用python接口調(diào)用訓(xùn)練號的模型識別數(shù)字臊泌。
圖片:
#編寫python調(diào)用模型預(yù)測圖片是數(shù)字幾:
import os
import sys
import numpy as np
import matplotlib.pyplot as plt
caffe_root = '你的caffe路徑'
sys.path.insert(0, caffe_root + 'python') #把pycaffe所在路徑添加到環(huán)境變量
import caffe
#指定網(wǎng)絡(luò)結(jié)構(gòu) 與 lenet_train_test.prototxt不同
MODEL_FILE = '你的caffe路徑/examples/mnist/lenet.prototxt'
PRETRAINED = '你的caffe路徑/examples/mnist/lenet_iter_10000.caffemodel'
#圖片已經(jīng)處理成 lenet.prototxt的輸入要求(尺寸28x28)且已經(jīng)二值化為黑白色
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()
結(jié)果預(yù)測為數(shù)字 4:
相關(guān)代碼和圖片在https://github.com/andylei77/Learning-caffe/tree/master/Lenet-mnist
適用于本Linux (適用于一次執(zhí)行)
#編寫python調(diào)用模型預(yù)測圖片是數(shù)字幾:
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所在路徑添加到環(huán)境變量
import caffe
#指定網(wǎng)絡(luò)結(jié)構(gòu) 與 lenet_train_test.prototxt不同
MODEL_FILE = 'caffe/examples/mnist/lenet.prototxt'
PRETRAINED = 'caffe/examples/mnist/lenet_iter_10000.caffemodel'
#圖片已經(jīng)處理成 lenet.prototxt的輸入要求(尺寸28x28)且已經(jīng)二值化為黑白色
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()