caffe笔记3(matlab程序)

引言:
在caffe提供的例程当中,例如mnist与cifar10中,数据集的准备均是通过调用代码自己完成的,而对于ImageNet1000类的数据库,对于个人而言,常常面临电脑内存不足的尴尬境地。而对于应用者而言,用适合于自己条件的的数据集在caffe下训练及测试才是更重要的。所以我们有必要用自己做数据库在caffe上训练和测试。

目的:使用自己的数据集,使用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分类。
如果当样本过多,就自己编写指令批量处理。 同样的方式可获得test.txt。
注:windows下matlab批量处理代码如下:
% 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 sh examples/mytest/get_filelist.sh
成功的话就会在examples/mydata/ 文件夹下生成train.txt和test.txt两个文本文件,里面就是图片的列表清单,如下图:
Caffe下用自己的数据训练和测试过程详解 - 樂不思蜀 - 樂不思蜀
 
2 转换为lmdb格式

接着再编写一个脚本文件,调用convert_imageset命令来转换数据格式:
 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下,修改训练和测试数据的路径以及产生数据的路径即可。
运行成功后,会在 examples/mytest下面生成两个文件夹mytest_train_lmdb和mytest_test_lmdb,分别用于保存图片转换后的lmdb文件。
Caffe学习:Caffe下用自己的数据训练和测试过程详解 - 樂不思蜀 - 樂不思蜀
 因为图片大小不一,因此我统一转换成256*256大小。
注:windows下用matlab代码处理图片大小问题:
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

 3 计算图像均值
图片减去均值再训练,会提高训练速度和精度。因此,一般都会有这个操作。caffe程序提供了一个计算均值的文件 tools/compute_image_mean.cpp,这个cpp是一个很好的例子去熟悉如何操作多个组建,例如协议的缓冲区,leveldbs,登录等。
编辑脚本文件并运行:
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 创建模型并编写配置文件
把caffe/models/bvlc_reference_caffenet中所有文件复制到caffe/examples/mytest文件夹中
sudo cp models/bvlc_reference_caffenet/solver.prototxt examples/mytest/
sudo cp models/bvlc_reference_caffenet/train_val.prototxt examples/mytest/
编辑train_val.prototxt文件,注意修改数据层的路径:

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%。
Caffe学习:Caffe下用自己的数据训练和测试过程详解 - 樂不思蜀 - 樂不思蜀
 
6 恢复数据
把caffe/examples/imagenet中的resume_training.sh复制过来编辑,并运行。
我们用指令 sudo ./examples/mytest/resume_training.sh 即可。

#!/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

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页