此篇依然是记录跟随caffe官网上的指导文件,主题为:微调(finetune)
http://caffe.berkeleyvision.org/gathered/examples/finetune_flickr_style.htm
上面网址里面有较为详尽的步骤,下为总结。
一、数据集的准备
1、准备图像文件和对应的txt文件
example里是通过命令在caffe根目录下运行
caffe % ./examples/finetune_flickr_style/assemble_data.py -h
caffe % python examples/finetune_flickr_style/assemble_data.py --workers=-1 --images=2000 --seed 831486
直接下载照片集(2000张),且一并下载了lable文件(train.txt和test.txt),都在caffe/data/flickr_style里面,存放目录可以在caffe/examples/finetune_flickr_style/assemble_data.py里面修改。
2、将txt文件转换成lmdb或leveldb
然而caffe更喜欢lmdb或leveldb格式,则需要将数据转换成lmdb格式使其更高效(train.txt->train.lmdb,test.txt->test.lmdb),可以使用caffe/tools提供的convert_imageset工具实现转换(./build/caffe/tools/convert_imageset -help查看用法)。参考这篇http://www.cnblogs.com/denny402/p/5082341.html,比如此处在caffe根目录下输入命令获得train_lmdb(注意路径):
./build/tools/convert_imageset \
--resize_height 227 --resize_width 227 --shuffle true \
home/yourname/caffe/data/flickr_style/images/ \
data/flickr_style/train.txt \
data/flickr_style/train_lmdb \
#第1行参数是可选参数
#第2行参数是图片集存放的绝对地址
#第3行参数是train.txt的图片标签文件
#第4行参数是要存放的lmdb文件的位置
#注意这里的图片标签文件与下载下来的不同,由相对位置图片名字+空格+标签号组成,不是绝对地址,
搜索图片的时候就是读取第2个参数图片集存放的绝对地址+第3个参数train.txt提供的相对地址,
比如 "1.jpg 0" 而不是 "/home/yourname/caffe/data/flickr_style/images/1.jpg 0"
#后面步骤修改数据层的参数时,将source改成相应的lmdb文件
那么怎样获得形如“1.jpg 0”的清单文件呢?写一个脚本文件sh,根据图片的命名贴上对应的标签:
# /usr/bin/env sh
DATA=data/xxxx/images
echo "Create train.txt..."
rm -rf data/xxxx/train.txt
find $DATA -name *category0.jpg | cut -d '/' -f3 | sed "s/$/ 0/">>data/xxxx/train.txt
find $DATA -name *category1.jpg | cut -d '/' -f3 | sed "s/$/ 1/">>data/xxxx/tmp1.txt
cat data/xxxx/tmp1.txt>>data/xxxx/train.txt
rm -rf data/xxxx/tmp1.txt
echo "Done.."
3、求取数据集的均值
然后,还有个很关键的步骤:准备均值文件,官网是在data/ilsvrc12里运行的get_ilsvrc_aux.sh,得到了imagenet_mean.binaryproto的针对imagenet的均值文件。
怎样获得自己数据集的均值文件<还需要学习>,目前看到caffe/tools里面有个compute_image_mean,但查看help文件可知它只支持leveldb和lmdb格式,不支持txt的标签。compute_image_mean用法:
./build/tools/compute_image_mean -backend lmdb xx/train_lmdb xxx/mean.binaryproto
#第1个参数指明文件类型lmdb还是leveldb
#第2个参数指明要求取均值的文件路径
#第3个参数指明要生成的binaryproto文件的路径
划重点,要是在自己的数据集上做finetune需要将照片放在一个文件夹里面(没有要求),重要的是train.txt和test.txt的编写(此处是指,直接作为用于训练的最终文件 而非 作为转换为lmdb格式的临时文件),打开下载的文件可以看出它的编写方式:图片的绝对路径下的具体名字+空格+从0开始的连续数字的标签。然后重要的一步是:准备均值文件,要减去自己数据的均值和除以自己的标准差,不能直接照搬imagenet的均值!
二、下载模型并修改文件
运行下载模型参数文件
./scripts/download_model_binary.py models/bvlc_reference_caffenet
会在 caffe/models/bvlc_reference_caffenet里面得到一系列文件,bvlc_reference_caffenet.caffemodel里面记录了训练好的权重(weights),我们需要导入到网络的配置文件里面。在model_zool里面有非常多的针对不同环境的caffe模型(目录不全):
https://github.com/BVLC/caffe/wiki/Model-Zoo#learning-structured-sparsity-in-deep-neural-networks
划重点:需要修改train_val.prototxt文件
1)修改前面的数据层,是否开启镜像mirror,图片尺寸大小crop_size,每批输入的图片数目batch_size,
2)必须修改meanfile(求得的均值文件所在)和source(训练集或测试集所在)后面的路径;
3)修改最后的输出层,调整num_output和lr_mult、decay_mult(可以使得lr_mult=10倍于原设,以更快地学习);
4)更改需要重新训练的层的名字(后续accuracy和loss层设计到该输出层的地方名字都要一起改),使得之前的权重使用bvlc_reference_caffenet.caffemodel里面的,最后这个输出层由于名字不匹配可以重新自己训练权重;
5)修改solver.prototxt文件里的全局参数,如降低base_lr和降低stepsize。
注:因为我们只需要微调前面几层的结构,而将最后一层的learning_rate设置为0.01,来加快这一层的学习;如果你想完全停止除fc8_flickr外其他层的微调,你可以设置那些层的lr_mult为0。在层数较深的情况下,由于DL本身的特性,在越高层形成的特征越抽象,而前面的卷积层则是颜色和边缘这些比较泛化的特征,所以在fine-tuning时,可以将前几层conv层的lr置为0,但是后面的conv不建议这么做。
建议:不管训练什么模型,最好自己新建一个目录,然后把所有需要的文件拷贝到该目录下,然后根据自己的需求更改。
比如,教程里面需要修改的文件都在caffle/models/finetune_flickr_style里面,有三个分别为:train_val.protxt、solver.protxt和deploy.prototxt (https://blog.youkuaiyun.com/sunshine_in_moon/article/details/49472901较为详细地介绍了这三个文件) ,可以对照原模型caffe/models/bvlc_reference_caffene对应的文件比较参考!强烈建议对照rain_val.protxt、solver.protxt和deploy.prototxt的不同,学习如何修改参数!个人认为这是简单的finetune的关键所在。
三、训练
caffe -训练train -求解器solver -导入权重weights(可选) -使用哪个gpu(用cpu就舍去这个)
caffe % ./build/tools/caffe train -solver models/finetune_flickr_style/solver.prototxt \
-weights models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel -gpu 0
注意:
caffe支持“端点续传” ,在迭代训练过程中中断或达到了设定的snapshot的频率,会生成_iter_().solverstate文件和_iter_().caffemodel,文件具体的位置和名称前缀是在solver.prototxt里的snapshot_prefix定义的,比如example里面是定义在models/finetune_flicker_style文件夹下,前缀是finetune_flicker_style,然后设定的snapshot的频率为snapshot:10000即每迭代10000次保存一次模型的训练进展。
在恢复训练的时候可以从这个文件读取继续,具体代码
caffe % ./build/tools/caffe train -solver models/finetune_flickr_style/solver.prototxt \
-snapshot models/finetune_flickr_style/finete_flickr_style_iter_100.solverstate
#不加-weights...否则报错
caffe运用已训练好的模型来测试一张新的图片<需要继续学习这部分>:
caffe % ./build/tools/caffe test -model models/finetune_flickr_style/train_val.prototxt \
-weights models/finetune_flickr_style/finete_flickr_style_iter_10000.caffemodel \
-gpu 0 -iterations 100
#只有在train_val.prototxt下有accuracy层和loss层,deploy.prototxt没有
或者用python测试
python python/classify.py --print_results --models/finetune_flickr_style/deploy.prototxt \
--pretrained_model models/finetune_flickr_style/finete_flickr_style_iter_10000.caffemodel \
--labels_file data/flickr_style/test.txt \
--center_only data/flickr_style/images/9296163038.jpg foo
下一章:finetune-VGG 或者 可视化 或者 caffe/tools代码解析(待续)