本系列文章主要介绍了在win10系统下caffe的安装编译,运用CPU和GPU完成简单的小项目,文章之间具有一定延续性。
step1:准备数据集
数据集是进行深度学习的第一步,在这里我们从以下五个链接中下载所需要的数据集:
animal
flower
plane
house
guitar
我们在原先的models文件夹下新建文件夹my_models_recognition,用于存放本文在实现图像识别过程中的相关文件。我们之前下载的五个压缩包包含animal、flower、plane、house和guitar五个类别。我们首先需要将其分成训练集和测试集两个部分,在这里,我们采用手工的方法来制作数据集。
首先分别在train和test文件夹下新建五个类别的文件夹,用于存放每个类别的训练集和测试集。
在这里,我们设定训练集的数目为500,测试集的数目为300,我们将每个分类的前500章图片剪切到train文件夹的相应类别下,用于作为训练集,剪切300张图片到test的相应文件夹下作为测试集。至此,我们已经完成了数据集的准备工作。
step2:制作标签
我们以“文件路径+标签”的形式对每个图像进行命名,在这里,如果我们继续采用手工操作对图像标签进行制作,这个过程需要耗费大量的时间。为此,我们在jupyter 中运行下列程序来帮助我们完成标签制作。在运行程序之前先新建labels文件夹用于存放产生的标签。
import os
#定义Caffe根目录
caffe_root = ‘E:/caffe-windows/’
#制作训练标签数据
i = 0 #标签
with open(caffe_root + ‘models/my_models_recognition/labels/train.txt’,‘w’) as train_txt:
for root,dirs,files in os.walk(caffe_root+‘models/my_models_recognition/data/train/’): #遍历文件夹
for dir in dirs:
for root,dirs,files in os.walk(caffe_root+‘models/my_models_recognition/data/train/’+str(dir)): #遍历每一个文件夹中的文件
for file in files:
image_file = str(dir) + ‘\’ + str(file)
label = image_file + ’ ’ + str(i) + ‘\n’ #文件路径+空格+标签编号+换行
train_txt.writelines(label) #写入标签文件中
i+=1 #编号加1
#制作测试标签数据
i=0 #标签
with open(caffe_root + ‘models/my_models_recognition/labels/test.txt’,‘w’) as test_txt:
for root,dirs,files in os.walk(caffe_root+‘models/my_models_recognition/data/test/’): #遍历文件夹
for dir in dirs:
for root,dirs,files in os.walk(caffe_root+‘models/my_models_recognition/data/test/’+str(dir)): #遍历每一个文件夹中的文件
for file in files:
image_file = str(dir) + ‘\’ + str(file)
label = image_file + ’ ’ + str(i) + ‘\n’ #文件路径+空格+标签编号+换行
test_txt.writelines(label) #写入标签文件中
i+=1#编号加1
print “成功生成文件列表”
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
运行程序,输出“成功生成文件列表”,打开labels文件夹,就可以在里面分别找到train和test的标签文件。
至此,我们也已经完成了标签的制作过程。
step3:数据转换
由于我们的数据集中图片是png的形式,我们需要将其转化为LMDB的格式,新建lmdb文件夹用于存放生成的lmdb文件。
和之前我们讲述的方法一样,在这里我们运用convert_imageset.exe来完成格式转化。运行批处理文件如下,对训练集的图像进行格式转换并打乱图片顺序:
%格式转换的可执行文件%
%重新设定图像大小%
%打乱图片%
%转换格式%
%图片路径%
%图片标签%
%lmdb文件的输出路径%
E:\caffe-windows\Build\x64\Release\convert_imageset.exe ^
--resize_height=256 --resize_width=256 ^
--shuffle ^
--backend=“lmdb” ^
E:\caffe-windows\models\my_models_recognition\data\train\ ^
E:\caffe-windows\models\my_models_recognition\labels\train.txt ^
E:\caffe-windows\models\my_models_recognition\lmdb\train
pause
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
同理,运行如下程序修改测试集中的图片格式。
%格式转换的可执行文件%
%重新设定图像大小%
%打乱图片%
%转换格式%
%图片路径%
%图片标签%
%lmdb文件的输出路径%
E:\caffe-windows\Build\x64\Release\convert_imageset.exe ^
--resize_height=256 --resize_width=256 ^
--shuffle ^
--backend=“lmdb” ^
E:\caffe-windows\models\my_models_recognition\data\test\ ^
E:\caffe-windows\models\my_models_recognition\labels\test.txt ^
E:\caffe-windows\models\my_models_recognition\lmdb\test
pause
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
step5:修改网络参数文件
在之前的文章中,我们使用过Googlenet,Googlenet适用于分类多,数据量大的情况,当数据集太小的时候容易出现过拟合现象(如本文只采用500个数据集),因此在这里我们使用caffenet来完成图像的分类。
把上述文件复制到my_models_recognition中,然后编辑网络参数文件
在这里,我们没有使用均值文件,因此将下列代码注释掉
# transform_param {
# mirror: true
# crop_size: 227
# mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
# }
# mean pixel / channel-wise mean instead of mean image
- 1
- 2
- 3
- 4
- 5
- 6
同理,还有下列代码:
# transform_param {
# mirror: false
# crop_size: 227
# mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
# }
# mean pixel / channel-wise mean instead of mean image
- 1
- 2
- 3
- 4
- 5
- 6
将第25行batch size改为100
将293和333行num_output改为512
373行中,因为这里我们只有五个类别,所以只需要5个输出即可,将1000改为5
step6:修改超参数文件
对超参数文件中的路径进行修改,最大迭代次数改为3000.,每500次迭代输出一次model,并新建文件夹model,用于存放训练得到的模型
net: "E:/caffe-windows/models/my_models_recognition/train_val.prototxt"
test_iter: 30
test_interval: 200
base_lr: 0.01
lr_policy: "step"
gamma: 0.1
stepsize: 1000
display: 50
max_iter: 3000
momentum: 0.9
weight_decay: 0.0005
snapshot: 500
snapshot_prefix: "E:/caffe-windows/models/my_models_recognition/model/"
solver_mode: GPU
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
step7:准备标签
新建label文件,在里面放置物体的类别
step8:修改deploy Prototxt文件
虽然在之前我们已经修改了网络结构文件,但是在测试过程中我们使用的是deploy Prototxt文件,因此我们对其进行同样的修改:
181行和157行输出改为512,第205行改为5.
step9:模型运行
运行批处理文件如下:
%train训练数据%
%超参数文件%
E:\caffe-windows\Build\x64\Release\caffe.exe train ^
-solver=E:/caffe-windows/models/my_models_recognition/solver.prototxt ^
pause
- 1
- 2
- 3
- 4
- 5
- 6
(第一次进行训练的时候是设置没5次迭代输出一次结构,第二次训练改为500次训练输出一次结构,因此前面有那些第五次第十次之类,忽略即可)
step10:准备测试图片
新建image文件夹,将我们要测试的图片放置在其中:
step11:模型测试
在jupyter中运行如下代码:
import caffe
import numpy as np
import matplotlib.pyplot as plt
import os
import PIL
from PIL import Image
import sys
#定义Caffe根目录
caffe_root = ‘E:/caffe-windows/’
#网络结构描述文件
deploy_file = caffe_root+‘models/my_models_recognition/deploy.prototxt’
#训练好的模型
model_file = caffe_root+‘models/my_models_recognition/model/_iter_3000.caffemodel’
#gpu模式
#caffe.set_device(0)
caffe.set_mode_cpu()
#定义网络模型
net = caffe.Classifier(deploy_file, #调用deploy文件
model_file, #调用模型文件
channel_swap=(2,1,0), #caffe中图片是BGR格式,而原始格式是RGB,所以要转化
raw_scale=255, #python中将图片存储为[0, 1],而caffe中将图片存储为[0, 255],所以需要一个转换
image_dims=(227, 227)) #输入模型的图片要是227*227的图片
#分类标签文件
imagenet_labels_filename = caffe_root +‘models/my_models_recognition/labels/label.txt’
#载入分类标签文件
labels = np.loadtxt(imagenet_labels_filename, str)
#对目标路径中的图像,遍历并分类
for root,dirs,files in os.walk(caffe_root+‘models/my_models_recognition/image/’):
for file in files:
#加载要分类的图片
image_file = os.path.join(root,file)
input_image = caffe.io.load_image(image_file)
<span class="token comment">#打印图片路径及名称</span>
image_path <span class="token operator">=</span> os<span class="token punctuation">.</span>path<span class="token punctuation">.</span>join<span class="token punctuation">(</span>root<span class="token punctuation">,</span><span class="token builtin">file</span><span class="token punctuation">)</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>image_path<span class="token punctuation">)</span>
<span class="token comment">#显示图片</span>
img<span class="token operator">=</span>Image<span class="token punctuation">.</span><span class="token builtin">open</span><span class="token punctuation">(</span>image_path<span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>axis<span class="token punctuation">(</span><span class="token string">'off'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">#预测图片类别</span>
prediction <span class="token operator">=</span> net<span class="token punctuation">.</span>predict<span class="token punctuation">(</span><span class="token punctuation">[</span>input_image<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">print</span> <span class="token string">'predicted class:'</span><span class="token punctuation">,</span>prediction<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>argmax<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 输出概率最大的前5个预测结果</span>
top_k <span class="token operator">=</span> prediction<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>argsort<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span>
<span class="token keyword">for</span> node_id <span class="token keyword">in</span> top_k<span class="token punctuation">:</span>
<span class="token comment">#获取分类名称</span>
human_string <span class="token operator">=</span> labels<span class="token punctuation">[</span>node_id<span class="token punctuation">]</span>
<span class="token comment">#获取该分类的置信度</span>
score <span class="token operator">=</span> prediction<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span>node_id<span class="token punctuation">]</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'%s (score = %.5f)'</span> <span class="token operator">%</span> <span class="token punctuation">(</span>human_string<span class="token punctuation">,</span> score<span class="token punctuation">)</span><span class="token punctuation">)</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
运行代码即可输出分类结果,我们发现模型的识别准确率非常高
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-2b43bc2447.css" rel="stylesheet">
</div>
<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
if(typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object"){
if(!window.csdn.anonymousUserLimit.judgment()){
window.csdn.anonymousUserLimit.Jumplogin();
return false;
}else if(!currentUserName){
window.csdn.anonymousUserLimit.updata();
}
}
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>