码迷,mamicode.com
首页 > 其他好文 > 详细

caffe源码深入学习

时间:2020-10-07 21:44:58      阅读:42      评论:0      收藏:0      [点我收藏+]

标签:relative   clear   diff   mutex   灵活   original   文章   探索   nts   

 

 

Google:inline Forward Caffe

 


 

作者:jiongnima

这个作者很懒,什么都没留下…
  • 原创 干货!caffe源码深入学习9:caffe框架神经网络反传代码解析(三)之contrastive_loss_layer源码解析

    本篇博客是Caffe深度学习梯度反传代码解析的第3篇。从本篇博客开始,在对Caffe框架中的反传代码进行解析时,笔者将解析更复杂的实现代码,比如包含可训练参数的层与复杂求导过程的层。本片博客解析了对比损失层,即contrastive_loss_layer,对比损失是在人脸验证,图像检索中使用的非常广泛的一个层。希望给大家带来收获,欢迎阅读与分享!
    2019-10-13 14:57:11 技术图片283 技术图片0
  • 原创 caffe初探4:对训练得到的模型进行测试

    续caffe初探1,2,3,在我们训练出自己的模型之后,就可以测试,或者说使用我们的模型来分类了,在我们使用网络模型对单张图片进行分类测试之前笔者还是列出测试所需物资清单: 兹测试所需物资清单如下: (1)类名文件,未准备。标定分类名称的txt文件。 (2)测试图片,未准备。准备若干张供网络模型分类的图片。 (3)后缀名称为.caffemodel的网络模型文件,已准备。笔者
    2016-09-27 16:23:53 技术图片15328 技术图片8
  • 原创 tensorflow2caffe(2) : 如何在tensorflow中取出模型参数

    本文是tensorflow2caffe的第二步,讲述了如何从tensorflow中提取出训练参数,分享给大家~
    2017-10-24 10:12:22 技术图片7065 技术图片7
  • 原创 tensorflow2caffe(3) : 如何将tensorflow框架下训练得到的权重转化为caffe框架下的权重参数

       在前两期专栏tensorflow2caffe(1)和tensorflow2caffe(2)中,笔者向大家介绍了caffemodel文件类型下的参数架构和如何取出tensorflow框架下训练参数。在本期中,笔者将向大家阐述,如何去将tensorflow框架下训练得到的参数转化为caffe框架下的规定格式的参数。首先,我们来捋一捋目前我们手里面已经有了哪些东西: 1. 我们有自己的tenso...
    2017-10-29 09:50:25 技术图片10874 技术图片61
  • 原创 tensorflow2caffe(1) : caffemodel解析,caffemodel里面到底记录了什么?

    本系列开始介绍如何进行tensorflow到caffe的框架转换。由于目前介绍从tensorflow里面取出训练参数的文章比较多,可是解析caffe框架下生成的模型参数的文章比较少,本文讲解了如何可视化生成的caffemodel。
    2017-06-07 22:14:24 技术图片19837 技术图片31
  • 原创 tensorflow2caffe(4) : caffemodel的生成与tensorflow2caffe框架转换的总结

    本篇是tensorflow2caffe模型转换的最终章,描述了如何生成caffemodel和对tensorflow2caffe模型转换的一些总结,欢迎阅读与分享~
    2017-11-03 14:43:39 技术图片5278 技术图片24
  • 原创 FCN训练不收敛的原因分析和最详细的FCN训练与测试自己的数据程序配置

    本文分析了FCN训练不收敛的原因并给出了解决方案。 同时给出了详尽的完善的FCN训练与测试程序配置,欢迎阅读与分享。
    2017-11-16 11:31:10 技术图片16055 技术图片172
  • 原创 详细的Faster R-CNN源码解析之ROI-Pooling逐行代码解析

       在笔者的上一篇博客中,解析了Faster R-CNN中的RPN代码,在本篇博客中,笔者详细地解析一下ROI-Pooling代码。为大家讲解2015年Fast R-CNN的核心贡献(ROI Pooling被Faster R-CNN沿用)ROI Pooling的实现原理。(笔者其实一年半之前就看过这个代码,只是当时没有写到博客上,感慨.jpg)   在代码解析正式开始之前,笔者声明几点:1. 本...
    2018-04-20 19:45:56 技术图片10429 技术图片12
  • 原创 重启caffe源码深入学习7:caffe框架深度神经网络反传代码解析(一)之ReLU层源码解析

    近年来,TensorFlow和PyTorch等安装简洁,使用灵活,不需要构造反传代码的深度学习框架越来越多地走进了深度学习研究者的视野,为大家提供了很多便捷。不过同时,也造就了很多**调包侠**,调包侠们既编程能力有限,也不明了底层原理,仅仅知道调包解决问题,脱离深度学习框架之后无法解决深层次的深度学习问题。因此,笔者重重启caffe源码解析博客,为大家分享深度学习底层实现相关干货!
    2019-10-03 23:53:51 技术图片293 技术图片0
  • 原创 caffe源码深入学习4:支持魔改的layer:layer.hpp与layer.cpp

    到caffe源码深入学习3为止,我们解析了caffe底层的数据相关代码,了解了caffe这个深度学习框架中数据的存储与流通实现细节,那么,从本篇博客开始,笔者将开始解析更高层的代码,首先解析的是caffe中构成深度神经网络的网络层layer,在使用caffe架构的程序员眼中,各种layer就像一块一块的积木一般,可以通过搭建,拼接成各种各样好看的玩具城堡,同时,这些积木本身还支持各种魔改,在...
    2017-02-20 21:26:08 技术图片1595 技术图片1
  • 原创 caffe源码深入学习8:caffe框架深度神经网络反传代码解析(二)之pooling层源码解析

    caffe源码深入学习8:caffe框架深度神经网络反传代码解析(二)之pooling层源码解析写在前面池化层源码及注释池化层源码解析最大池化平均池化 写在前面 在上一篇博客,即重启caffe源码深入学习7中,笔者从最简单的激活层开始,进行了caffe源码的解析,尤其讲述了梯度反传的部分。在本篇博客中,笔者将解析另一个基础层的源码,即池化层,池化层与激活层类似,其中不包含任何可训练参数。caffe...
    2019-10-07 21:23:22 技术图片766 技术图片0
  • 原创 在c++程序中调用caffe训练完毕的模型进行分类

    本文讲述了如何在c++程序中调用caffe训练好的模型进行分类,并使用cmake编译分类文件。同时附上classification.cpp解析
    2017-04-16 20:39:43 技术图片22173 技术图片47
  • 原创 caffe工程化实例:将caffe分类程序编译成.so文件并在程序中调用

    在上一篇博客中,笔者提到了对caffe分类程序的工程化,那么本篇博客笔者就来实践一下对caffe分类的工程化。    首先进行一下需求分析:在工程中,往往是用一张图片作为输入,并返回该输入图片的分类结果,也就是说,需要把分类程序放在一个.so链接库中,并在主函数中调用该链接库。    请各位读者朋友们注意,笔者在进行实验时,还是引用了上一篇博客中提到的检测图片中是否包含岔路口的模型,因此请对实
    2017-04-16 23:18:12 技术图片9729 技术图片31
  • 原创 nvidia jetson TX2配置caffe

    本文阐述了nvidia jetson TX2配置caffe的过程
    2017-04-10 23:54:37 技术图片24711 技术图片36
  • 原创 caffe初探3:结合数据集与设计的网络模型进行训练

    续caffe初探1和caffe初探2,回首一下,此时已经有一些收获了呢,已经生成了数据集,并准备了均值文件还有网络结构文件,现在就可以进行模型的训练了。首先,我们来清点一下训练所需要的物资清单吧。 兹训练物资清单如下: (1)数据集                   准备完毕,分别是./caffe/forkrecognition/train_lmdb和./caffe/forkreco
    2016-09-27 10:26:20 技术图片3873 技术图片3
  • 原创 caffe初探2:有关网络设计的探索

    续caffe初探1大笑大笑大笑有兴趣的朋友可以关注笔者的博客,笔者作为一个初涉深度学习领域和caffe的rookie,很高兴同大家一起学习和探讨,对于本人博客中的谬误与疏漏,笔者诚恳地期待各位读者朋友们的指点与建议。 在caffe初探1中,笔者提到了如何制作自己的数据集,那么在此文中,笔者将讲解如何撰写网络架构。众所周知,在卷及神经网络中,网络架构是最重要的一部分,网络的构造与模型效果的
    2016-09-27 10:18:01 技术图片4067 技术图片4
  • 原创 caffe初探1:生成自己的数据集

    之前的博文转载过如何配置caffe,在配置好caffe之后呢,我们就可以利用caffe结合自己设计的网络与制作的数据集来训练模型并且测试了。可是,一口吃一个胖子是很愚蠢的,笔者希望通过若干个系列的博客告诉大家如何一步一步地训练出自己的模型并测试。这若干个系列的博客笔者打算这样安排: (1)数据的准备与训练数据集生成 (2)有关caffe网络设计的探索 (3)结合数据集
    2016-09-26 20:07:48 技术图片8411 技术图片15
  • 原创 caffe源码深入学习3:更底层的数据信息存取与交换代码:syncedmem.hpp和syncedmem.cpp

    还记得在上一期博客中,当我们解析Blob类相关时,遇到一些成员函数如Update(),cpu_data(),mutable_gpu_data()等等,这些函数在完成对应功能的同时,调用了更多底层的函数,这些函数与Blob中的函数同名,如cpu_data(),gpu_data(),mutable_cpu_data(),mutable_gpu_data()等,在上一篇博客中的代码注释部分我们提到,这些
    2017-02-19 09:53:33 技术图片1440 技术图片0
  • 原创 caffe源码深入学习1:caffe.cpp解析

    距离笔者接触深度学习已经将近半年了,在这段时间中,笔者最先接触的是lenet网络,然后就学习了2015-2016年非常火爆的fast-rcnn与faster-rcnn,到最近自己利用深度学习搞事情,笔者的最大感受是,经过一些例子的实践,已经对深度学习有了大概的了解,但是离熟练上手还有很可观的距离,这时,笔者不由得想起来一句老话:read the fxxx source code。因此,笔者开始学习
    2017-02-13 20:20:35 技术图片8106 技术图片5
  • 原创 caffe卷积层延伸:卷积核膨胀详细解析

    在笔者的上一篇博客中,解析caffe的卷积层时,在conv_layer.cpp中有一个卷积核膨胀操作,在conv_layer.cpp的第17行有如下代码 const int kernel_extent = dilation_data[i] * (kernel_shape_data[i] - 1) + 1;    上面的代码描述了卷积核的膨胀操作,我们不妨来做个假设,卷积核为3*3的,膨胀系数为
    2017-04-06 22:33:09 技术图片15302 技术图片7
  • 原创 caffe源码深入学习5:超级详细的caffe卷积层代码解析

    caffe实现的卷积层是一个功能强大完整,同时也是一个相对复杂的层,涉及conv_layer.hpp,conv_layer.cpp,base_conv_layer.hpp和base_conv_layer.cpp,请读者朋友们仔细欣赏~
    2017-04-04 11:00:53 技术图片12494 技术图片15
  • 原创 caffe源码深入学习2:blob.hpp+blob.cpp

    在caffe源码深入学习1中我们提到了caffe.cpp文件调用用户定义的solver.prototxt文件进行网络的训练,其中,网络训练的接口是train()函数,而在train()函数中,使用了Solve()这个函数接口去求解网络参数,那么,找逻辑来说,接下来该解析solver.cpp文件,可是,事情并没有想象那么简单!如果打开solver.cpp文件,你会发现里面调用了Net相关的东西,这个
    2017-02-15 21:14:15 技术图片2407 技术图片1
  • 原创 实用:使用caffe训练模型时solver.prototxt中的参数设置解析

    笔者之前发布了关于解析caffe的层的博客,解析caffe常用层的博客正在不断更新中。本篇博客是一个插播的博客,目的在彻底解决使用caffe训练模型时的参数设置问题,为什么要发这篇博客呢?是因为笔者最近在自定义网络时,需要构造自己的solver.prototxt,由于之前使用别人的网络时,很多设置参数都没有变,举个例子,下面是caffe官方例程中关于训练LeNet的配置参数文件: # The t
    2017-03-31 19:50:26 技术图片9704 技术图片2
  • 原创 caffe源码深入学习6:超级详细的im2col绘图解析,分析caffe卷积操作的底层实现

    在本篇博客中,笔者通过绘图,详细解析了caffe中im2col的实现,分析了卷积的底层实现原理。
    2017-04-08 19:26:00 技术图片17552 技术图片28
  • 转载 Ubuntu14.04配置caffe

    前段时间接到任务需要配置caffe并在上面训练神经网络相关,对caffe与深度学习一窍不通的我有幸得到了xizero00师兄的指导并在Ubuntu 14.04上面配置了caffe,亲测可用,以下是师兄写的博文正文: 网上充斥各种安装方法,但是都很繁琐,特别是安装显卡驱动以及依赖项,对于初学者不是很方便。我觉得采用包管理工具更方便因此写下本文。 (1)首先安装ssh,这样
    2016-09-26 16:41:47 技术图片1051 技术图片0

 

 

 


 

 

 

caffe源码深入学习4:支持魔改的layer:layer.hpp与layer.cpp

   到caffe源码深入学习3为止,我们解析了caffe底层的数据相关代码,了解了caffe这个深度学习框架中数据的存储与流通实现细节,那么,从本篇博客开始,笔者将开始解析更高层的代码,首先解析的是caffe中构成深度神经网络的网络层layer,在使用caffe架构的程序员眼中,各种layer就像一块一块的积木一般,可以通过搭建,拼接成各种各样好看的玩具城堡,同时,这些积木本身还支持各种魔改,在一个创造性强的深度学习玩家手里,各种魔改的layer搭配起来,可以解决各式各样的深度学习问题。

   尽管各种魔改成果让大家眼花缭乱,可是别忘了,任何魔改积木都是从一块原木开始的,我们就先从这一块原木下手,下面按照惯例先放注释的源码。

   首先是对layer.hpp的代码

 

  1.  
    #ifndef CAFFE_LAYER_H_
  2.  
    #define CAFFE_LAYER_H_
  3.  
     
  4.  
     
  5.  
    #include <algorithm>
  6.  
    #include <string>
  7.  
    #include <vector>
  8.  
     
  9.  
     
  10.  
    #include "caffe/blob.hpp"
  11.  
    #include "caffe/common.hpp"
  12.  
    #include "caffe/layer_factory.hpp"
  13.  
    #include "caffe/proto/caffe.pb.h"
  14.  
    #include "caffe/util/math_functions.hpp"
  15.  
     
  16.  
     
  17.  
    /**
  18.  
    Forward declare boost::thread instead of including boost/thread.hpp
  19.  
    to avoid a boost/NVCC issues (#1009, #1010) on OSX.
  20.  
    */
  21.  
    /*网络计算过程中的一些互斥量*/
  22.  
    namespace boost { class mutex; }
  23.  
     
  24.  
     
  25.  
    namespace caffe {
  26.  
     
  27.  
     
  28.  
    /**
  29.  
    * @brief An interface for the units of computation which can be composed into a
  30.  
    * Net.
  31.  
    *
  32.  
    * Layer%s must implement a Forward function, in which they take their input
  33.  
    * (bottom) Blob%s (if any) and compute their output Blob%s (if any).
  34.  
    * They may also implement a Backward function, in which they compute the error
  35.  
    * gradients with respect to their input Blob%s, given the error gradients with
  36.  
    * their output Blob%s.
  37.  
    */
  38.  
    template <typename Dtype>
  39.  
    class Layer {
  40.  
    public:
  41.  
    /**
  42.  
    * You should not implement your own constructor. Any set up code should go
  43.  
    * to SetUp(), where the dimensions of the bottom blobs are provided to the
  44.  
    * layer.
  45.  
    */
  46.  
    /*Layer类的构造函数,这个构造函数在用户自定义Layer的时候是不需要去修改的,该构造函数的作用主要是
  47.  
    对该层的模式做出初始化,是用于训练还是测试,并且在初始的时候层的参数是在Proto中的,在这里把它读到blobs_中*/
  48.  
    explicit Layer(const LayerParameter& param)
  49.  
    : layer_param_(param), is_shared_(false) {
  50.  
    // Set phase and copy blobs (if there are any).
  51.  
    phase_ = param.phase();
  52.  
    if (layer_param_.blobs_size() > 0) {//如果在层定义文件中有blob参数,则在这里初始化
  53.  
    blobs_.resize(layer_param_.blobs_size());
  54.  
    for (int i = 0; i < layer_param_.blobs_size(); ++i) {
  55.  
    blobs_[i].reset(new Blob<Dtype>());
  56.  
    blobs_[i]->FromProto(layer_param_.blobs(i));
  57.  
    }
  58.  
    }
  59.  
    }
  60.  
    virtual ~Layer() {}
  61.  
     
  62.  
     
  63.  
    /**
  64.  
    * @brief Implements common layer setup functionality.
  65.  
    *
  66.  
    * @param bottom the preshaped input blobs
  67.  
    * @param top
  68.  
    * the allocated but unshaped output blobs, to be shaped by Reshape
  69.  
    *
  70.  
    * Checks that the number of bottom and top blobs is correct.
  71.  
    * Calls LayerSetUp to do special layer setup for individual layer types,
  72.  
    * followed by Reshape to set up sizes of top blobs and internal buffers.
  73.  
    * Sets up the loss weight multiplier blobs for any non-zero loss weights.
  74.  
    * This method may not be overridden.
  75.  
    */
  76.  
    void SetUp(const vector<Blob<Dtype>*>& bottom,
  77.  
    const vector<Blob<Dtype>*>& top) {
  78.  
    InitMutex();//对前向传播时的互斥量进行初始化
  79.  
    CheckBlobCounts(bottom, top);//检查网络传播时底层与顶层的blob形状是否规则
  80.  
    LayerSetUp(bottom, top);//一个非常重要的层初始化函数,往往在该函数中会进行一些对于层定义文件中的参数的读取
  81.  
    Reshape(bottom, top);//一个非常重要的对于层输入输出blob的初始化函数
  82.  
    SetLossWeights(top);//这个函数对输出blob设置loss的权重
  83.  
    }
  84.  
     
  85.  
     
  86.  
    /**
  87.  
    * @brief Does layer-specific setup: your layer should implement this function
  88.  
    * as well as Reshape.
  89.  
    *
  90.  
    * @param bottom
  91.  
    * the preshaped input blobs, whose data fields store the input data for
  92.  
    * this layer
  93.  
    * @param top
  94.  
    * the allocated but unshaped output blobs
  95.  
    *
  96.  
    * This method should do one-time layer specific setup. This includes reading
  97.  
    * and processing relevent parameters from the <code>layer_param_</code>.
  98.  
    * Setting up the shapes of top blobs and internal buffers should be done in
  99.  
    * <code>Reshape</code>, which will be called before the forward pass to
  100.  
    * adjust the top blob sizes.
  101.  
    */
  102.  
    /*LayerSetUp中往往会读取层定义文件中的一些参数*/
  103.  
    virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
  104.  
    const vector<Blob<Dtype>*>& top) {}
  105.  
     
  106.  
     
  107.  
    /**
  108.  
    * @brief Whether a layer should be shared by multiple nets during data
  109.  
    * parallelism. By default, all layers except for data layers should
  110.  
    * not be shared. data layers should be shared to ensure each worker
  111.  
    * solver access data sequentially during data parallelism.
  112.  
    */
  113.  
    /*设置层能否被多个网络共享,只有数据层才允许被其他网络共享*/
  114.  
    virtual inline bool ShareInParallel() const { return false; }
  115.  
     
  116.  
     
  117.  
    /** @brief Return whether this layer is actually shared by other nets.
  118.  
    * If ShareInParallel() is true and using more than one GPU and the
  119.  
    * net has TRAIN phase, then this function is expected return true.
  120.  
    */
  121.  
    /*在上面的函数起作用的时候,并且只是在使用多gpu训练的时候,本函数返回为true,指示该数据层被其他网络共享*/
  122.  
    inline bool IsShared() const { return is_shared_; }
  123.  
     
  124.  
     
  125.  
    /** @brief Set whether this layer is actually shared by other nets
  126.  
    * If ShareInParallel() is true and using more than one GPU and the
  127.  
    * net has TRAIN phase, then is_shared should be set true.
  128.  
    */
  129.  
    /*检验层共享条件是否成立,如果不成立,那么不允许共享*/
  130.  
    inline void SetShared(bool is_shared) {
  131.  
    CHECK(ShareInParallel() || !is_shared)
  132.  
    << type() << "Layer does not support sharing.";
  133.  
    is_shared_ = is_shared;
  134.  
    }
  135.  
     
  136.  
     
  137.  
    /**
  138.  
    * @brief Adjust the shapes of top blobs and internal buffers to accommodate
  139.  
    * the shapes of the bottom blobs.
  140.  
    *
  141.  
    * @param bottom the input blobs, with the requested input shapes
  142.  
    * @param top the top blobs, which should be reshaped as needed
  143.  
    *
  144.  
    * This method should reshape top blobs as needed according to the shapes
  145.  
    * of the bottom (input) blobs, as well as reshaping any internal buffers
  146.  
    * and making any other necessary adjustments so that the layer can
  147.  
    * accommodate the bottom blobs.
  148.  
    */
  149.  
    /*一个非常重要,并且必须实现的函数,resape函数主要是协定了层输入输出的blob大小*/
  150.  
    virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
  151.  
    const vector<Blob<Dtype>*>& top) = 0;
  152.  
     
  153.  
     
  154.  
    /**
  155.  
    * @brief Given the bottom blobs, compute the top blobs and the loss.
  156.  
    *
  157.  
    * @param bottom
  158.  
    * the input blobs, whose data fields store the input data for this layer
  159.  
    * @param top
  160.  
    * the preshaped output blobs, whose data fields will store this layers‘
  161.  
    * outputs
  162.  
    * \return The total loss from the layer.
  163.  
    *
  164.  
    * The Forward wrapper calls the relevant device wrapper function
  165.  
    * (Forward_cpu or Forward_gpu) to compute the top blob values given the
  166.  
    * bottom blobs. If the layer has any non-zero loss_weights, the wrapper
  167.  
    * then computes and returns the loss.
  168.  
    *
  169.  
    * Your layer should implement Forward_cpu and (optionally) Forward_gpu.
  170.  
    */
  171.  
    /*Forward函数实现了层的前向传播,具体实现见下方*/
  172.  
    inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
  173.  
    const vector<Blob<Dtype>*>& top);
  174.  
     
  175.  
     
  176.  
    /**
  177.  
    * @brief Given the top blob error gradients, compute the bottom blob error
  178.  
    * gradients.
  179.  
    *
  180.  
    * @param top
  181.  
    * the output blobs, whose diff fields store the gradient of the error
  182.  
    * with respect to themselves
  183.  
    * @param propagate_down
  184.  
    * a vector with equal length to bottom, with each index indicating
  185.  
    * whether to propagate the error gradients down to the bottom blob at
  186.  
    * the corresponding index
  187.  
    * @param bottom
  188.  
    * the input blobs, whose diff fields will store the gradient of the error
  189.  
    * with respect to themselves after Backward is run
  190.  
    *
  191.  
    * The Backward wrapper calls the relevant device wrapper function
  192.  
    * (Backward_cpu or Backward_gpu) to compute the bottom blob diffs given the
  193.  
    * top blob diffs.
  194.  
    *
  195.  
    * Your layer should implement Backward_cpu and (optionally) Backward_gpu.
  196.  
    */
  197.  
    /*Backward函数实现了层的后向传播,具体实现见下方*/
  198.  
    inline void Backward(const vector<Blob<Dtype>*>& top,
  199.  
    const vector<bool>& propagate_down,
  200.  
    const vector<Blob<Dtype>*>& bottom);
  201.  
     
  202.  
     
  203.  
    /**
  204.  
    * @brief Returns the vector of learnable parameter blobs.
  205.  
    */
  206.  
    /*这里返回的是指向blob的指针容器blobs_,该容器在存储层参数的blob与proto交换时起作用*/
  207.  
    vector<shared_ptr<Blob<Dtype> > >& blobs() {
  208.  
    return blobs_;
  209.  
    }
  210.  
     
  211.  
     
  212.  
    /**
  213.  
    * @brief Returns the layer parameter.
  214.  
    */
  215.  
    /*该函数返回prototxt文件定义的网络参数*/
  216.  
    const LayerParameter& layer_param() const { return layer_param_; }
  217.  
     
  218.  
     
  219.  
    /**
  220.  
    * @brief Writes the layer parameter to a protocol buffer
  221.  
    */
  222.  
    /*ToProto函数将网络定义的参数存放进Proto*/
  223.  
    virtual void ToProto(LayerParameter* param, bool write_diff = false);
  224.  
     
  225.  
     
  226.  
    /**
  227.  
    * @brief Returns the scalar loss associated with a top blob at a given index.
  228.  
    */
  229.  
    /**/
  230.  
    /*通过top blob的索引返回loss*/
  231.  
    inline Dtype loss(const int top_index) const {
  232.  
    return (loss_.size() > top_index) ? loss_[top_index] : Dtype(0);
  233.  
    }
  234.  
     
  235.  
     
  236.  
    /**
  237.  
    * @brief Sets the loss associated with a top blob at a given index.
  238.  
    */
  239.  
    /*通过blob的索引设置loss*/
  240.  
    inline void set_loss(const int top_index, const Dtype value) {
  241.  
    if (loss_.size() <= top_index) {
  242.  
    loss_.resize(top_index + 1, Dtype(0));
  243.  
    }
  244.  
    loss_[top_index] = value;
  245.  
    }
  246.  
     
  247.  
     
  248.  
    /**
  249.  
    * @brief Returns the layer type.
  250.  
    */
  251.  
    /*返回层类型*/
  252.  
    virtual inline const char* type() const { return ""; }
  253.  
     
  254.  
     
  255.  
    /**
  256.  
    * @brief Returns the exact number of bottom blobs required by the layer,
  257.  
    * or -1 if no exact number is required.
  258.  
    *
  259.  
    * This method should be overridden to return a non-negative value if your
  260.  
    * layer expects some exact number of bottom blobs.
  261.  
    */
  262.  
    /*返回层底部精确blob数量*/
  263.  
    virtual inline int ExactNumBottomBlobs() const { return -1; }
  264.  
    /**
  265.  
    * @brief Returns the minimum number of bottom blobs required by the layer,
  266.  
    * or -1 if no minimum number is required.
  267.  
    *
  268.  
    * This method should be overridden to return a non-negative value if your
  269.  
    * layer expects some minimum number of bottom blobs.
  270.  
    */
  271.  
    /*返回层底部blob的最少个数*/
  272.  
    virtual inline int MinBottomBlobs() const { return -1; }
  273.  
    /**
  274.  
    * @brief Returns the maximum number of bottom blobs required by the layer,
  275.  
    * or -1 if no maximum number is required.
  276.  
    *
  277.  
    * This method should be overridden to return a non-negative value if your
  278.  
    * layer expects some maximum number of bottom blobs.
  279.  
    */
  280.  
    /*返回层底部blob的最多个数*/
  281.  
    virtual inline int MaxBottomBlobs() const { return -1; }
  282.  
    /**
  283.  
    * @brief Returns the exact number of top blobs required by the layer,
  284.  
    * or -1 if no exact number is required.
  285.  
    *
  286.  
    * This method should be overridden to return a non-negative value if your
  287.  
    * layer expects some exact number of top blobs.
  288.  
    */
  289.  
    /*返回层顶部精确blob数量*/
  290.  
    virtual inline int ExactNumTopBlobs() const { return -1; }
  291.  
    /**
  292.  
    * @brief Returns the minimum number of top blobs required by the layer,
  293.  
    * or -1 if no minimum number is required.
  294.  
    *
  295.  
    * This method should be overridden to return a non-negative value if your
  296.  
    * layer expects some minimum number of top blobs.
  297.  
    */
  298.  
    /*返回层顶部blob的最少个数*/
  299.  
    virtual inline int MinTopBlobs() const { return -1; }
  300.  
    /**
  301.  
    * @brief Returns the maximum number of top blobs required by the layer,
  302.  
    * or -1 if no maximum number is required.
  303.  
    *
  304.  
    * This method should be overridden to return a non-negative value if your
  305.  
    * layer expects some maximum number of top blobs.
  306.  
    */
  307.  
    /*返回层顶部blob的最多个数*/
  308.  
    virtual inline int MaxTopBlobs() const { return -1; }
  309.  
    /**
  310.  
    * @brief Returns true if the layer requires an equal number of bottom and
  311.  
    * top blobs.
  312.  
    *
  313.  
    * This method should be overridden to return true if your layer expects an
  314.  
    * equal number of bottom and top blobs.
  315.  
    */
  316.  
    /*返回层底部blob与顶部blob个数是否相等*/
  317.  
    virtual inline bool EqualNumBottomTopBlobs() const { return false; }
  318.  
     
  319.  
     
  320.  
    /**
  321.  
    * @brief Return whether "anonymous" top blobs are created automatically
  322.  
    * by the layer.
  323.  
    *
  324.  
    * If this method returns true, Net::Init will create enough "anonymous" top
  325.  
    * blobs to fulfill the requirement specified by ExactNumTopBlobs() or
  326.  
    * MinTopBlobs().
  327.  
    */
  328.  
    /*如果AutoTopBlobs返回结果为真的话,那么Net会根据层最少或精确blob数量去填充顶部blob*/
  329.  
    virtual inline bool AutoTopBlobs() const { return false; }
  330.  
     
  331.  
     
  332.  
    /**
  333.  
    * @brief Return whether to allow force_backward for a given bottom blob
  334.  
    * index.
  335.  
    *
  336.  
    * If AllowForceBackward(i) == false, we will ignore the force_backward
  337.  
    * setting and backpropagate to blob i only if it needs gradient information
  338.  
    * (as is done when force_backward == false).
  339.  
    */
  340.  
    /*对于bottom_index的blob,允不允许强制反传,如果AllowForceBackward为假的话,那么直接忽略force_backward*/
  341.  
    virtual inline bool AllowForceBackward(const int bottom_index) const {
  342.  
    return true;
  343.  
    }
  344.  
     
  345.  
     
  346.  
    /**
  347.  
    * @brief Specifies whether the layer should compute gradients w.r.t. a
  348.  
    * parameter at a particular index given by param_id.
  349.  
    *
  350.  
    * You can safely ignore false values and always compute gradients
  351.  
    * for all parameters, but possibly with wasteful computation.
  352.  
    */
  353.  
    /*对于给定的参数id判断是否应该计算该参数梯度*/
  354.  
    inline bool param_propagate_down(const int param_id) {
  355.  
    return (param_propagate_down_.size() > param_id) ?
  356.  
    param_propagate_down_[param_id] : false;
  357.  
    }
  358.  
    /**
  359.  
    * @brief Sets whether the layer should compute gradients w.r.t. a
  360.  
    * parameter at a particular index given by param_id.
  361.  
    */
  362.  
    /*对于给定的参数id设置是否应该计算该参数梯度*/
  363.  
    inline void set_param_propagate_down(const int param_id, const bool value) {
  364.  
    if (param_propagate_down_.size() <= param_id) {
  365.  
    param_propagate_down_.resize(param_id + 1, true);
  366.  
    }
  367.  
    param_propagate_down_[param_id] = value;
  368.  
    }
  369.  
     
  370.  
     
  371.  
     
  372.  
     
  373.  
    protected:
  374.  
    /** The protobuf that stores the layer parameters */
  375.  
    LayerParameter layer_param_;//layer的参数
  376.  
    /** The phase: TRAIN or TEST */
  377.  
    Phase phase_;//layer的模式,测试还是训练
  378.  
    /** The vector that stores the learnable parameters as a set of blobs. */
  379.  
    vector<shared_ptr<Blob<Dtype> > > blobs_;//存储指向层参数的指针的容器
  380.  
    /** Vector indicating whether to compute the diff of each param blob. */
  381.  
    vector<bool> param_propagate_down_;//存储对每个参数blob是否应该计算梯度的标志的容器
  382.  
     
  383.  
     
  384.  
    /** The vector that indicates whether each top blob has a non-zero weight in
  385.  
    * the objective function. */
  386.  
    vector<Dtype> loss_;//存储对于每个top blob的loss
  387.  
     
  388.  
     
  389.  
    /** @brief Using the CPU device, compute the layer output. */
  390.  
    /*在cpu上面的前向传播函数,非常重要,必须实现*/
  391.  
    virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
  392.  
    const vector<Blob<Dtype>*>& top) = 0;
  393.  
    /**
  394.  
    * @brief Using the GPU device, compute the layer output.
  395.  
    * Fall back to Forward_cpu() if unavailable.
  396.  
    */
  397.  
    /*在gpu上面实现的前向传播函数,如果没有实现则使用cpu上的前向传播*/
  398.  
    virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
  399.  
    const vector<Blob<Dtype>*>& top) {
  400.  
    // LOG(WARNING) << "Using CPU code as backup.";
  401.  
    return Forward_cpu(bottom, top);
  402.  
    }
  403.  
     
  404.  
     
  405.  
    /**
  406.  
    * @brief Using the CPU device, compute the gradients for any parameters and
  407.  
    * for the bottom blobs if propagate_down is true.
  408.  
    */
  409.  
    /*在cpu上面的反向传播函数,非常重要,必须实现*/
  410.  
    virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
  411.  
    const vector<bool>& propagate_down,
  412.  
    const vector<Blob<Dtype>*>& bottom) = 0;
  413.  
    /**
  414.  
    * @brief Using the GPU device, compute the gradients for any parameters and
  415.  
    * for the bottom blobs if propagate_down is true.
  416.  
    * Fall back to Backward_cpu() if unavailable.
  417.  
    */
  418.  
    /*在gpu上面实现的反向传播函数,如果没有实现则使用cpu上的反向传播*/
  419.  
    virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
  420.  
    const vector<bool>& propagate_down,
  421.  
    const vector<Blob<Dtype>*>& bottom) {
  422.  
    // LOG(WARNING) << "Using CPU code as backup.";
  423.  
    Backward_cpu(top, propagate_down, bottom);
  424.  
    }
  425.  
     
  426.  
     
  427.  
    /**
  428.  
    * Called by the parent Layer‘s SetUp to check that the number of bottom
  429.  
    * and top Blobs provided as input match the expected numbers specified by
  430.  
    * the {ExactNum,Min,Max}{Bottom,Top}Blobs() functions.
  431.  
    */
  432.  
    /*检查网络的底层与顶层blob形状是否符合规则,被SetUp函数调用*/
  433.  
    virtual void CheckBlobCounts(const vector<Blob<Dtype>*>& bottom,
  434.  
    const vector<Blob<Dtype>*>& top) {
  435.  
    if (ExactNumBottomBlobs() >= 0) {//检查网络中底部精确blob的数量是否为底部blob的数量
  436.  
    CHECK_EQ(ExactNumBottomBlobs(), bottom.size())
  437.  
    << type() << " Layer takes " << ExactNumBottomBlobs()
  438.  
    << " bottom blob(s) as input.";
  439.  
    }
  440.  
    if (MinBottomBlobs() >= 0) {//检查网络中底部blob的数量是否大于约定的底部最少blob的数量
  441.  
    CHECK_LE(MinBottomBlobs(), bottom.size())
  442.  
    << type() << " Layer takes at least " << MinBottomBlobs()
  443.  
    << " bottom blob(s) as input.";
  444.  
    }
  445.  
    if (MaxBottomBlobs() >= 0) {//检查网络中底部blob数量是否小于约定的底部最多blob的数量
  446.  
    CHECK_GE(MaxBottomBlobs(), bottom.size())
  447.  
    << type() << " Layer takes at most " << MaxBottomBlobs()
  448.  
    << " bottom blob(s) as input.";
  449.  
    }
  450.  
    if (ExactNumTopBlobs() >= 0) {//检查网络中顶部精确blob的数量是否为顶部blob的数量
  451.  
    CHECK_EQ(ExactNumTopBlobs(), top.size())
  452.  
    << type() << " Layer produces " << ExactNumTopBlobs()
  453.  
    << " top blob(s) as output.";
  454.  
    }
  455.  
    if (MinTopBlobs() >= 0) {//检查网络中顶部blob的数量是否大于约定的顶部最少blob的数量
  456.  
    CHECK_LE(MinTopBlobs(), top.size())
  457.  
    << type() << " Layer produces at least " << MinTopBlobs()
  458.  
    << " top blob(s) as output.";
  459.  
    }
  460.  
    if (MaxTopBlobs() >= 0) {//检查网络中顶部blob数量是否小于约定的顶部最多blob的数量
  461.  
    CHECK_GE(MaxTopBlobs(), top.size())
  462.  
    << type() << " Layer produces at most " << MaxTopBlobs()
  463.  
    << " top blob(s) as output.";
  464.  
    }
  465.  
    if (EqualNumBottomTopBlobs()) {//如果约定了底部与顶部blob的数量相同,则在此检查
  466.  
    CHECK_EQ(bottom.size(), top.size())
  467.  
    << type() << " Layer produces one top blob as output for each "
  468.  
    << "bottom blob input.";
  469.  
    }
  470.  
    }
  471.  
     
  472.  
     
  473.  
    /**
  474.  
    * Called by SetUp to initialize the weights associated with any top blobs in
  475.  
    * the loss function. Store non-zero loss weights in the diff blob.
  476.  
    */
  477.  
    /*这个函数按照网络参数中的设置的weight对top blob进行loss的权重设置*/
  478.  
    inline void SetLossWeights(const vector<Blob<Dtype>*>& top) {
  479.  
    const int num_loss_weights = layer_param_.loss_weight_size();
  480.  
    if (num_loss_weights) {
  481.  
    CHECK_EQ(top.size(), num_loss_weights) << "loss_weight must be "
  482.  
    "unspecified or specified once per top blob.";
  483.  
    for (int top_id = 0; top_id < top.size(); ++top_id) {//对每一个top blob设置loss权重
  484.  
    const Dtype loss_weight = layer_param_.loss_weight(top_id);
  485.  
    if (loss_weight == Dtype(0)) { continue; }
  486.  
    this->set_loss(top_id, loss_weight);
  487.  
    const int count = top[top_id]->count();
  488.  
    Dtype* loss_multiplier = top[top_id]->mutable_cpu_diff();
  489.  
    caffe_set(count, loss_weight, loss_multiplier);//将每一个权重设置到相应的top blob的梯度上
  490.  
    }
  491.  
    }
  492.  
    }
  493.  
     
  494.  
     
  495.  
    private:
  496.  
    /** Whether this layer is actually shared by other nets*/
  497.  
    bool is_shared_;//指示该层支不支持共享
  498.  
     
  499.  
     
  500.  
    /** The mutex for sequential forward if this layer is shared */
  501.  
    shared_ptr<boost::mutex> forward_mutex_;//对于共享的层的前传共享数据
  502.  
     
  503.  
     
  504.  
    /** Initialize forward_mutex_ */
  505.  
    void InitMutex();//对于共享数据的初始化
  506.  
    /** Lock forward_mutex_ if this layer is shared */
  507.  
    void Lock();//如果层是共享的,进行锁住互斥量的操作
  508.  
    /** Unlock forward_mutex_ if this layer is shared */
  509.  
    void Unlock();//如果层是共享的,进行解锁互斥量的操作
  510.  
     
  511.  
     
  512.  
    DISABLE_COPY_AND_ASSIGN(Layer);
  513.  
    }; // class Layer
  514.  
     
  515.  
     
  516.  
    // Forward and backward wrappers. You should implement the cpu and
  517.  
    // gpu specific implementations instead, and should not change these
  518.  
    // functions.
  519.  
    /*前向传播过程*/
  520.  
    template <typename Dtype>
  521.  
    inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom,
  522.  
    const vector<Blob<Dtype>*>& top) {
  523.  
    // Lock during forward to ensure sequential forward
  524.  
    Lock();//在前向传播时,需要锁住互斥量
  525.  
    Dtype loss = 0;
  526.  
    Reshape(bottom, top);//对底层与顶层的blob进行初始化
  527.  
    switch (Caffe::mode()) {
  528.  
    case Caffe::CPU:
  529.  
    Forward_cpu(bottom, top);//cpu前向传播
  530.  
    for (int top_id = 0; top_id < top.size(); ++top_id) {
  531.  
    if (!this->loss(top_id)) { continue; }//在最后一层才进行损失的计算
  532.  
    const int count = top[top_id]->count();
  533.  
    const Dtype* data = top[top_id]->cpu_data();
  534.  
    const Dtype* loss_weights = top[top_id]->cpu_diff();
  535.  
    loss += caffe_cpu_dot(count, data, loss_weights);//损失就是数据向量与对应的权重向量作点积并相加
  536.  
    }
  537.  
    break;
  538.  
    case Caffe::GPU:
  539.  
    Forward_gpu(bottom, top);//进行gpu前向传播
  540.  
    #ifndef CPU_ONLY//loss的计算过程与cpu方式几乎相同
  541.  
    for (int top_id = 0; top_id < top.size(); ++top_id) {
  542.  
    if (!this->loss(top_id)) { continue; }
  543.  
    const int count = top[top_id]->count();
  544.  
    const Dtype* data = top[top_id]->gpu_data();
  545.  
    const Dtype* loss_weights = top[top_id]->gpu_diff();
  546.  
    Dtype blob_loss = 0;
  547.  
    caffe_gpu_dot(count, data, loss_weights, &blob_loss);
  548.  
    loss += blob_loss;
  549.  
    }
  550.  
    #endif
  551.  
    break;
  552.  
    default:
  553.  
    LOG(FATAL) << "Unknown caffe mode.";
  554.  
    }
  555.  
    Unlock();//解锁互斥量
  556.  
    return loss;//返回loss,如不是最后一层,则loss为0
  557.  
    }
  558.  
     
  559.  
     
  560.  
    /*反向传播过程*/
  561.  
    template <typename Dtype>
  562.  
    inline void Layer<Dtype>::Backward(const vector<Blob<Dtype>*>& top,
  563.  
    const vector<bool>& propagate_down,
  564.  
    const vector<Blob<Dtype>*>& bottom) {
  565.  
    switch (Caffe::mode()) {//根据模式去判断进行哪一种方式的反向传播
  566.  
    case Caffe::CPU:
  567.  
    Backward_cpu(top, propagate_down, bottom);
  568.  
    break;
  569.  
    case Caffe::GPU:
  570.  
    Backward_gpu(top, propagate_down, bottom);
  571.  
    break;
  572.  
    default:
  573.  
    LOG(FATAL) << "Unknown caffe mode.";
  574.  
    }
  575.  
    }
  576.  
     
  577.  
     
  578.  
    // Serialize LayerParameter to protocol buffer
  579.  
    template <typename Dtype>//将层的参数保存至Proto
  580.  
    void Layer<Dtype>::ToProto(LayerParameter* param, bool write_diff) {
  581.  
    param->Clear();
  582.  
    param->CopyFrom(layer_param_);
  583.  
    param->clear_blobs();
  584.  
    for (int i = 0; i < blobs_.size(); ++i) {
  585.  
    blobs_[i]->ToProto(param->add_blobs(), write_diff);
  586.  
    }
  587.  
    }
  588.  
     
  589.  
     
  590.  
    } // namespace caffe
  591.  
     
  592.  
     
  593.  
    #endif // CAFFE_LAYER_H_


然后是layer.cpp的代码

 

 

 

 

  1.  
    #include <boost/thread.hpp>
  2.  
    #include "caffe/layer.hpp"
  3.  
     
  4.  
    namespace caffe {
  5.  
     
  6.  
    template <typename Dtype>
  7.  
    void Layer<Dtype>::InitMutex() {//初始化互斥量
  8.  
    forward_mutex_.reset(new boost::mutex());
  9.  
    }
  10.  
     
  11.  
    template <typename Dtype>
  12.  
    void Layer<Dtype>::Lock() {
  13.  
    if (IsShared()) {
  14.  
    forward_mutex_->lock();//若层为共享的话,互斥量上锁的操作
  15.  
    }
  16.  
    }
  17.  
     
  18.  
    template <typename Dtype>
  19.  
    void Layer<Dtype>::Unlock() {
  20.  
    if (IsShared()) {
  21.  
    forward_mutex_->unlock();//若层为共享的话,互斥量解锁操作
  22.  
    }
  23.  
    }
  24.  
     
  25.  
    INSTANTIATE_CLASS(Layer);
  26.  
     
  27.  
    } // namespace caffe


   乍一看layer的定义比较复杂,下面我们就依次解析一下layer的各个部分。
首先在Layer的private部分有几个变量/函数

 

 

 

 

  1.  
    private:
  2.  
    bool is_shared_;
  3.  
    shared_ptr<boost::mutex> forward_mutex_;
  4.  
    void InitMutex();
  5.  
    void Lock();
  6.  
    void Unlock();

在这里可以将layer的private部分理解为有关数据共享的相关信息变量/函数,is_shared_标志层能否共享,forward_mutex_指向层共享时共享变量的指针,而后四个函数则是有关网络前向传播时共享变量的初始化,上锁,解锁等操作,需要注意的是,只有在使用多GPU训练时,数据层才能被其他网络共享,这几个变量/函数在构造自己的layer时并不会频繁地使用。

 


然后我们看看网络的protected部分

 

  1.  
    protected:
  2.  
    LayerParameter layer_param_;
  3.  
    Phase phase_;
  4.  
    vector<shared_ptr<Blob<Dtype> > > blobs_;
  5.  
    vector<bool> param_propagate_down_;
  6.  
    vector<Dtype> loss_;
  7.  
    virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
  8.  
    const vector<Blob<Dtype>*>& top) = 0;
  9.  
    virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
  10.  
    const vector<Blob<Dtype>*>& top) {
  11.  
    // LOG(WARNING) << "Using CPU code as backup.";
  12.  
    return Forward_cpu(bottom, top);
  13.  
    }
  14.  
    virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
  15.  
    const vector<bool>& propagate_down,
  16.  
    const vector<Blob<Dtype>*>& bottom) = 0;
  17.  
    virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
  18.  
    const vector<bool>& propagate_down,
  19.  
    const vector<Blob<Dtype>*>& bottom) {
  20.  
    // LOG(WARNING) << "Using CPU code as backup.";
  21.  
    Backward_cpu(top, propagate_down, bottom);
  22.  
    }
  23.  
    virtual void CheckBlobCounts(const vector<Blob<Dtype>*>& bottom,
  24.  
    const vector<Blob<Dtype>*>& top)
  25.  
    inline void SetLossWeights(const vector<Blob<Dtype>*>& top)

               在protected部分就包含一些我们魔改layer,加入自己需要的功能时的东西了,首先layer_param_表示在caffe.proto中设置的有关层的参数;phase_只能为TRAIN或者TEST,表示层的模式;blobs_表示层的可学习参数的存储单元;param_propagate_down标志是否计算各个参数的梯度;loss_存储每个top blob的loss;CheckBlobCounts核验底层与顶层blob的大小是否符合规范,是否符合层的前传反传要求;SetLossWeights为各个top blob设置loss的权重。
   接下来,protected中就包含了四个重要的函数了,Forward_cpu和Forward_gpu与Backward_cpu和Backward_gpu,这四个函数是用户在构造新层的时候会实现的函数,其中,Forward_cpu与Backward_cpu是必须要实现的虚函数,而剩余两者是可选实现的,注意虚函数的作用,即在实现gpu部分后,cpu部分自动不执行,否则执行cpu部分。带cpu的部分表示层是在cpu上运行(这标志着该层是在串行工作),带gpu的部分表示层是在gpu上面运行(这标志着层是在并行计算)。

 


   接下来,我们再去看看层的public部分

 

  1.  
    public:
  2.  
    explicit Layer(const LayerParameter& param)
  3.  
    : layer_param_(param), is_shared_(false)
  4.  
    virtual ~Layer() {}
  5.  
    void SetUp(const vector<Blob<Dtype>*>& bottom,
  6.  
    const vector<Blob<Dtype>*>& top)
  7.  
    virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
  8.  
    const vector<Blob<Dtype>*>& top) {}
  9.  
    virtual inline bool ShareInParallel() const
  10.  
    inline bool IsShared() const
  11.  
    inline void SetShared(bool is_shared)
  12.  
    virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
  13.  
    const vector<Blob<Dtype>*>& top) = 0;
  14.  
    inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
  15.  
    const vector<Blob<Dtype>*>& top);
  16.  
    inline void Backward(const vector<Blob<Dtype>*>& top,
  17.  
    const vector<bool>& propagate_down,
  18.  
    const vector<Blob<Dtype>*>& bottom);
  19.  
    vector<shared_ptr<Blob<Dtype> > >& blobs()
  20.  
    const LayerParameter& layer_param() const
  21.  
    virtual void ToProto(LayerParameter* param, bool write_diff = false);
  22.  
    inline Dtype loss(const int top_index) const
  23.  
    inline void set_loss(const int top_index, const Dtype value)
  24.  
    virtual inline const char* type() const
  25.  
    virtual inline int ExactNumBottomBlobs() const
  26.  
    virtual inline int MinBottomBlobs() const
  27.  
    virtual inline int MaxBottomBlobs() const
  28.  
    virtual inline int ExactNumTopBlobs() const
  29.  
    virtual inline int MinTopBlobs() const
  30.  
    virtual inline int MaxTopBlobs() const
  31.  
    virtual inline bool EqualNumBottomTopBlobs() const
  32.  
    virtual inline bool AutoTopBlobs() const
  33.  
    virtual inline bool AllowForceBackward(const int bottom_index) const
  34.  
    inline bool param_propagate_down(const int param_id)
  35.  
    inline void set_param_propagate_down(const int param_id, const bool value)


               在public部分中,给出了判断与设置是否计算参数梯度的开关;其次,设置了许多查询与设置顶部与底部blob的接口以及顶部blob的loss的接口;网络的可学习参数存放在blob_中,并定义了blob与Proto相交互的ToProto;同时还定义了网络共享相关的ShareInParallel(),IsShared()和SetShared()。
   接下来,在public中,还有几个重要的常用函数,首先是layerSetup函数,往往在自定义层时,在该函数中进行layer的各个参数初始化;然后是Reshape函数,这个函数在自定义层时对layer的底部和顶部的blob形状进行初始化,协定层传播计算时的数据规格。此外还有Forward函数,该函数负责层的前向传播过程,并判断若该层是网络的最后一层的话,就进行loss的计算;Backward函数则进行层的反传操作。
   值得注意的是,构造函数在我们自定义层时是不需要去修订或者重写的,Layer提供了LayerSetup和Reshape供用户初始化;构造函数的作用是,获取层的模式,并且将层定义文件中用户定义的权重和偏置放置于blob_中,可是往往我们在定义层时不定义权重与偏置,因此并没有在构造函数中初始化。Layer中的更重要的一个SetUp函数把层的很多初始化集成了起来,并将在Net初始化时进行调用,笔者将在后话解析。
   在layer.cpp中,主要是定义了对层共享时前传所使用的互斥量进行的操作。

 

   到此为止,layer.hpp与layer.cpp便解析结束了,值得注意的是,这只是一块没有经过雕琢的自然原木,因此,很多独有特征并没有被显示出来。接下来,笔者还打算更新几篇讲解caffe中几个常用层的博客,这样能从代码中完全体会深度神经网络中层的运算过程。不过,无论派生的自定义层多么高大上,这块原木一直默默伫立在这里,约定了层的结构设置与计算过程。因此,在构造层的时候,一定要注意参考这个父类,不要只是盲目借鉴其他的派生成品。
   总的来说,各种Layer像一块块积木,搭建了深度神经网络这个大魔幻城堡,layer的构造严谨,支持继承并且完善用户自己的功能,用户修改操作简单,接口封装性好。
   欢迎阅读笔者后续解析常用层的博客,各位读者朋友的支持与鼓励是我最大的动力!

 

 

written by jiong
To be a geek
 

 

 

 

 

caffe源码深入学习

标签:relative   clear   diff   mutex   灵活   original   文章   探索   nts   

原文地址:https://www.cnblogs.com/cx2016/p/13778371.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!