Caffe学习笔记

1. 简介 

    1)官方教材
    2)Hacker's guide to Neural Networks(计算梯度实例)
    3)Convolution in Caffe: a memo    
    4)Caffe上手教程 

    5)Layer的详细定义  

    6)DIY Deep Learning for Vision: a Hands-On Tutorial with Caffe

    7)Caffe-Android-Lib   Caffe-android-demo

    8)OpenCL Caffe  

    9)Model Zoo

    10)DAG:Directed Acyclic Graph
    11)   


Caffe学习系列(10):命令行解析

如何用caffe解决回归问题?

【深度学习】caffe中那些layers

Caffe 中的卷积的计算过程



1.1 Caffe代码层次

    1)Blob:是基础的数据结构,是用来保存学习到的参数以及网络传输过程中产生数据的类。
    2)Layer:是网络的基本单元,由此派生出了各种层类。修改这部分的人主要是研究特征表达方向的。
    3)Net:是网络的搭建,将Layer所派生出层类组合成网络。
    4)Solver:是Net的求解,修改这部分人主要会是研究DL求解方向的。   

1.2 Blob

    数据及其导数以blobs的形式在层间流动。
   Blob是用以存储数据的4维数组,例如
      1) 对于数据:Number*Channel*Height*Width
      2) 对于卷积权重:Output*Input*Height*Width
      3) 对于卷积偏置:Output*1*1*1
     Caffe支持CUDA,在数据级别上也做了一些优化,这部分最重要的是知道它主要是对protocol buffer所定义的数据结构的继承,Caffe也因此可以在尽可能小的内存占用下获得很高的效率。(追求性能的同时Caffe也牺牲了一些代码可读性)
    在更高一级的Layer中Blob用下面的形式表示学习到的参数:
        vector<shared_ptr<Blob<Dtype> > > blobs_;
    这里使用的是一个Blob的容器是因为某些Layer包含多组学习参数,比如多个卷积核的卷积层。
    以及Layer所传递的数据形式,后面还会涉及到这里:
        vector<Blob<Dtype>*> &bottom;

        vector<Blob<Dtype>*> *top;


1.3 Layer

    Caffe层的定义由2部分组成:层属性与层参数,例如

name:"conv1"
type:CONVOLUTION
bottom:"data"
top:"conv1"
convolution_param{
    num_output:20
    kernel_size:5
    stride:1
    weight_filler{
        type: "xavier"
    }
}


    前面4项为层属性,后面的为层参数。

1.3.1 Layer主要派生类型

    Caffe十分强调网络的层次性,也就是说卷积操作,非线性变换(ReLU等),Pooling,权值连接等全部都由某一种Layer来表示。具体来说分为5大类Layer:
    1)NeuronLayer类:
         定义于neuron_layers.hpp中,其派生类主要是元素级别的运算(比如Dropout运算,激活函数ReLu,Sigmoid等),运算均为同址计算(in-place computation,返回值覆盖原值而占用新的内存)。
    2)LossLayer类:
         定义于loss_layers.hpp中,其派生类会产生loss,只有这些层能够产生loss。
    3)数据层:
         定义于data_layer.hpp中,作为网络的最底层,主要实现数据格式的转换。
    4)特征表达层:
          定义于vision_layers.hpp(为什么叫vision这个名字,我目前还不清楚),实现特征表达功能,更具体地说包含卷积操作,Pooling操作,他们基本都会产生新的内存占用(Pooling相对较小)。
    5)网络连接层和激活函数:
         定义于common_layers.hpp,Caffe提供了单个层与多个层的连接,并在这个头文件中声明。这里还包括了常用的全连接层InnerProductLayer类。

1.3.2 Layer的重要成员函数

    在Layer内部,数据主要有两种传递方式,正向传导(Forward)和反向传导(Backward)。Forward和Backward有CPU和GPU(部分有)两种实现。Caffe中所有的Layer都要用这两种方法传递数据。

    virtual void Forward(const vector<Blob<Dtype>*> &bottom,                     
                               vector<Blob<Dtype>*> *top) = 0;
    virtual void Backward(const vector<Blob<Dtype>*> &top,
                          const vector<bool> &propagate_down, 
                                vector<Blob<Dtype>*> *bottom) = 0;

    Layer类派生出来的层类通过这实现这两个虚函数,产生了各式各样功能的层类。Forward是根据bottom计算top的过程,Backward则相反(根据top计算bottom)。注意这里为什么用了一个包含Blob的容器(vector),对于大多数Layer来说输入和输出都各连接只有一个Layer,然而对于某些Layer存在一对多的情况,比如LossLayer和某些连接层。在网路结构定义文件(*.proto)中每一层的参数bottom和top数目就决定了vector中元素数目。
    layers {
        bottom: "decode1neuron"   // 该层底下连接的第一个Layer
        bottom: "flatdata"        // 该层底下连接的第二个Layer
        top: "l2_error"           // 该层顶上连接的一个Layer
        name: "loss"              // 该层的名字
        type: EUCLIDEAN_LOSS      // 该层的类型
        loss_weight: 0
    }

1.3.3  Layer的重要成员变量

  /** The vector that indicates whether each top blob has a non-zero weight in
   *  the objective function. */
  vector<Dtype> loss_;
    每一层又有一个loss_值,只不过大多数Layer都是0,只有LossLayer才可能产生非0的loss_。计算loss是会把所有层的loss_相加。


  /** The vector that stores the learnable parameters as a set of blobs. */
  vector<shared_ptr<Blob<Dtype> > > blobs_;
    前面提到过的,Layer学习到的参数。

1.4 Net

    

    Net用容器的形式将多个Layer有序地放在一起,其自身实现的功能主要是对逐层Layer进行初始化,以及提供Update( )的接口(更新网络参数),本身不能对参数进行有效地学习过程。

  /// @brief Individual layers in the net
  vector<shared_ptr<Layer<Dtype> > > layers_;

    同样Net也有它自己的Forward和Backward函数:

  /**
   * @brief Run Forward and return the result.
   *
   */
  const vector<Blob<Dtype>*>& Forward(Dtype* loss = NULL);

  /**
   * The network backward should take no input and output, since it solely
   * computes the gradient w.r.t the parameters, and the data has already been
   * provided during the forward pass.
   */
  void Backward();

    他们是对整个网络的前向和反向传导,各调用一次就可以计算出网络的loss了。

1.5 Solver

    这个类中包含一个Net的指针,主要实现了训练模型参数所采用的优化算法,它所派生的类就可以对整个网络进行训练了。

  shared_ptr<Net<Dtype> > net_;

    不同的模型训练方法通过重载函数ComputeUpdateValue( )实现计算update参数的核心功能:

    

  virtual void ComputeUpdateValue(int param_id, Dtype rate);

    最后当进行整个网络训练过程(也就是你运行Caffe训练某个模型)的时候,实际上是在运行caffe.cpp中的train( )函数,而这个函数实际上是实例化一个Solver对象,初始化后调用了Solver中的Solve( )方法。而这个Solve( )函数主要就是在迭代运行下面这两个函数,就是刚才介绍的哪几个函数。

  ComputeUpdateValue();
  net_->Update();

    


1.6 Loss

    

2. Caffe使用第三方工具

    1)Caffe生成的数据分为2种格式:Lmdb和Leveldb
    它们都是键/值对(Key/Value Pair)嵌入式数据库管理系统编程库。虽然lmdb的内存消耗是leveldb的1.1倍,但是lmdb的速度比leveldb快10%至15%,更重要的是lmdb允许多种训练模型同时读取同一组数据集。因此lmdb取代了leveldb成为Caffe默认的数据集生成格式。
    2)Google Logging library (Glog): 一个C++语言的应用级日志记录框架,提供了C++风格的流操作和各种助手宏.
    3)CBLAS library(CPU版本的矩阵操作)
    4)CUBLAS library (GPU 版本的矩阵操作)

3. Caffe架构

    

  1. 预处理图像的leveldb构建
    输入:一批图像和label (2和3)
    输出:leveldb (4)
    指令里包含如下信息:
    • conver_imageset (构建leveldb的可运行程序)
    • train/ (此目录放处理的jpg或者其他格式的图像)
    • label.txt (图像文件名及其label信息)
    • 输出的leveldb文件夹的名字
    • CPU/GPU (指定是在cpu上还是在gpu上运行code)
  2. CNN网络配置文件

    • Imagenet_solver.prototxt (包含全局参数的配置的文件)
    • Imagenet.prototxt (包含训练网络的配置的文件)
    • Imagenet_val.prototxt (包含测试网络的配置文件)

4. Caffe训练步骤

使用 Caffe 训练的一般步骤就是:

  • 数据预处理;
  • 模型定义;
  • 求解策略定义;
  • 运行。

4.1 数据流程



5. 前向传播(Forward)

    1)从高层次到低层次的调用Forward函数:Solver->Net->Layer->Specific Layer (Convolution等...)
    2)核心函数:
          - forward_cpu()
          - forward_gpu() 

6. 反向传播(Backpropagation)

    1)误差顺着Chain Rule法则回流到前面的层
    2)核心函数:
          - backward_cpu()
          - backward_gpu()










  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值