参考博客:caffe学习系列:训练自己的图片集(超详细教程)
按照这位dalao的博客走一遍,基本上可以解决caffe单标签训练的问题。我这里主要记录一下这个过程中需要注意的地方。
caffe为单标签分类问题提供了很好的支持,很多操作都可以通过caffe提供的可执行文件来完成,这些可执行文件保存在caffe编译后生成的build/tools文件夹中。
一、准备训练数据
这一步需要我们借助python等工具将原始格式的数据集整理成caffe能够接受的格式,并在这个过程中对数据进行预处理。一般来说,数据预处理都会包括以下几个环节:
① 从数据集的标签文件中获取图片的路径及标签信息
② 统计并平衡各种分类样本的数量(有些数据集中各种分类样本的数量不平衡,这时可以通过程序进行手动调整,使前景和背景、各种分类样本之间的数量比达到平衡)
③ 将样本划分为训练(training)、验证(validation)和测试(test)三个部分(也可以不用test,但最好有val,以防止过拟合)
一般来说,val数据集用于在训练过程中评估训练效果,判断是否发生过拟合,还能用于帮助程序决定该在何时调整学习率,何时结束训练;test数据集用于在训练结束后测试训练结果。所以,test数据集是不会参与训练的,caffe中的TEST过程指的是通常所说的val过程。
总之,最后,我们需要得到一个这样的数据集,它应当包含图片和标签文件(train.txt,val.txt,test.txt)两部分,其中,标签文件需要具备如下的结构:
(这是从CelebA数据集中提取出的关于人物是否佩戴眼镜的标签文件,其中1表示佩戴眼镜,0表示没有佩戴眼镜)
这里的路径指图片相对于数据集文件夹的路径(后面会有机会指定这个文件夹的路径),
而标签是从0开始的整数:0,1,2,3,4……,注意必须是从0开始,否则网络会不能将标签对应到正确的输出。
然后,把标签文件放到工程文件夹下备用(以后的文件都放到这个文件夹里)
二、生成lmdb数据集
作为caffe默认的数据集格式,lmdb具有体积小、速度快以及相比于hdf5,不需要将全部图片读入内存等优点,
caffe提供了用于直接从源数据集生成lmdb数据集的可执行文件,把可执行文件的调用过程封装一下,在工程文件夹下新建一个create_lmdb.sh脚本并执行(注意修改里面的路径和参数,如果不确定该用绝对路径还是相对路径,最好用绝对路径,这样可以保证你的脚本在任何目录下都能够执行,后面一样):
#!/usr/bin/env sh
CAFFE_PATH=... # caffe路径
IMG_PATH=... # 数据集文件夹
LMDB_PATH=... # 工程文件夹
echo "Create train lmdb.."
rm -rf $LMDB_PATH/img_train_lmdb
$CAFFE_PATH/build/tools/convert_imageset \
--shuffle \
--resize_height=227 \ # 图片尺寸(我这里要使用caffenet,所以要先将图片resize到227*227)
--resize_width=227 \
$IMG_PATH \
$LMDB_PATH/train.txt \
$LMDB_PATH/img_train_lmdb
echo "Create test lmdb.."
rm -rf $LMDB_PATH/img_test_lmdb
$CAFFE_PATH/build/tools/convert_imageset \
--shuffle \
--resize_width=227 \
--resize_height=227 \
$IMG_PATH \
$LMDB_PATH/val.txt \
$LMDB_PATH/img_test_lmdb
echo "Create meanfile.."
rm -rf $LMDB_PATH/mean.binaryproto
$CAFFE_PATH/build/tools/compute_image_mean \
$LMDB_PATH/img_train_lmdb \
$LMDB_PATH/mean.binaryproto
echo "All Done.."
emmmmmm...我把生成均值文件的指令也加了进去,后面再说。(如果不想生成均值文件可以删掉最后几行)
如果程序顺利执行的话,就能在工程文件夹下生成img_train_lmdb和img_test_lmdb两个lmdb数据集了。
三、生成均值文件
作为数据规范化的一种方法,均值规整并不是必须使用的方法,但最好使用一种方法,即使不用均值,也可以直接做归一化(image - 127.5) / 127.5,那样就不需要生成均值文件了。如果需要均值文件的话,可以使用caffe自带的compute_image_mean工具,调用方法见上面的脚本最后几行。
之后,会在工程文件夹下生成均值文件mean.binaryproto。
四、修改train_val.prototxt
如果要使用caffe自带的caffenet,可以在caffe目录下的models/bvlc_reference_caffenet文件夹下找到它的网络文件:train_val.prototxt和solver.prototxt,将这两个文件复制到工程文件夹下,并修改该文件,重点关注Data层(输入层)、Loss层和Accuaracy层:
1. Data层,包括训练和测试两个环节(里面的路径并不是一定用绝对路径,但是这样更保险一点,原因同上)
(事实上,prototxt里的相对路径指的是执行训练文件build/tools/caffe时终端所在路径,如果你能确保在工程文件夹下开始训练,那么这里的路径就可以只填一个文件名)
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN # 表示该层仅在训练时读取
}
transform_param {
mirror: true # 数据增强:镜像
crop_size: 227 # 数据增强:如果图片尺寸大于该尺寸,就对图片做随机裁剪
mean_file: "/home/.../mean.binaryproto" # 改成绝对路径
}
data_param {
source: "/home/.../img_train_lmdb"
batch_size: 64
backend: LMDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
mirror: false
crop_size: 227
mean_file: "/home/.../mean.binaryproto"
}
data_param {
source: "/home/.../img_test_lmdb"
batch_size: 100 # 训练和测试的batch_size不一定相等
backend: LMDB
}
}
2. Loss层
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "fc8"
bottom: "label"
top: "loss"
}
3. Accuaracy层
layer {
name: "accuracy"
type: "Accuracy"
bottom: "fc8"
bottom: "label"
top: "accuracy"
include {
phase: TEST # 这里设置为TEST,表示训练过程中不会测试准确率,当然也可以要求程序在训练过程中也测试准确率
}
}
五、修改solver.prototxt
这里定义了学习率、学习率调整方案、迭代次数等超参数,solver.prototxt的一个样例如下所示(这里用了相对路径,原因见上面):
net: "train_val.prototxt"
test_iter: 2 # 每次测试使用test_iter个batch
test_interval: 100 # 每test_interval个训练batch进行一次测试
base_lr: 0.0005 # 初始学习率和学习率调整规则
lr_policy: "step"
gamma: 0.8
stepsize: 10000
max_iter: 300000
momentum: 0.9
weight_decay: 0.0005
display: 100 # 每display个batch显示一次训练loss
average_loss: 100 # 每次显示的训练loss等于前average_loss个batch的平均值
snapshot: 5000 # 每snapshot个batch保存一次caffemodel和solverstate
snapshot_prefix: "models/" # 模型保存路径
solver_mode: GPU
按照你的需求修改这些参数。
六、训练
至此为止,在工程文件夹下应该已经有了以下文件:
- models/:空文件夹
- train.txt,val.txt,(test.txt):这几个文件训练过程用不到
- img_train_lmdb,img_test_lmdb
- mean.binaryproto
- train_val.prototxt
- solver.prototxt
这样就可以开始训练了,再新建一个sh脚本用于调用caffe可执行文件,命名为train.sh:
#!/usr/bin/env sh
set -e
/home/.../caffe/build/tools/caffe train \
-solver solver.prototxt
修改其中的路径为你的caffe路径,然后执行该脚本,不出意外的话,就可以开始训练了。