【Caffe实战:训练和测试自己的图片】
1.准备数据
这个共有500张图片,分为大巴车、恐龙、大象、鲜花和马五个类,每个类100张。编号分别以3,4,5,6,7开头,各为一类。从其中每类选出20张作为测试,其余80张作为训练。因此最终训练图片400张,测试图片100张,共5类。
2.转换为leveldb格式
由于这个数据集的图片量比较大,所以我们选择编写python代码,批量生成train.txt和test.txt清单文件。
python的项目结构如下图所示:
其中,test和trian文件夹下存放的是若干图片,而test.txt和train.txt是程序自动生成的清单文件。
代码实现(train):
#coding=utf-8
import os
txtName="train.txt"
f=file(txtName,"a+")
def file_name(file_dir):
for root,dirs,files in os.walk(file_dir):
for file in files:
new_context=file+" "+str((int)(file[0])-3)+"\n"
f.write(new_context)
file_name('train')
代码实现(test):
#coding=utf-8
import os
txtName="test.txt"
f=file(txtName,"a+")
def file_name(file_dir):
for root,dirs,files in os.walk(file_dir):
for file in files:
new_context=file+" "+str((int)(file[0])-3)+"\n"
f.write(new_context)
file_name('test')
请注意,标注的类别编号label一定要从0开始,否则测试时的accuracy将会一直为0.2 ,即所有的类别分类错误。原理请看这篇博文:http://blog.csdn.net/u014381600/article/details/54319030
然后我们在caffe-master/data文件目录下新建一个re文件夹,将test文件夹、train文件夹、test.txt清单文件、trian.txt清单文件移动到该re文件夹下,如下图所示:
接下来,编写批处理文件,将图片转换为leveldb格式,其中每个参数解释可以参考我的上一篇文章,这里只给出实现代码:
首先是训练集:
.\Build\x64\Release\convert_imageset.exe -backend=leveldb -resize_height=256 -resize_width=256 data\re\trian\ data\re\train.txt examples\myfile\img_train_leveldb
pause
接下来是测试集:
.\Build\x64\Release\convert_imageset.exe -backend=leveldb -resize_height=256 -resize_width=256 data\re\test\ data\re\test.txt examples\myfile\img_test_leveldb
pause
接下来,将会在examples/myfile/的目录下生成相应的leveldb文件,如下图所示:
3.计算均值并保存
图片减去均值再训练,会提过训练速度和精度,因此,一般都会有这个操作。具体参数解释,请参考我之前的文章“Caffe从入门到精通05”,这里只是实现代码:
.\Build\x64\Release\compute_image_mean.exe -backend=leveldb examples\myfile\img_train_leveldb examples\myfile\mean.binaryproto
pause
运行成功后,会在examples\myfile\下面生成一个mean.binaryproto的均值文件。
4.创建模型并编写配置文件
模型就用caffe自带的caffenet模型,位置在models/bvlc_reference_caffenet/文件夹下,需要将两个配置文件solver.prototxt和train_val.prototxt 复制到我们的exmaples/myfile/文件夹下,如下图所示:
修改其中的solver.prototxt
net: "examples/myfile/train_val.prototxt"
test_iter: 10
test_interval: 100
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 1000
display: 20
max_iter: 500
momentum: 0.9
weight_decay: 0.005
solver_mode: GPU
我们知道,测试集一共有100个测试数据,batch_size为10,因此test_iter设置为10,就能将所有的测试样本全部覆盖了。
在训练过程中,调整学习率,逐渐变小。采用的策略是“step”,动态调整学习率,返回值为base_lr * gamma ^ (floor(iter / stepsize)),其中,floor()函数为下取整函数,iter为当前迭代次数。
修改其中的train_val.protxt
name: "CaffeNet"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mirror: true
crop_size: 227
mean_file: "examples/myfile/mean.binaryproto"
}
data_param {
source: "examples/myfile/img_train_leveldb"
batch_size: 64
backend: LEVELDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
mirror: false
crop_size: 227
mean_file: "examples/myfile/mean.binaryproto"
}
data_param {
source: "examples/myfile/img_test_leveldb"
batch_size: 10
backend: LEVELDB
}
}
我们需要修改两个阶段的data层,再将“fc8”的num_output值改为5,因为这个图片集只有5类5. 训练和测试
编写批处理文件,运行即可:
.\Build\x64\Release\caffe.exe train -solver=examples\myfile\solver.prototxt
pause
最终结果如下图所示:
迭代500次后,测试准确率达到了0.96.
6.评估与分析
1.出现loss=1.#QNAN,说明loss已经不收敛,应该讲base_lr减小一个数量级
2.若train loss低,test loss高,说明出现了过拟合。
3.根据数据量与网络模型,适当选择batch_size。这点很重要!
我尝试了多种batch_size的情况:当把batch_size设置为10的时候,loss开始震荡,无法收敛,且test accuracy一直保持0.2
当把batch_size设置为256的时候,loss虽然开始下降,但是训练非常缓慢。
当把batch_size设置为64的,在性能与效果上达到了一个比较好的结果。
——实战经验:
batch的size设置的太小,会导致在复杂的模型下,loss函数震荡而无法收敛!所以设置batch的原则是:应该在合理的范围内,增大batch_size!在一定范围内,一般来说,batch_size越大,其确定的下降方向越准,引起训练震荡越小!