caffe增加自己的layer实战(上)--caffe学习(10)

github上如何增加自己的caffe layer:这里写链接内容
摘要如下:

Here's roughly the process I follow.
    Add a class declaration for your layer to the appropriate one of common_layers.hpp, data_layers.hpp, loss_layers.hpp, neuron_layers.hpp, or vision_layers.hpp. Include an inline implementation of type and the *Blobs() methods to specify blob number requirements. Omit the *_gpu declarations if you'll only be implementing CPU code.
    Implement your layer in layers/your_layer.cpp.
        SetUp for initialization: reading parameters, allocating buffers, etc.
        Forward_cpu for the function your layer computes
        Backward_cpu for its gradient
    (Optional) Implement the GPU versions Forward_gpu and Backward_gpu in layers/your_layer.cu.
    Add your layer to proto/caffe.proto, updating the next available ID. Also declare parameters, if needed, in this file.
    Make your layer createable by adding it to layer_factory.cpp.
    Write tests in test/test_your_layer.cpp. Use test/test_gradient_check_util.hpp to check that your Forward and Backward implementations are in numerical agreement.

Since this is a many step process, I thought it worth recording here. I would welcome improvements to Caffe that make the layer adding process less involved. BVLC folk All, if I've made an error or omitted something here, feel free to edit this post the wiki.

1:首先明确最新版caffe的目录结构:
头文件.hpp:/caffe/include/caffe
cpp文件:/caffe/src/caffe
2:首先明确自己需要增加的layer是属于哪一种类别的layer:可参考:这里写链接内容
caffe在include里分了四大类,vision\common\loss\data layer

———————-分割线————————-
下面以我们添加一个data layer为例开始讲解:
完善后的地址这里写链接内容(这是CVPR2016一篇论文中实现的,我是基于该版本做一个分析和学习,源代码解释权归其所有)

1:目的:在caffe里面增加一个一个datalayer,名字为video_layer,就是允许caffe的输入data层数据为视频,而不是局限于imag
2:因为它是属于datalayer,而且我们的视频和原来的image是最接近的,因为视频就是多幅图片,所以找到/caffe/include/caffe/data_layers.hpp
或者目录\caffe-master\include\caffe\layers\image_data_layers.hpp
可以看看里面原来有什么:

/**
 * @brief Provides data to the Net from image files.
 *
 * TODO(dox): thorough documentation for Forward and proto params.
 */
template <typename Dtype>
class ImageDataLayer : public BasePrefetchingDataLayer<Dtype> {
public:
    explicit ImageDataLayer(const LayerParameter& param)
    : BasePrefetchingDataLayer<Dtype>(param) {}
    virtual ~ImageDataLayer();
    virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
            const vector<Blob<Dtype>*>& top);

    virtual inline const char* type() const { return "ImageData"; }
    virtual inline int ExactNumBottomBlobs() const { return 0; }
    virtual inline int ExactNumTopBlobs() const { return 2; }

protected:
    shared_ptr<Caffe::RNG> prefetch_rng_;
    virtual void ShuffleImages();
    virtual void InternalThreadEntry();

#ifdef USE_MPI
    inline virtual void advance_cursor(){
        lines_id_++;
        if (lines_id_ >= lines_.size()) {
            // We have reached the end. Restart from the first.
            DLOG(INFO) << "Restarting data prefetching from start.";
            lines_id_ = 0;
            if (this->layer_param_.image_data_param().shuffle()) {
                ShuffleImages();
            }
        }
    }
#endif

    vector<std::pair<std::string, int> > lines_;
    int lines_id_;
};

可以看到原来的caffe中ImageDataLayer 是通过这句话继承BasePrefetchingDataLayer类来的:

class ImageDataLayer : public BasePrefetchingDataLayer<Dtype> 

我们的video也是基于imag的,所以同样依样画葫芦继承该类:

/**
 * Provides data to the Net from video files.
 */
template <typename Dtype>
class VideoDataLayer : public BasePrefetchingDataLayer<Dtype> {

视频的初始化和image基本一致,首先将该类完全复制但是改名为VideoDataLayer,如下:

template <typename Dtype>
class VideoDataLayer : public BasePrefetchingDataLayer<Dtype> {
public:
    explicit VideoDataLayer(const LayerParameter& param)
    : BasePrefetchingDataLayer<Dtype>(param) {}
    virtual ~VideoDataLayer();
    virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
            const vector<Blob<Dtype>*>& top);

    virtual inline const char* type() const { return "VideoData"; }
    virtual inline int ExactNumBottomBlobs() const { return 0; }
    virtual inline int ExactNumTopBlobs() const { return 2; }

protected:
    shared_ptr<Caffe::RNG> prefetch_rng_;
    shared_ptr<Caffe::RNG> prefetch_rng_2_;
    shared_ptr<Caffe::RNG> prefetch_rng_1_;
    shared_ptr<Caffe::RNG> frame_prefetch_rng_;
    virtual void ShuffleVideos();
    virtual void InternalThreadEntry();

#ifdef USE_MPI
    inline virtual void advance_cursor(){
        lines_id_++;
        if (lines_id_ >= lines_.size()) {
            // We have reached the end. Restart from the first.
            DLOG(INFO) << "Restarting data prefetching from start.";
            lines_id_ = 0;
            if (this->layer_param_.video_data_param().shuffle()) {
                ShuffleVideos();
            }
        }
    }
#endif

更新:
最好是在这里新建一个hpp文件名:video_data_layer_.hpp
后面的video_data_layer_.cpp记得包含video_data_layer_.hpp文件。video_data_layer_.hpp文件内容:

#ifndef CAFFE_IMAGE_DATA_LAYER_HPP_
#define CAFFE_IMAGE_DATA_LAYER_HPP_

#include <string>
#include <utility>
#include <vector>

#include "caffe/blob.hpp"
#include "caffe/data_transformer.hpp"
#include "caffe/internal_thread.hpp"
#include "caffe/layer.hpp"
#include "caffe/layers/base_data_layer.hpp"
#include "caffe/proto/caffe.pb.h"

namespace caffe {

/**
 * @brief Provides data to the Net from video files.
 *
 * TODO(dox): thorough documentation for Forward and proto params.
 */
template <typename Dtype>
class VideoDataLayer : public BasePrefetchingDataLayer<Dtype> {
public:
  explicit VideoDataLayer(const LayerParameter& param)
  : BasePrefetchingDataLayer<Dtype>(param) {}
  virtual ~VideoDataLayer();
  virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);

  virtual inline const char* type() const { return "VideoData"; }
  virtual inline int ExactNumBottomBlobs() const { return 0; }
  virtual inline int ExactNumTopBlobs() const { return 2; }

protected:
  shared_ptr<Caffe::RNG> prefetch_rng_;
  shared_ptr<Caffe::RNG> prefetch_rng_2_;
  shared_ptr<Caffe::RNG> prefetch_rng_1_;
  shared_ptr<Caffe::RNG> frame_prefetch_rng_;
  virtual void ShuffleVideos();
  virtual void InternalThreadEntry();

#ifdef USE_MPI
  inline virtual void advance_cursor(){
    lines_id_++;
    if (lines_id_ >= lines_.size()) {
      // We have reached the end. Restart from the first.
      DLOG(INFO) << "Restarting data prefetching from start.";
      lines_id_ = 0;
      if (this->layer_param_.video_data_param().shuffle()) {
        ShuffleVideos();
      }
    }
  }
#endif

  vector<std::pair<std::string, int> > lines_;
  vector<int> lines_duration_;
  int lines_id_;
  string name_pattern_;
};


}  // namespace caffe

#endif  // CAFFE_IMAGE_DATA_LAYER_HPP_

具体的操作在通过在cpp中实现:
virtual ~VideoDataLayer();
主要的不同除了名字以外还有:

protected:
    shared_ptr<Caffe::RNG> prefetch_rng_;
    shared_ptr<Caffe::RNG> prefetch_rng_2_;
    shared_ptr<Caffe::RNG> prefetch_rng_1_;
    shared_ptr<Caffe::RNG> frame_prefetch_rng_;

这里我还没太明白,看了半天github的讨论这里写链接内容
欢迎各位探讨,先放在这里后面在弄清楚它。
接下篇:
caffe增加自己的layer实战(中)–caffe学习(11)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值