目的:使用自己的数据集,使用caffe自带的ImageNet网络结构进行训练和测试。
参考官网链接:http://caffe.berkeleyvision.org/gathered/examples/imagenet.html
1 数据集准备在caffe/data/中新建文件夹mydata,把准备好的数据集放入mydata中,我们需要准备的文件有:
1 文件夹train:里面放训练的图片
2 文件夹test:里面放测试的图片
3 train.txt :训练图片的文件名和对应的类别
4 test.txt:测试图片的文件名和对应的类别
我去网上找了一些其它的图片来代替ImageNet1000库,共有500张图片,分为大巴车、恐龙、大象、鲜花和马五个类,每个类100张。编号分别以3,4,5,6,7开头,各为一类。我从其中每类选出20张作为测试,其余80张作为训练。因此最终训练图片400张,测试图片100张,共5类。
其中,训练和测试的输入是用train.txt和val.txt描述的,这些文档列出所有文件和他们的标签。运行以下指令(注意路径):DATA=examples/images
find $DATA -name *cat.jpg | cut -d '/' -f3 | sed "s/$/ 1/">>$DATA/train.txt
然后,如果数据库样本数比较少,可以自行手动做分类标签。在train.txt的每个照片后用3-7分类。
% batch write in txt
clear all
clc
file=dir('F:\animal\sea_horse');
temp=length(file);
file=file(3:temp);
fp=fopen('F:\animal\animal.txt','at');
% 'at' open or create file for reading and writing; append data to end of file
% 'wt' discard existing contents
for n=1:length(file)
fprintf('iter=%d\n',n)
txt=[file(n).name ' 2' '\n'];
fprintf(fp,txt);
end
fclose(fp);
ubuntu下编辑脚本文件:
sudo mkdir examples/mytest sudo vi examples/mytest/get_filelist.sh
#!/usr/bin/env sh DATA=data/mydata echo "Create train.txt..." rm -rf $DATA/train.txt for i in 3 4 5 6 7 do find $DATA/train -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$DATA/train.txt done echo "Create test.txt..." rm -rf $DATA/test.txt for i in 3 4 5 6 7 do find $DATA/test -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$DATA/test.txt done echo "All done"
运行脚本: sudo vi examples/mytest/create_lmdb.sh
#!/usr/bin/env sh EXAMPLE=examples/mytest ##根据自己的路径修改 DATA=data/mydata // TOOLS=bulid/tools
echo "Create train lmdb.." rm -rf $EXAMPLE/mytest_train_lmdb build/tools/convert_imageset \ --shuffle \ --resize_height=256 \ --resize_width=256 \ /home/wujx/caffe/data/mydata/ \ ##训练图片的路径 $DATA/train.txt \ ##输入train.txt的路径 $EXAMPLE/mytest_train_lmdb ##输出train_lmdb的路径
echo "Create test lmdb.." rm -rf $EXAMPLE/mytest_test_lmdb build/tools/convert_imageset \ --shuffle \ --resize_width=256 \ --resize_height=256 \ /home/wujx/caffe/data/mydata/ \ ##测试图片的路径 $DATA/test.txt \ ##输入test.txt的路径 $EXAMPLE/mytest_test_lmdb ##输出test_lmdb的路径 echo "All Done.."
ps:如果想省事,可以直接将caffe/examples/imagenet的create_imagenet.sh复制到examples/mytest下,修改训练和测试数据的路径以及产生数据的路径即可。for n=1:length(file)
temp=imread(['F:\animal\panda\' file(n).name]);
temp=imresize(temp,2);
temp=imresize(temp,[256 256]);
imwrite(temp,['F:\animal\panda\' file(n).name]);
end
sudo vi examples/mytest/make_image_mean.sh sudo sh examples/mytest/make_image_mean.sh
#!/usr/bin/env sh # Compute the mean image from the imagenet training lmdb # N.B. this is available in data/ilsvrc12 EXAMPLE=examples/mytest %@@ 根据自己的路径修改 DATA=data/mydata %@@ 根据自己的路径修改 TOOLS=build/tools %@@ 根据自己的路径修改 $TOOLS/compute_image_mean $EXAMPLE/mytest_train_lmdb \ $DATA/mytest_mean.binaryproto %@@ echo "Done."
compute_image_mean带两个参数,第一个参数是lmdb训练数据位置,第二个参数设定均值文件的名字及保存路径。 运行成功后,会在 examples/myfile/ 下面生成一个mytest_mean.binaryproto的均值文件。4 创建模型并编写配置文件
sudo cp models/bvlc_reference_caffenet/solver.prototxt examples/mytest/ sudo cp models/bvlc_reference_caffenet/train_val.prototxt examples/mytest/
name: "CaffeNet" layer { name: "data" type: "Data" top: "data" top: "label" include { phase: TRAIN } transform_param { mirror: true crop_size: 227 mean_file: "examples/mytest/mytest_mean.binaryproto" } # mean pixel / channel-wise mean instead of mean image # transform_param { # crop_size: 227 # mean_value: 104 # mean_value: 117 # mean_value: 123 # mirror: true # } data_param { source: "examples/mytest/mytest_train_lmdb" batch_size: 32 %@@此处batch_size不宜设置过大,否则会出现out of memory错误 backend: LMDB } } layer { name: "data" type: "Data" top: "data" top: "label" include { phase: TEST } transform_param { mirror: false crop_size: 227 mean_file: "examples/mytest/mytest_mean.binaryproto" } # mean pixel / channel-wise mean instead of mean image # transform_param { # crop_size: 227 # mean_value: 104 # mean_value: 117 # mean_value: 123 # mirror: false # } data_param { source: "examples/mytest/mytest_val_lmdb" batch_size: 50 backend: LMDB } }
... ...
如果你细心观察train_val.prototext,你会发现他们除了数据来源不同和最后一层不同,其他基本相同。在训练中,我们用一个softmax——loss层计算损失函数和初始化反向传播,而在验证,我们使用精度层检测我们的精度。编辑solver.prototxt,从里面可以观察到,我们将运行256批次,迭代4500000次(90期),每1000次迭代,我们测试学习网络验证数据,我们设置初始的学习率为0.01,每100000(20期)次迭代减少学习率,显示一次信息,训练的weight_decay为0.0005,每10000次迭代,我们显示一下当前状态。
以上是教程的,实际上,以上需要耗费很长时间,因此,我们稍微改一下 :
net: "examples/mytest/train_val.prototxt" //根据自己的路径做修改 test_iter: 2 //测试的时候,输入2个batch test_interval: 50 //每迭代50次,测试一次 base_lr: 0.001 //基础学习率,因为数据量小,0.01就会下降太快了,因此改成0.001 lr_policy: "step" gamma: 0.1 //0.1学习率变化的比率 stepsize: 100 //每迭代100次,调整一次学习率 display: 20 //每20次迭代,显示一次 max_iter: 1000 //最大迭代1000次 momentum: 0.9 //学习的参数,不用变 weight_decay: 0.0005 //学习的参数,不用变 snapshot: 5000 //每迭代5000次显示状态 snapshot_prefix: "examples/mytest/caffenet_train" //根据自己的路径做修改 solver_mode: GPU //表示用GPU运算
知识点说明:查看我们train_val.prototxt文件,发现batch_size: 50;我们的test图片是100张,100/50=2,所以test_iter=2。
5 开始训练
编辑并运行脚本文件:
sudo vi examples/mytest/train_mycaffenet.sh sudo sh examples/mytest/train_mycaffenet.sh
#!/usr/bin/env sh set -e ./build/tools/caffe train \ --solver=examples/mytest/solver.prototxt $@
运行时间和最后的精确度,会根据机器配置,参数设置的不同而不同。我的是gpu+cudnn运行500次,大约8分钟,精度为95%。#!/usr/bin/env sh set -e ./build/tools/caffe train \ --solver=examples/mytest/solver.prototxt \ --snapshot=examples/mytest/caffenet_train_10000.solverstate.h5 \ $@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
错误总结:
测试出现如下错误:
F0713 21:28:27.059324 3532 syncedmem.cpp:47] Check failed: error == cudaSuccess(2 vs. 0) out of memory *** Check failure stack trace: *** @ 0x7fb1ce8da9fd google::LogMessage::Fail() @ 0x7fb1ce8dc89d google::LogMessage::SendToLog() @ 0x7fb1ce8da5ec google::LogMessage::Flush() @ 0x7fb1ce8dd1be google::LogMessageFatal::~LogMessageFatal() @ 0x447284 caffe::SyncedMemory::mutable_gpu_data() @ 0x43c9d2 caffe::Blob<>::mutable_gpu_diff() @ 0x4934f2 caffe::InnerProductLayer<>::Backward_gpu() @ 0x42e403 caffe::Net<>::Backward() @ 0x445bd7 caffe::Solver<>::Solve() @ 0x40a0c8 main @ 0x7fb1cbf56ec5 (unknown) @ 0x40be37 (unknown) Aborted (core dumped)
Google 之后 https://github.com/BVLC/caffe/issues/682 发现是train_val.prototxt中的train部分的batch_size设置过大导致,把batch_size改小重新运行就好了。
原来设置为256,是为了方便看测试数据,例如我改成了32。
参考官网链接:http://caffe.berkeleyvision.org/gathered/examples/imagenet.html