【PyCaffe学习】0.前言及介绍

(声明:下面的内容参考大神的博客撰写http://blog.csdn.net/tostq/article/details/73611437,在原文的基础上进行了部分修改)

0.前言及介绍

Caffe是一个深度学习框架,但是本人感觉使用的时候比较麻烦。现在比较流行的框架有Tensorflow、Keras、Caffe2或者是PyTorch。
Caffe支持三种开发模式:命令行方式,Python接口,Matlab接口。

  1. 命令行:windows下使用bat运行,一般由caffe.exe、prototxt、caffemodel等几部分组成。
  2. Python: Python支持的框架较多,在ML和DL领域支持的package也比较多。
  3. Matlab:可视化效果较好,而且具有交互式调试功能,能够简单的得到每一步的中间结果。
0.1 Caffe平台搭建

准备的环境:

  • VS2013和Caffe源码
  • OpenCV Python版本
  • Anaconda2
  • Pycharm
  • Cuda、Cudnn(没有的话可以使用CPU版本进行运行)
  • Github(推荐使用)

配置过程:http://blog.csdn.net/twt520ly/article/details/79142777

0.2 Caffe的结构和开发流程

安装Pycaffe后,可以import caffe进行查看。通过编译Pycaffe项目所得到Caffe的Python接口包,实际上并不是Caffe的纯Python实现,而将Caffe用Python进行包装,运行中调用的是Caffe的C++代码,但我们仍可以通过Python来查看Caffe网络在运行中的数据。

本节主要介绍Caffe的结构,主要包含了三个部分:Caffe的网络模型结构组成、Caffe的数据结构及Caffe的Python包结构。通过这三个部分的介绍,最后将总结如何用Python进行Caffe的开发。

0.2.1 Caffe的模型结构

对于Caffe深度学习系统中,数据和模型是最核心的两个部分,网络模型结构组成是指构建一个网络模型的要素。通常来说,一个深度学习模型是由三个部分组成:

  • 网络结构配置文件:主要描述网络各层Layer(卷积层、全连接层、池化层等)的配置参数及各层之间的连接结构。这里的层之间的输入输出都Blob数据结构,所以层之间的连接都是Blob数据结构为媒介的,但在网络结构配置文件中并没有描述Blob结构,而只是描述层的配置,因为层的输入输出Blob可以由层layer的配置参数所确定。一般来说,网络结构配置文件在网络运行中是不可修改的,其大体上分为三类:训练网络结构train.prototxt、测试网络结构test.prototxt及实施网络结构deploy.prototxt。其都是以*.prototxt的文件格式存储在磁盘中的。对于深度学习网络来说,一般都会涉及到三种网络配置,训练时网络(train.prototxt)、测试时网络及实施时网络。这三者的不同之处:

 1. 输入数据层不一样,训练时网络用的是训练数据,而测试时网络用的是测试数据,而实施时网络,并没有预先设定数据。
 2. 处理批量不一样,训练时网络的批量batch是一个预先设定的非常重要的超参数,而测试时网络的批量可以在内存范围内任意设置,批量设置越大,总测试时间越少,而实施时网络的批量不重要,一般设为1(即指单次处理一张图)。
 3. 最后的层不一样,训练时网络最后必须有一个损失层,而测试时网络最后要有一个匹配层(判断检测是否正确),而实施时网络直接输出最终结果。
 4. 内部结构可能不一样,许多网络在训练时需要应用特定措施,比如dropout,而往往要在测试时网络和实施时网络中移除这些结构。
  • 网络权重参数文件:该文件用于保存网络各层的权重值,是以*.caffemodel格式存储的文件。而在运行中,其将以Blob数据形式存入内存中。
  • 训练超参数文件:用来控制网络训练及测试阶段的超参数,比如测试网络结构配置文件,梯度下降法中的批量、学习率、遗忘因子等参数,测试的间隔迭代次数等等,其同样是用*.prototxt的文件格式(比如solver.prototxt)

Python使用上述的模型文件调用网络:
1.通过训练超参数文件继续网络训练

import caffe
solver = caffe.SGDSolver('lenet_solver.prototxt')
solver.solve()

2.通过网络权重参数及网络结构配置文件调用网络

net = caffe.Net('deploy.prototxt','*.caffemodel',caffe.TEST)

其中caffemodel是之前训练的网络权重参数,deploy.prototxt是实际使用时候的网络的结构定义。
3.通过训练超参数文件及网络权重参数文件进行权重预设的网络训练:

solver = caffe.SGDSolver('solver.prototxt') #使用超参数文件调用训练器
solver.net.copy_from(caffemodel) #使用先前的model进行网络初始化权重(fine tune)
solver.solver() #训练网络
test_net = solver.test_nets[0]#测试网络
0.2.2 Caffe的数据结构

在Caffe中,用Net结构来表示一个深度神经网络,而一个Net由多个层(layer)拼接而成。每一层的参数以及输入输出都是blob数据结构类型。
1.Blob
Caffe的所有数据(各层的参数以及各层输入输出)都是以Blob数据结构形式存储在内存中的,这与Torch、Theano和Tensorflow的Tensor(张量)是一样的。
Blob实际上表示为4维数组,其维度从低到高分别表示为宽、高、通道数及数量。对于深度网络,一般都是通过梯度下降法训练的,因此在Blob结构中除了包含一个存储数据或者权重值的4维数组外,而需要包含一个存储权重增量(diff)的4维数组。
2.Layer
层(layer)是Caffe的基本运算单元,layer将输入blob(bottom)计算得到输出blob(top),然后这个过程在网络层中一步一步的传递下去,就完成了整个神经网络的过程。
对于层(Layer),其至少会有一个输入Blob或者输出Blob,当然也可以有多个输入或输出Blob。一些层的内部还会有权重值(Weight)和偏置值(Bias)两个Blob结构。
层作为基本计算单元,其主要进行两类运算:前向传播(forward)和后向传播(backward)。在前向传播中,Layer主要是将输入Blob进行某种处理(比如卷积操作)得到输出Blob,而在后向传播中,主要是对输出Blob的diff进行处理得到输入Blob的diff(这也就是损失梯度的反向传播过程),对于需要进行参数更新的层,还会计算权重值Blob及偏置Blob的diff,并用于参数更新(对于批量训练法,会在根据一个批量的累积diff来进行参数更新,而并不是在每次反向传播中都进行参数更新)。
各类层的定义及声明可以参见caffe源码的layer文件夹。
Python获取Layer层信息的过程:

net = caffe.Net('deploy.prototxt','*.caffemodel',caffe.TEST) #初始化网络
conv1_W = net.params['conv1'][0].data #net中的params保存了各层的参数,conv1的权重值
conv1_b = net.params['conv1'][1].data #net中的params保存了各层的参数,conv1的偏置值

3.Net
Net在Caffe中代表一个完整的CNN模型,其由若干Layer所组成,我们可以通过*.prototxt来定义网络Net的结构。
Net中包含了两个部分结构:Layer结构和Blob结构。其中Blob对象主要用于存放每个Layer层的输入及输出的中间结果,而Layer结构即为对Blob对象进行计算处理的层(比如卷积、全连接、池化、softmax等)。注意的是Blob对象和Layer对象可能重名,但两者是完全不一样的。

0.2.3 Caffe Python的结构

我们通过VS2013编译Pycaffe项目会得到一个Caffe的Python包,其位于pycaffe/caffe,我们就caffe文件夹移入到Anaconda2/Lib/site-packages下,就可以使用Caffe的Python接口了。
在Caffe的文件夹下面,需要关注一下几个文件:

  • model_libs.py:主要包含一些生成常用网络模型结构的函数,如带BN的卷积层、ResNet网络主体结构、Inception结构、VGG网络主体结构、带标签的数据层结构等,这些结构都可以由caffe的基础层拼接而成,但并没有Caffe C++源代码所实现。
  • pycaffe.py:该文件定义Caffe的python接口,说明了网络能使用的相关Python函数和数据,比如前向传递forward函数、后向传递backward函数、网络参数params、网络数据blobs、网络名称names等等。
  • io.py:包含blobproto和numpy数组之间转换函数,图像数据的变换函数,以及图像导入导出、预处理的相关函数。
  • coord_map.py:处理一些层(Convolution、Pooling等)的输入输出坐标映射。
  • net_spec.py:网络、层、参数结构的基础性声明
  • _caffe.lib:其是由_caffe.cpp所编译而来的,打开_caffe.cpp,我们可以看出,这个文件主要用于声明caffe结构到Python结构的名称转换。
  • classifier.py:里面有一个分类预测函数
  • detector.py:里面主要是用于目标检测的相关函数
  • draw.py:一些画图命令
0.3查看Caffe的Python接口

Python直接将层类定义转换成一个Python函数,函数名称为类名,函数输入参数,可以打开caffe.proto文件,该文件定义params结构,举个例子比如对于pool层来说,该层类名为PoolingLayer,其层名(其Python函数名)为该类的返回类型(type()函数返回)为Pooling。其输入参数,可以在caffe.proto文件中查找PoolingParameter的定义:

message PoolingParameter {
  enum PoolMethod {
    MAX = 0;
    AVE = 1;
    STOCHASTIC = 2;
  }
  optional PoolMethod pool = 1 [default = MAX]; // The pooling method
  // Pad, kernel size, and stride are all given as a single value for equal
  // dimensions in height and width or as Y, X pairs.
  optional uint32 pad = 4 [default = 0]; // The padding size (equal in Y, X)
  optional uint32 pad_h = 9 [default = 0]; // The padding height
  optional uint32 pad_w = 10 [default = 0]; // The padding width
  optional uint32 kernel_size = 2; // The kernel size (square)
  optional uint32 kernel_h = 5; // The kernel height
  optional uint32 kernel_w = 6; // The kernel width
  optional uint32 stride = 3 [default = 1]; // The stride (equal in Y, X)
  optional uint32 stride_h = 7; // The stride height
  optional uint32 stride_w = 8; // The stride width
  enum Engine {
    DEFAULT = 0;
    CAFFE = 1;
    CUDNN = 2;
  }
  optional Engine engine = 11 [default = DEFAULT];
  // If global_pooling then it will pool over the size of the bottom by doing
  // kernel_h = bottom->height and kernel_w = bottom->width
  optional bool global_pooling = 12 [default = false];
}

pooling层的调用方式如下:

from caffe import layers as L
L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride, pad = pad)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值