【原文:http://blog.csdn.net/qqlu_did/article/details/47131549】
在caffe提供的例程当中,例如mnist与cifar10中,数据集的准备均是通过调用代码自己完成的,而对于ImageNet1000类的数据库,对于高校实验室而言,常常面临电脑内存不足的尴尬境地。而对于应用者而言,用适合于自己条件的的数据集在caffe下训练及测试才是更重要的。所以我们有必要自己做数据库以及在caffe上训练及测试。
1,数据准备
在data中新建文件夹myself,我们截取了ImageNet1000类中的两类—panda与sea_horse,训练panda的图片24张,测试panda的图片6张,训练sea_horse的图片38张,测试sea_horse的图片7张。如图所示:
培训和测试的输入是用train.txt和val.txt描述的,这些文档列出所有文件和他们的标签。注意,在imagenet1000类中,我们分类的名字是ASCII码的顺序,即0-999,对应的分类名和数字的映射在synset_words.txt(自己写)中。
运行以下指令:
<code class="hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">find <span class="hljs-attribute" style="box-sizing: border-box;">-name</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>jpeg <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">|</span>cut <span class="hljs-attribute" style="box-sizing: border-box;">-d</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'/'</span> <span class="hljs-attribute" style="box-sizing: border-box;">-f2</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span> train<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>txt</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
注意路径
然后,因为自己的数据库样本数比较少,可以自行手动做分类标签。在train.txt的每个照片后用1-2分类。如图:
当样本过多,就自己编写指令批量处理。
同理,获得val.txt。matlab(windows下)批量处理代码如下:
<code class="hljs delphi has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">% batch <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">write</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> txt
clear all
clc
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>=dir(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'F:\animal\sea_horse'</span>);
temp=length(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>:temp);
fp=fopen(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'F:\animal\animal.txt'</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'at'</span>);
% <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'at'</span> open <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> create <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> reading <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> writing; append data <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>
% <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'wt'</span> discard existing contents
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> n=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:length(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>)
fprintf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'iter=%d\n'</span>,n)
txt=[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>(n).name <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">' 2'</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>];
fprintf(fp,txt);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span>
fclose(fp);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>
Test.txt不能标签,全部设置成0。
我们还需要把图片的大小变成256X256,官网上提供了下面的命令:
<code class="hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> name <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> /path/to/imagenet/val/*.JPEG; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>
convert -resize <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>x256\! <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$name</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$name</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">done</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
但是我自己并没有成功,就只好用matlab(windows下)代码处理了一下:
<code class="hljs applescript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> n=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:<span class="hljs-property" style="box-sizing: border-box;">length</span>(<span class="hljs-type" style="box-sizing: border-box;">file</span>)
temp=imread(['F:\animal\panda\' <span class="hljs-type" style="box-sizing: border-box;">file</span>(n).<span class="hljs-property" style="box-sizing: border-box;">name</span>]);
temp=imresize(temp,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
temp=imresize(temp,[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>]);
imwrite(temp,['F:\animal\panda\' <span class="hljs-type" style="box-sizing: border-box;">file</span>(n).<span class="hljs-property" style="box-sizing: border-box;">name</span>]);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
然后在caffe-master/examples中新建myself文件夹,然后将caffe-maester/examples/imagenet的create_imagenet.sh复制到该文件夹下,将其名改为create_animal.sh,修改训练和测试路径的设置,运行该sh.如图:
最后得到myself_train_lmdb和myself_val_lmdb:
2 计算图像均值
模型需要我们从每张图片减去均值,所以我们必须获得训练的均值,用
tools/compute_image_mean.cpp实现,这个cpp是一个很好的例子去熟悉如何操作多个组建,例如协议的缓冲区,leveldbs,登录等。我们同样复制caffe-maester/examples/imagenet的
./make_imagenet_mean到examples/myself中,将其改名为make_animal_mean.sh,加以修改路径。
3 网络的定义
把caffe-master/models/bvlc_reference_caffenet中所有文件复制到caffe-master/examples/myself文件夹中,修改train_val.prototxt,注意修改数据层的路径。如图:
如果你细心观察train_val.prototext,你会发现他们除了数据来源不同和最后一层不同,其他基本相同。在训练中,我们用一个softmax——loss层计算损失函数和初始化反向传播,而在验证,我们使用精度层检测我们的精度。
我们还有一个运行的协议solver.prototxt,复制过来,将第一行路径改为我们的路径net: “examples/myself/train_val.prototxt”,从里面可以观察到,我们将运行256批次,迭代4500000次(90期),每1000次迭代,我们测试学习网络验证数据,我们设置初始的学习率为0.01,每100000(20期)次迭代减少学习率,显示一次信息,训练的weight_decay为0.0005,每10000次迭代,我们显示一下当前状态。
以上是教程的,实际上,以上需要耗费很长时间,因此,我们稍微改一下
test_iter: 1000是指测试的批次,我们就10张照片,设置10就可以了。
test_interval: 1000是指每1000次迭代测试一次,我们改成500次测试一次。
base_lr: 0.01是基础学习率,因为数据量小,0.01就会下降太快了,因此改成0.001
lr_policy: “step”学习率变化
gamma: 0.1学习率变化的比率
stepsize: 100000每100000次迭代减少学习率
display: 20每20层显示一次
max_iter: 450000最大迭代次数,
momentum: 0.9学习的参数,不用变
weight_decay: 0.0005学习的参数,不用变
snapshot: 10000每迭代10000次显示状态,这里改为2000次
solver_mode: GPU末尾加一行,代表用GPU进行
4 训练
把caffe-master/examples/imagenet中的train_caffenet.sh复制过来并修改名为train_myself.sh运行,修改里面的路径,如图:
当然,只有两类,正确率还是相当的高,例如迭代到2000次的时候,正确率是0.924,即13张var样本只有1张预测错了。
如图:
5 恢复数据
把caffe-master/examples/imagenet中的resume_training.sh复制过来并运行。
我们用指令./即可。
参照材料:学习笔记3 用自己的数据训练和测试“CaffeNet” 2014.7.22 薛开宇
Caffe官网 ImageNet tutorial