程序与技术分享:caffe的使用方法

简介: 程序与技术分享:caffe的使用方法

Caffe学习总结(更新中)


主要参考一个大牛的caffe学习系列博客:


这里说明一下:下面的测试分别在我自己的电脑和服务器上进行(服务器速度快),


  1.  关于caffe的简介


  caffe是一个清晰而高效的深度学习框架,纯粹的C++/CUDA架构,支持命令行、Python和MATLAB接口,可以在CPU和GPU直接无缝切换;


  caffe的主要优势:


    (1)CPU与GPU的无缝切换;


    (2)模型与优化都是通过配置文件来设置,无需代码;


  简洁好用不多说。


  2. Caffe环境的搭建,参考另一篇博客:Ubuntu14.04安装caffe。


  3.  Caffe总体框架介绍


  主要参考:深度学习框架Caffe源码解析;


  若想详细了解caffe源码,参考官方教程Tutorial Documentation或者看《caffe官方教程中译本》。


  还有一个博客写的很好,caffe源码解析:


  Caffe主要由Blob,Layer,Net 和 Solver这几个部分组成。


   1)Blob


    主要用来表示网络中的数据,包括训练数据,网络各层自身的参数(包括权值、偏置以及它们的梯度),网络之间传递的数据都是通过 Blob 来实现的,同时 Blob 数据也支持在 CPU 与 GPU 上存储,能够在两者之间做同步。


  2)Layer


    是对神经网络中各种层的一个抽象,包括我们熟知的卷积层和下采样层,还有全连接层和各种激活函数层等等。同时每种 Layer 都实现了前向传播和反向传播,并通过 Blob 来传递数据。


   3) Net


    是对整个网络的表示,由各种 Layer 前后连接组合而成,也是我们所构建的网络模型。


   4) Solver


    定义了针对 Net 网络模型的求解方法,记录网络的训练过程,保存网络模型参数,中断并恢复网络的训练过程。自定义 Solver 能够实现不同的网络求解方式。


完整巧妙不多说。


  4. 总流程(重点)


  完成一个简单的自己的网络模型训练预测,主要包含几个步骤:(以一个实例介绍)


  1) 准备数据;


  例1,学习系列博客上的数据,后面会用到,这里简单说明一下:


    可以从这里下载:


    共有500张图片,分为大巴车、恐龙、大象、鲜花和马五个类,每个类100张。编号分别以3,4,5,6,7开头,各为一类。从其中每类选出20张作为测试,其余80张作为训练。


    因此最终训练图片400张,测试图片100张,共5类。我将图片放在caffe根目录下的  data文件夹下面。即训练图片目录:data/re/train/ ,测试图片目录: data/re/test/。


  2) 数据格式处理,也就是把我们jpg,jpeg,png,tif等格式的图片(可能存在大小不一致的问题),处理转换成caffe中能够运行的db(leveldb/lmdb)文件。


  参考学习系列博客 Caffe学习系列(11):图像数据转换成db(leveldb/lmdb)文件 讲的非常详细。


    convert_imageset.cpp,存放在根目录下的tools文件夹下。编译之后,生成对应的可执行文件放在 buile/tools/ 下面,这个文件的作用就是用于将图片文件转换成caffe框架中能直接使用的db文件。


    该文件的使用格式:


      convert_imageset 【FLAGS】 ROOTFOLDER/ LISTFILE DB_NAME


    四个参数:


      FLAGS: 图片参数组,后面详细介绍;


      ROOTFOLDER/: 图片存放的绝对路径,从linux系统根目录开始;


      LISTFILE: 图片文件列表清单,一般为一个txt文件,一行一张图片;


      DB_NAME: 最终生成的db文件存放目录。


    其中第二个和第四个目录是自己决定的,不多说;


    先说第三个,所谓图片列表清单,也叫标签文件,一般该文件存放图片文件路径,以及该图片的标签(属于哪个类);一般来说,标签文件有两个,一个描述训练集合-train.txt,一个描述测试集合-test.txt,(可能还有描述验证的val.txt),


    例1中测试图片转换后的标签文件格式(test.txt)如下:


  那怎么由图片生成标签文件呢?


    当然图片很少的时候,直接手动输入就好了,但图片很多的情况,就需要用脚本文件来自动生成了。之前对脚本的编写不是很熟,有个快速上手的文章:


    其实非常简单( ̄▽ ̄))


    对于例1,在examples下面创建一个myfile的文件夹,来用存放配置文件和脚本文件。然后编写一个脚本create_filelist.sh,用来生成train.txt和test.txt清单文件。脚本(/examples/myfile/create_filelist.sh)编写如下:


#!/usr/bin/env sh


DATA=data/re/


MY=examples/myfile


echo "Create train.txt..."


rm -rf $MY/train.txt


for i in 3 4 5 6 7


do


find $DATA/train -name $i.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/"$MY/train.txt


done


echo "Create test.txt..."


rm -rf $MY/test.txt


for i in 3 4 5 6 7


do


find $DATA/test -name $i.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/"$MY/test.txt


done


echo "All done"


    生成的.txt文件,就可以作为第三个参数,直接使用了。


  最后了解一下第一个参数:即FLAGS这个参数组,有些什么内容:


    -gray: 是否以灰度图的方式打开图片。程序调用opencv库中的imread()函数来打开图片,默认为false


    -shuffle: 是否随机打乱图片顺序。默认为false


    -backend:需要转换成的db文件格式,可选为leveldb或lmdb,默认为lmdb


    -resize_width/resize_height: 改变图片的大小。在运行中,要求所有图片的尺寸一致,因此需要改变图片大小。 程序调用opencv库的resize()函数来对图片放大缩小,默认为0,不改变


    -check_size: 检查所有的数据是否有相同的尺寸。默认为false,不检查


    -encoded: 是否将原图片编码放入最终的数据中,默认为false


    -encode_type: 与前一个参数对应,将图片编码为哪一个格式:‘png','jpg'......


  继续看例1,于是将训练数据转换成lmdb文件命令如下:


    注:由于图片大小不一,因此这里统一转换成256256大小。


    类似的,将测试数据转换成lmdb文件命令如下:


    当然,由于参数比较多,依然可以写脚本(examples/myfile/create_lmdb.sh):


#!/usr/bin/env sh


MY=examples/myfile


echo "Create train lmdb.."


rm -rf $MY/img_train_lmdb


build/tools/convert_imageset \


--shuffle \


--resize_height=256 \


--resize_width=256 \


/home/xxx/caffe/data/re/ \


$MY/train.txt \


$MY/img_train_lmdb


echo "Create test lmdb.."


rm -rf $MY/img_test_lmdb


build/tools/convert_imageset \


--shuffle \


--resize_width=256 \


--resize_height=256 //代码效果参考:http://hnjlyzjd.com/hw/wz_24213.html

\

/home/xxx/caffe/data/re/ \


$MY/test.txt \


$MY/img_test_lmdb


echo "All Done.."


  这里的xxx是你具体的路径。


    运行成功后,会在 examples/myfile下面生成两个文件夹img_train_lmdb和img_test_lmdb,分别用于保存图片转换后的lmdb文件。


  3) 计算均值并保存


  图片减去均值再训练,会提高训练速度和精度。因此,一般都会有这个操作。


  caffe程序提供了一个计算均值的文件compute_image_mean.cpp,我们直接使用就可以了。


  对于例1,命令如下:


1 sudo build/tools/compute_image_mean examples/myfile/img_train_lmdb examples/myfile/mean.binaryproto


  compute_image_mean带两个参数,第一个参数是lmdb训练数据位置,第二个参数设定均值文件的名字及保存路径。


  运行成功后,会在 examples/myfile/ 下面生成一个mean.binaryproto的均值文件。


  4) 创建模型


  在caffe中是通过.prototxt配置文件来定义网络模型。


  例如,可以打开caffe自带的手写数字库MNIST例子的网络结构文件:


    sudo //代码效果参考:http://hnjlyzjd.com/xl/wz_24211.html

vim examples/mnist/lenet_train_test.prototxt

  这个网络模型是非常有名的LeNet模型,网络结构如下图。


  可以看到各个网络层是如何定义的:


    l 数据层(也叫输入层)


layer {


name: "mnist" //表示层名


type: "Data" //表示层的类型


top: "data"


top: "label"


include {


phase: TRAIN //表示仅在训练阶段起作用


}


transform_param {


scale: 0.00390625 //将图像像素值归一化


}


data_param {


source: "examples/mnist/mnist_train_lmdb" //数据来源


batch_size: 64 //训练时每个迭代的输入样本数量


backend: LMDB //数据类型


}


}


   关于数据层及参数的编写,参看学习系列(2):Caffe学习系列(2):数据层及参数


   简单介绍一下其中参数:


    name: 表示该层的名称,可随意取


    type: 层类型,如果是Data,表示数据来源于LevelDB或LMDB。根据数据的来源不同,数据层的类型也不同(后面会详细阐述)。一般在练习的时候,我们都是采 用的LevelDB或LMDB数据,因此层类型设置为Data。


    top或bottom: 每一层用bottom来输入数据,用top来输出数据。如果只有top没有bottom,则此层只有输出,没有输入。反之亦然。如果有多个 top或多个bottom,表示有多个blobs数据的输入和输出。


    data 与 label: 在数据层中,至少有一个命名为data的top。如果有第二个top,一般命名为label。 这种(data,label)配对是分类模型所必需的。


    include: 一般训练的时候和测试的时候,模型的层是不一样的。该层(layer)是属于训练阶段的层,还是属于测试阶段的层,需要用include来指定。如果没有include参数,则表示该层既在训练模型中,又在测试模型中。


    Transformations: 数据的预处理,可以将数据变换到定义的范围内。如设置scale为0.00390625,实际上就是1/255, 即将输入数据由0-255归一化到0-1之间。


  l 视觉层


  视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层。


  关于视觉层及参数的编写,参看:Caffe学习系列(3):视觉层(Vision Layers)及参数


  仍然以mnist为例,


  mnist卷积层定义如下:


layer {


name: "conv1"


type: "Convolution"


bottom: "data" //输入是data


top: "conv1" //输出是卷积特征


param {


lr_mult: 1 //权重参数w的学习率倍数


}


param {


lr_mult: 2 //偏置参数b的学习率倍数


}


convolution_param {


num_output: 20


kernel_size: 5


stride: 1


weight_filler { //权重参数w的初始化方案,使用xavier算法


type: "xavier"


}


bias_filler {


type: "constant" //偏置参数b初始化化为常数,一般为0


}


}


}


  简单介绍一下其中参数:


    层类型:Convolution


    lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。


    在后面的convolution_param中,我们可以设定卷积层的特有参数。


    必须设置的参数:


    num_output: 卷积核(filter)的个数


    kernel_size: 卷积核的大小。如果卷积核的长和宽不等,需要用kernel_h和kernel_w分别设定


    其它参数:


     stride: 卷积核的步长,默认为1。也可以用stride_h和stride_w来设置。


     pad: 扩充边缘,默认为0,不扩充。 扩充的时候是左右、上下对称的,比如卷积核的大小为55,那么pad设置为2,则四个边缘都扩充2个像素,即宽度和高度都扩充了4个像素,这样卷积运算之后的特征图就不会变小。也可以通过pad_h和pad_w来分别设定。


     weight_filler: 权值初始化。 默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian"


     bias_filler: 偏置项的初始化。一般设置为"constant",值全为0。


     bias_term: 是否开启偏置项,默认为true, 开启


     group: 分组,默认为1组。如果大于1,我们限制卷积的连接操作在一个子集内。如果我们根据图像的通道来分组,那么第i个输出分组只能与第i个输入分组进行连接。


    输入:nc0w0h0


    输出:nc1w1h1


    其中,c1就是参数中的num_output,生成的特征图个数


    w1=(w0+2pad-kernel_size)/stride+1;


    h1=(h0+2pad-kernel_size)/stride+1;


    如果设置stride为1,前后两次卷积部分存在重叠。如果设置pad=(kernel_size-1)/2,则运算后,宽度和高度不变。


  mnist的Pooling层,也叫池化层,为了减少运算量和数据维度而设置的一种层。


  LeNet总共有两个,其中一个定义如下:


layer {


name: "pool1"


type: "Pooling"


bottom: "conv1"


top: "pool1"


pooling_param {


pool: MAX


kernel_size: 2


stride: 2


}


}


  层类型:Pooling


  必须设置的参数:


   kernel_size: 池化的核大小。也可以用kernel_h和kernel_w分别设定。


  其它参数:


   pool: 池化方法,默认为MAX。目前可用的方法有MAX, AVE, 或STOCHASTIC


    pad: 和卷积层的pad的一样,进行边缘扩充。默认为0


    stride: 池化的步长,默认为1。一般我们设置为2,即不重叠。也可以用stride_h和stride_w来设置。


  还有Local Response Normalization (LRN)层和im2col层等,在LeNet中没有定义,可以参看AlexNet或GoogLenet等更复杂的模型。


  l 激活层


  关于激活层及参数的编写,参看Caffe学习系列(4):激活层(Activiation Layers)及参数


  在LeNet中,用到的激活函数是ReLU / Rectified-Linear and Leaky-ReLU,


  ReLU是目前使用最多的激活函数,主要因为其收敛更快,并且能保持同样效果。标准的ReLU函数为max(x, 0),当x>0时,输出x; 当x<=0时,输出0。


    f(x)=max(x,0)。


  定义如下:


layer {


name: "relu1"


type: "ReLU"


bottom: "ip1"


top: "ip1"


}


  层类型:ReLU


  可选参数:


    negative_slope:默认为0. 对标准的ReLU函数进行变化,如果设置了这个值,那么数据为负数时,就不再设置为0,而是用原始数据乘以negative_slope。


  RELU层支持in-place计算,这意味着bottom的输出和输入相同以避免内存的消耗。


  l 其他层


  包括:softmax_loss层,Inner Product层,accuracy层,reshape层和dropout层等,参看Caffe学习系列(5):其它常用层及参数,不多说。


  l 关于模型编写的一个总结:


  Caffe学习系列(6):Blob,Layer and Net以及对应配置文件的编写


  一个完整网络例子:


  第一层:name为mnist, type为Data,没有输入(bottom),只有两个输出(top),一个为data,一个为label


  第二层:name为ip,type为InnerProduct, 输入数据data, 输出数据ip


  第三层:name为loss, type为SoftmaxWithLoss,有两个输入,一个为ip,一个为label,有一个输出loss,没有画出来。


  对应的配置文件prototxt就可以这样写:


name: "LogReg"


layer {


name: "mnist"


type: "Data"


top: "data"


top: "label"


data_param {


source: "input_leveldb"


batch_size: 64


}


}


layer {


name: "ip"


type: "InnerProduct"


bottom: "data"


top: "ip"


inner_product_param {


num_output: 2


}


}


layer {


name: "loss"


type: "SoftmaxWithLoss"


bottom: "ip"


bottom: "label"


top: "loss"


}


  5) 编写配置文件


   主要参看Caffe学习系列(7):solver及其配置 和Caffe学习系列(8):solver优化方法


   先看一下mnist中配置文件(一般是..solver.prototxt文件):


1 sudo vim examples/mnist/lenet_solver.prototxt


   配置文件如下:


sudo vim examples/mnist/lenet_solver.prototxt


配置文件如下:


# The train/test net protocol buffer definition


net: "examples/mnist/lenet_train_test.prototxt" //设置深度网络模型,就是介绍的模型。


# test_iter specifies how many forward passes the test should carry out.


# In the case of MNIST, we have test batch size 100 and 100 test iterations,


# covering the full 10,000 testing images.


test_iter: 100 //这个要与test layer中的batch_size结合起来理解。mnist数据中测试样本总数为10000,一次性执行全部数据效率很低,因此我们将测试数据分成几个批次来执行,每个批次的数量就是batch_size。假设我们设置batch_size为100,则需要迭代100次才能将10000个数据全部执行完。因此test_iter设置为100。执行完一次全部数据,称之为一个epoch


# Carry out testing every 500 training iterations.


test_interval: 500 // 测试间隔。也就是每训练500次,才进行一次测试。


# The base learning rate, momentum and the weight decay of the network.


base_lr: 0.01


momentum: 0.9 //上一次梯度更新的权重


weight_decay: 0.0005 <span style="color: rgba(0, 128, 0,

相关文章
|
5月前
|
并行计算 开发者 Python
GitHub标星破千!这份Python并行编程手册,可以封神了!
现在这个时代是并行编程与多核的时代,硬件成本越来越低,如何充分利用硬件所提供的各种资源是每一个软件开发者需要深入思考的问题。若想充分利用所有的计算资源来构建高效的软件系统,并行编程技术是不可或缺的一项技能。
|
6月前
|
TensorFlow 算法框架/工具
【tensorflow】- 知识点补充
【tensorflow】- 知识点补充
|
12月前
|
并行计算 PyTorch 算法框架/工具
关于在安装caffe2环境中遇到的坑整理(欢迎入坑讨论)
关于在安装caffe2环境中遇到的坑整理(欢迎入坑讨论)
|
并行计算 计算机视觉 异构计算
【CUDA学习笔记】第三篇:CUDA C并行化编程【下半部分】(附案例代码下载方式)(二)
【CUDA学习笔记】第三篇:CUDA C并行化编程【下半部分】(附案例代码下载方式)(二)
190 0
【CUDA学习笔记】第三篇:CUDA C并行化编程【下半部分】(附案例代码下载方式)(二)
|
缓存 并行计算 API
【CUDA学习笔记】第三篇:CUDA C并行化编程【下半部分】(附案例代码下载方式)(一)
【CUDA学习笔记】第三篇:CUDA C并行化编程【下半部分】(附案例代码下载方式)(一)
169 0
|
TensorFlow 算法框架/工具 iOS开发
《从零到一:IOS平台TensorFlow入门及应用详解(附源》电子版地址
从零到一:IOS平台TensorFlow入门及应用详解(附源
81 0
《从零到一:IOS平台TensorFlow入门及应用详解(附源》电子版地址
|
TensorFlow 算法框架/工具 iOS开发
《从零到一:IOS平台TensorFlow入门及应用详解(附源码)》电子版地址
从零到一:IOS平台TensorFlow入门及应用详解(附源码)
115 0
《从零到一:IOS平台TensorFlow入门及应用详解(附源码)》电子版地址
|
Python
python做的快手自动评论工具 源码开源
可以自动打开快手 评论
233 0
|
PyTorch 算法框架/工具
pytorch使用方法积累
1. net.parameters()查看网络参数 2. torch.optim.lr_scheduler.MultiStepLR 2.1 学习率的参数配置
93 0
|
机器学习/深度学习 数据挖掘 TensorFlow
TensorFlow学习之旅(一)入门知识记录
TensorFlow学习之旅(一)入门知识记录
158 0
TensorFlow学习之旅(一)入门知识记录