深度学习文章5:使用caffe对自己的图像数据进行训练并测试

使用caffe对自己的图像数据进行训练并测试

之前实践的一些步骤诸如数据集的准备、数据集的转换等过程都是为了训练我们所需要的模型进行铺垫,我们学习caffe的核心目的是使用caffe对我们自己的数据集进行训练,得到较好的模型,并通过模型对新的数据进行分析,这样才能较好的使用caffe分析实际项目并应用到实际领域。

1.将自己的数据集转换为caffe需要的db文件

请参照博主之前的博文深度学习文章3:将自己的图像数据转换成caffe需要的db(leveldb/lmdb)文件 ,将自己的图像数据集转换未caffe需要的db文件,这里我们生成的是文件在caffe根目录下的examples/myfile文件夹例,两个文件夹为img_train_lmdb和img_test_lmdb,分别用于保存图片转换后的lmdb文件。如图:

这里写图片描述

2.将自己的数据集转换为caffe需要的db文件

计算数据集的均值文件,请参照博主之前的博文深度学习文章4:计算图像数据集的均值 ,通过均值,我们将会提高训练的速度和精度,通常建议保留这个操作。我们生成了两个均值文件,均在caffe的根目录下的examples/myfile文件夹里:

  • mean.binaryproto,这是二进制格式的均值文件,是训练时需要的均值文件。
  • mean.npy,这是python接口需要的均值文件,是在对新的图片进行分类时需要的均值文件。

这里写图片描述

3.编写配置文件并训练模型

训练模型的配置文件包括两方面:

  • 参数的配置文件,通常名称为solver.prototxt,这里面主要包含模型的一些参数值,通常以键值对的形式存在,例如:test_iter:100,表示测试迭代次数100次。之后配置文件我们将详细介绍每个参数的含义。
  • 训练网络的配置文件,有时候为一个文件命名为train_val.prototxt,有时候为了细化分为两个文件,分别为train.prototxt和val.prototxt。主要是针对我们所使用的网络层的具体配置。

因为好多同学初学,自己并不了解如何配置参数,也不了解在如何配置更好的网络层次模型,这里为了更好的方便上手,我们将使用caffe自带的caffenet的模型,针对这个模型进行适当修改,先让同学们了解整个训练过程,上手之后再针对细节的地方进行钻研改进。

caffe自带的caffenet模型的相关文件在caffe根目录下的models/bvlc_reference_caffenet/文件夹下,我们将我们需要的两个配置文件,复制到我们自己的myfile文件夹下:

cd ~/caffe/
sudo cp models/bvlc_reference_caffenet/solver.prototxt examples/myfile/
sudo cp models/bvlc_reference_caffenet/train_val.prototxt examples/myfile/

然后,修改第一个配置文件solver.prototxt,

cd ~/caffe/
sudo gedit examples/myfile/solver.prototxt

将文件内容进行修改如下:

net: "examples/myfile/train_val.prototxt"
test_iter: 2
test_interval: 50
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 100
display: 20
max_iter: 500
momentum: 0.9
weight_decay: 0.005
snapshot: 50
snapshot_prefix: "examples/myfile/myfile_train"
solver_mode: CPU

参数列表的意思分别如下:

注:有些参数的理解需要之前对神经网络、卷积神经网络以及深度学习相关模型及算法有一定的了解,如果不了解, 可以直接参照博主的文件配置即可。这里不再详细解释。

  • net:训练的网络模型所在的位置,这里我们是将train(训练)和val(验证)作为一个文件,所以时net,如果分为两个文件,则键值对为tarin_net:训练配置文件的位置,test_net:测试配置文件的位置。
  • test_iter:测试迭代次数,我们每完成一次全部数据的训练,需要进行一次验证,例如这里我们测试迭代次数设为2,是因为我们有100个测试数据,batch_size为50,则test_iter设为100/50=2,就能全cover了。
  • test_interval:测试间隔
  • base_lr:基础学习率
  • lr_policy:学习率的变化规律
  • gamma:学习率的变化指数
  • stepsize:学习率变化频率,结合上面三个可以理解,我们的学习率初始为0.001,每迭代100次,学习率乘以变化指数0.1。
  • display:屏幕日志显示间隔,这是指多久打印依次日志,我们设为每20此迭代打印一次。
  • max_iter:最大迭代次数
  • momentum:动量
  • weight_decay:权值衰减
  • snapshot:保存训练模型的间隔,这里设为每迭代50次保存一个模型文件。
  • snapshot_prefix:保存的模型文件的前缀,例如这里为/examples/myfile/文件夹下面,前缀名为myfile_train,则该模型迭代50次后生成一个myfile_train_iter_50.caffemodel文件,其他同理,这个模型文件保存了我们训练的模型得到的各种参数信息,例如w,b。
  • solver_mode:计算方式,这里博主设置为CPU,如果你们的计算机支持GPU并且已经配置好caffe相关,则可设置为GPU,GPU的计算速度比CPU快好多。

当然,还有一种更为通用的使用python代码生成solver文件的方式,但通常来说,修改即可,这里我们也把python代码放在这里,有需要的可以自行使用:

#coding=utf-8

path='/home/moqi/'
solver_file=path+'solver.prototxt' #solver文件保存位置

kv={}
kv['net']='"examples/myfile/train_val.prototxt"'
kv['test_iter']='2'
kv['test_interval']='50'
kv['base_lr']='0.001'
kv['lr_policy']='"step"'
kv['gamma']='0.1'
kv['stepsize']='100'
kv['display']='20'
kv['max_iter']='500'
kv['momentum']='0.9'
kv['weight_decay']='0.005'
kv['snapshot']='50'
kv['snapshot_prefix']='"examples/myfile/myfile_train"'
kv['solver_mode']='CPU'

def write_solver():
    #写入文件
    with open(solver_file, 'w') as file:
        for key, value in sorted(kv.items()):
            if not(type(value) is str):
                raise TypeError('所有参数必须为字符串')
            file.write('%s: %s\n' % (key, value))
if __name__ == '__main__':
    write_solver()

有了solver.prototxt文件后,我们还需要修改另一个配置文件,即训练模型net的各层配置,这里我们只需要修改caffenet的data层即可,后面的可以不用修改,因为后面的卷积层、池化层等需要根据不同的项目边训练边调整,我们也可以参照caffe官网提供的一些不同领域的模型,目前还没有一种较为系统的层数设置和选择的方法,需要自行训练修改。两个data层修改如下:

name: "CaffeNet"
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
    mean_file: "examples/myfile/mean.binaryproto"
  }
  data_param {
    source: "examples/myfile/img_train_lmdb"
    batch_size: 256
    backend: LMDB
  }
}
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 227
    mean_file: "examples/myfile/mean.binaryproto"
  }
  data_param {
    source: "examples/myfile/img_test_lmdb"
    batch_size: 50
    backend: LMDB
  }
}

后面的conv卷积层等就不用修改了,之后实际应用中可参照目前主流的配置修改自己的,毕竟修改需要建立在具有卷积神经网络的基础概念和网络模型的了解的基础上,这里就不赘述了。

接下来,就是训练模型:

cd ~/caffe/
sudo build/tools/caffe train -solver examples/myfile/solver.prototxt

运行的时间和准确率会根据不同的电脑配置即参数设置不同,博主这里训练了两次,均采用CPU计算,第一次准确率96%:

这里写图片描述

第二次准确率94%:

这里写图片描述

运行实践大概在5小时左右,因为博主搭建环境的机器配置较低,并且是CPU模式,如果可以有较好的机器配置,外加GPU+CUDNN,大概时间可缩短到半个小时左右,准确率徘徊在95%左右。

运行后会根据之前solver设置的保存模型的位置生成对应的文件,可以选择准确率较高的模型文件在之后测试新的图像分类时使用:

这里写图片描述

3.使用模型对新的图像进行分类

在对一个新的图片进行分类之前,我们还需要一个deploy.prototxt文件,这个文件和之前模型层次文件类似,只不过首尾不太一样,没有第一层数据输入层,也没有最后的Accuracy层,但最后需要添加一个Softmax层,用于计算分类概率。

这里我们将caffenet的solver.prototxt复制过来使用即可,如果之后自己的设计model的train_val时,记得要将solver.prototxt与其保持一致。

cd ~/caffe/
sudo cp models/bvlc_reference_caffenet/deploy.prototxt examples/myfile/

接着,还需要一个类别映射文件,我们可以将类别数字代码转换成对应的类别名称,例如之前3-汽车,4-恐龙,5-大象,6-花,7-马。主要注意的是这个文件往往是根据索引来的,最好的时类别数字代码从0开始,即可对应,但如果没有从0开始,像博主一样,就需要添加一个来凑齐索引对应,我的映射文件命名为labels.txt,内容如下:

这里写图片描述

如果你的类名数字从0开始,和索引一致,就不需要加一些来凑齐了。

接下来,我们拿一张新的测试图片,命名为my.jpg,实际类别为大象,这个文件也在myfile/文件夹下:

这里写图片描述

然后我们需要编写代码来对图片应用模型进行分类,这里博主使用python来进行,python的IDE时Eclipse+PyDev插件,代码如下:

Eclipse+PyDev,需要的同学可以根据博主的另一篇博文Eclipse中Python开发环境搭建(Ubuntu16.04) 搭建。

#coding=utf-8
import sys
caffe_root = '/home/moqi/caffe/'
sys.path.insert(0, caffe_root + 'python')

import caffe

import numpy as np

root='/home/moqi/caffe/'   #根目录
deploy=root + 'examples/myfile/deploy.prototxt'    #deploy文件
caffe_model=root + 'examples/myfile/myfile_train_iter_100.caffemodel'   #训练好的 caffemodel
img=root+'examples/myfile/my.jpg'    #随机找的一张待测图片
labels_filename = root + 'examples/myfile/labels.txt'  #类别名称文件,将数字标签转换回类别名称
mean_file=root + 'examples/myfile/mean.npy' #均值文件


net = caffe.Net(deploy,caffe_model,caffe.TEST)   #加载model和network

#图片预处理设置
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) #设定图片的shape格式(1,3,28,28)
transformer.set_transpose('data', (2,0,1))    #改变维度的顺序,由原始图片(28,28,3)变为(3,28,28)
transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))    #减去均值
transformer.set_raw_scale('data', 255)    # 缩放到【0,255】之间
transformer.set_channel_swap('data', (2,1,0))   #交换通道,将图片由RGB变为BGR


im=caffe.io.load_image(img) #加载图片
net.blobs['data'].data[...] = transformer.preprocess('data',im)      #执行上面设置的图片预处理操作,并将图片载入到blob中

#执行测试
out = net.forward()
labels = np.loadtxt(labels_filename, str, delimiter='\t')   #读取类别名称文件

prob= net.blobs['prob'].data[0].flatten()#取出最后一层(Softmax)属于某个类别的概率值
top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1] 
for i in np.arange(top_k.size): 
    print top_k[i], labels[top_k[i]],prob[top_k[i]]

需要注意的是一些文件的路径问题,例如deploy文件、训练好的 caffemodel文件(这里用的是迭代100次的)、待测图片、类别名称文件(将数字标签转换回类别名称)、均值文件(之前生成的python接口所需的均值文件,可查看前篇博文)。

运行结束后,可以看到结果:

这里写图片描述

可以看到属于大象的概率0.99,恐龙0.003,汽车0.0015,花0.0004,马0.0003,所以,这个待测图片属于大象类别,与实际相符。

4.题后语

至此,我们已经实际的将一个模型搭建起来,并可以进行应用,但具体实际的模型层次设计,需要根据不同的应用领域不同编写,这就需要很好的理论学习,这里我们更多说的时实际操作,博主之后会就神经网络以及深度学习的相关理论知识写出博文,敬请期待,希望大家对博文不合适的地方提出来,交流改正。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值