浅度理解caffe

浅度理解caffe


一. caffe 简介

caffe是一个开源的深度学习框架,可读性高,它默认实现了一些现有的通用的网络模型和优化方法,同时允许自由选择CPU或者GPU训练网络,不需要自己编写程序,只需要通过protobuf文件来配置网络以及其参数。相对于TenserFlow来说,caffe在基本功能具备的情况下,速度快,代码精简,层次分明,对于源码的学习和深度学习工作原理比较有利。


二. caffe依赖以及安装

依赖
    caffe
        |-基础库:Boost+Protobuf+hdf5+glog+gflags
        |-BLAS计算库: ATAS/MKL/OpenBLAS
        |-(IO库):lmdb  leveldb(-snappy)
        |-(图片预处理库):Opencv
        |-(GPU支持):CUDA+Cudnn
        |-(GPU多卡):nccl
        |-->(python支持)、(matlab支持)
依赖安装

在有必要的情况,需要将依赖库一个一个编译安装,比较繁琐,但是一般情况下都可以直接通过系统的包管理器直接安装(如debian系的apt-get,等等)参考caffe官网安装指导

编译与安装

caffe可以直接将其当做一个工程,并在其上进行修改或者加入自己的程序代码,通过 make 编译整个工程来进行使用,同时也可以用 make install 将其编译出的库与头文件导出当做程序的依赖库进行使用。编译caffe可以修改 Makefile.config 配置项,直接 make 编译,也可以用cmake工具来进行配置构建工程。 相关操作可以参考caffe官网安装指导


三. caffe源码浅析

caffe目录结构
    caffe
        |-cmake         cmake工程构建文件
        |-data          存放预置的样例训练数据
        |-docs          帮助文档
        |-example       一些样例程序
        |-matlab        matlab接口文件
        |-python        python接口文件
        |-model         一些配置好的网络模型参数
        |-scripts       一些工具脚本
        |-
        |-tools         可执行工具程序的源码
        |-include       caffe的头文件
        |-src           caffe的实现源码
caffe源码结构
    src
      |-gtest           google test的测试库
      |-caffe
            |-test      使用gtest的测试代码
            |-util      调用第三方依赖库的一些工具代码
            |-proto     Protubuf的一些定义
            |-layers    各种layer层实现文件,全部继承Layer类,也可以加入自定义层实现
            |-*.cpp     caffe的核心代码文件
                |blob                   的基本数据结构Blob类
                |common                 Caffe类
                |net                    网络结构类Net
                |solver                 优化方法类Solver
                |layer_factory          层类Layer的工厂类
                |data_transformer       输入数据的基本操作类DataTransformer
                |internal_thread        多线程使用boost::thread库
                |syncedmem              内存管理类CaffeMallocHost,用于同步cpu,gpu数据
caffe基本类描述

Blob: 作为数据传输的媒介,无论是网络权重参数,还是输入数据,都是转化为Blob数据结构来存储。

  1. Blob的类型描述

Caffe内部采用的数据类型主要是对protocol buffer所定义的数据结构的继承,因此可以在尽可能小的内存占用下获得很高的效率,虽然追求性能的同时Caffe也会牺牲了一些代码可读性。直观来说,可以把Blob看成一个有4维的结构体(包含数据和梯度),而实际上,它们只是一维的指针而已,其4维结构通过shape属性得以计算出来。

  1. Blob的重要成员函数和变量

     shared_ptr<SyncedMemory> data_ //数据
     shared_ptr<SyncedMemory> diff_ //梯度
     
     void Blob<Dtype>::Reshape(const int num, const int channels, const int height, const int width) //变形
     inline int count(int start_axis, int end_axis) const //Blob大小
    

Layer: 作为网络的基础单元,神经网络中层与层间的数据节点、前后传递都在该数据结构中被实现,层类种类丰富,比如常用的卷积层、全连接层、pooling层等等,大大地增加了网络的多样性。

  1. Layer的类型描述

Layer是网络模型和计算的核心,在数据存储上,主要分成bottom_vecs、top_vecs、weights&bias三个部分;在数据传递上,也主要分为LayerSetUp、Reshape、Forward、Backward四个过程,符合直观上对层与层之间连接的理解。

  1. Layer的重要成员函数和变量

     vector<Dtype> loss_ //每一层都会有一个loss值,但只有LossLayer才会产生非0的loss
     vector<shared_ptr<Blob<Dtype>>> blobs_ //Layer所学习的参数,包括权值和偏差
    
     virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) //通过bottom Blob对象的形状以及LayerParameter(从prototxt读入)来确定Layer的学习参数(以Blob类型存储)的形状。
    
     virtual void Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) //通过bottom Blob对象的形状以及Layer的学习参数的形状来确定top Blob对象的形状。
    
     virtual void Forward(const vector<Blob<Dtype>*> &bottom, vector<Blob<Dtype>*> *top) = 0  //Layer内部数据正向传播,从bottom到top方向, 重载实现。
    
     virtual void Backward(const vector<Blob<Dtype>*> &top, const vector<bool> &propagate_down, vector<Blob<Dtype>*> *bottom) = 0  //Layer内部梯度反向传播,从top到bottom方向, 重载实现。
    

Net: 作为网络的整体骨架,决定了网络中的层次数目以及各个层的类别等信息。

  1. Net的类型描述

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

  1. Net的重要成员函数和变量

     vector<shared_ptr<Layer<Dtype>>> layers_ //构成该net的layers
     vector<vector<Blob<Dtype>*>> bottom_vecs_ //每一层layer中的bottom Blobs
     vector<vector<Blob<Dtype>*>> top_vecs_ //每一层layer中的top Blobs
     vector<shared_ptr<Blob<Dtype>>> params_ //整个net中的learnable parameter
    
     void Init(const NetParameter& param) //net初始化,简单的来说就是先把网络中所有层的bottom Blobs&top Blobs(无重复)实例化,并从输入层开始,逐层地进行Setup的工作,从而完成了整个网络的搭建,为后面的数据前后传输打下基础。
    
     vector<Blob<Dtype>*>& Forward(const vector<Blob<Dtype>* > & bottom, Dtype* loss = NULL) //前向传播
     void Net<Dtype>::Backward()     //反向传播,计算loss
    

Solver: 作为网络的求解策略,涉及到求解优化问题的策略选择以及参数确定方面,修改这个模块的话一般都会是研究DL的优化求解的方向。

  1. Solver的类型描述

Solver类中包含一个Net的指针,主要是实现了训练模型参数所采用的优化算法,根据优化算法的不同会派生不同的类,而基于这些子类就可以对网络进行正常的训练过程。

  1. Solver的重要成员函数和变量

     shared_ptr<Net<Dtype> > net_ //net对象
    
     void Step(int iters)    //对已初始化后的网络进行固定次数的训练迭代过程。
    
     ComputeUpdateValue();   
     net_->Update();        //不同的模型训练方法通过重载函数 ComputeUpdateValue() 实现 update 参数的核心功能。
    
caffe程序基本调用流程

caffe中caffe.cpp提供了一个用来训练和测试的现有模型的工具,编译之后既/build/tools/caffe, 通过命令和参数进行相关操作(命令:train、test、device_query、time)。下面我们将从该入口描述caffe的整个调用流程:

./build/tools/caffe train --solver lenet_solver.prototxt

  1. 进入程序入口 caffe.cpp main()
  2. caffe.cpp main() 根据参数调用 caffe.cpp train()
  3. caffe.cpp train() 读取xxx.prototxt参数,调用 solver.cpp Solver() 的构造函数创建 Solver 对象
  4. solver.cpp Solver() 调用 solver.cpp Init() 函数来初始化模型的网络
  5. solver.cpp Init() 函数调用 solver.cpp InitTrainNet() 和InitTestNets()函数来分别初始化训练和测试网络
  6. solver.cpp InitTrainNet() 和 InitTestNets() 通过 xxx.prototxt 指定的xxxnet.prototxt 读取net的参数,调用 net.cpp Net() 的构造函数,分别创建训练网络和测试网络
  7. net.cpp Net() 调用 net.cpp Init() 函数,循环->
    • 创建网络中每一个 Layer 对象
    • 调用 layer.cpp Setup()
  8. solver.cpp 创建测试网络,与 InitTrainNet()类似
  9. 运行返回到 caffe.cpp train() 中,利用创建好的 solver 对象调用 solver.cpp Solve() 函数
  10. solver.cpp Solve() 调用 solver.cpp Step() 函数,迭代->
    • 调用 net.cpp ForwardBackward() 来前向以及后向传播
    • 调用 solve.cpp ApplyUpdate() 更新参数
    • 每一定轮次运行 solver.cpp TestAll()
  11. 运行结束

调用图如下

caffe.cpp Solver Net Layer Blob main() 根据命令调用 train() xxx.prototxt Solver() Init() InitTrainNet() / InitTestNets() 初始化 Net() Init() 循环调用初始化层 Layer() 初始化层的bottom和top Blob() 初始化 初始化完成 Setup() 初始化完成 初始化完成 Solve() 循环 Step() ForwardBackward() ApplyUpdate() 达到条件调用 TestAll() Restore() caffe.cpp Solver Net Layer Blob

最后

其实caffe是个很老的深度学习框架了,现阶段对于比较新的网络支持也不是很完善,但是就深度学习入门来说caffe还是很不错的,毕竟网上的相关资料多如牛毛,源码也相对清晰易读,这篇文章其实也是参考了很多别人的资料,因为最近接触caffe,所以记录下来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值