Caffe自定义网络层

这篇博客介绍了如何在Caffe中添加自定义网络层,包括不带参数和带参数的实现。对于不带参数的层,需要创建cpp和hpp文件,并实现Forward和Backward函数;带参数的层则需要在proto文件中定义参数,然后在cpp文件中获取并使用这些参数。完成这些步骤后,通过make编译Caffe即可使用新添加的网络层。
摘要由CSDN通过智能技术生成

参考博客

1 说明

本文描述了在Caffe源码中添加网络层的两种情况:不带配置参数的带配置参数的。示例的网络层中没有做数据处理,传入的数据块直接传出去,也没有梯度计算。

2 不带参数的网络层

我们将要在 .prototxt 中添加的网络层为:

layer {
  name:"NewLayer"
  type:"New" # 网络类型
  bottom: "data"
  top:"data"
}

该网络层的类型名称为New,没有其他配置参数,只需要在对应位置添加 .cpp.hpp 文件,添加步骤如下:

  • ./include/caffe/layers/ 文件夹下添加 new_layer.hpp
    :::details

    #ifndef CAFFE_NEW_LAYER_HPP_
    #define CAFFE_NEW_LAYER_HPP_
     
    #include <vector>
     
    #include "caffe/blob.hpp"
    #include "caffe/layer.hpp"
    #include "caffe/proto/caffe.pb.h"
     
    namespace caffe {
    	template <typename Dtype>
    	class NewLayer : public Layer<Dtype> {
    	public:
    		explicit NewLayer(const LayerParameter& param)
    			: Layer<Dtype>(param) {}
    		virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
    			const vector<Blob<Dtype>*>& top){};
    		virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
    			const vector<Blob<Dtype>*>& top){};
     
    	protected:
    		virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    			const vector<Blob<Dtype>*>& top);
    		virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
    			const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
    		virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
    			const vector<Blob<Dtype>*>& top){};
    		virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
    			const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom){};
    	};
     
    } 
    #endif 
    

    :::

  • ./src/caffe/layers/ 文件夹下添加 new_layer.cpp
    :::details

    #include <vector>
    #include "caffe/layers/new_layer.hpp"
     
    namespace caffe {
     
    template <typename Dtype>
    void NewLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    	const vector<Blob<Dtype>*>& top) {
    	const Dtype* bottom_data = bottom[0]->cpu_data();
    	Dtype* top_data = top[0]->mutable_cpu_data();
    	const int count = bottom[0]->count();
    	for (int i = 0; i < count; ++i) {
    			top_data[i] = bottom_data[i];
    	}
    }
     
    template <typename Dtype>
    void NewLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    	const vector<bool>& propagate_down,
    	const vector<Blob<Dtype>*>& bottom) {
    	if (propagate_down[0]) {
    		const Dtype* bottom_data = bottom[0]->cpu_data();
    		const Dtype* top_diff = top[0]->cpu_diff();
    		Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    		const int count = bottom[0]->count();
    		for (int i = 0; i < count; ++i) {
    			bottom_diff[i] = top_diff[i];
    		}
    	}
    }
     
    #ifdef CPU_ONLY
    	STUB_GPU(NewLayer);
    #endif
     
    INSTANTIATE_CLASS(NewLayer);  //类名,注:这个类名与prototxt文件中的层名不需一致
    REGISTER_LAYER_CLASS(New); // 对应层的类型
     
    }  // namespace caffe
    

    :::

  • 在 Caffe 的根目录下执行 make 即可编译。编译成功后即可在 .prototxt 中添加该网络层。

3 带参数的网络层

我们将要在 .prototxt 中添加的网络层为:

layer {
  name:"NewLayer"
  type:"New"
  bottom: "data"
  top:"data"
    new_param {
    coeff1: 1.0
	coeff2: 2.0
  }
}

相比于不带参数的网络层,带参数的网络层还需要 caffe.proto 文件中添加参数的说明。网络层添加步骤如下:

  • 打开 ./src/caffe/proto/caffe.proto 文件

    • message LayerParameter {} 中添加
        optional NewParameter new_param = 151;
      
    • 在其他空白出添加:
      message NewParameter{
          optional float coeff1 = 1 [default = 1];
          optional float coeff2 = 2 [default = 2];
      }
      
  • .cpp 中获取参数
    :::details

    #include <vector>
    #include "caffe/layers/new_layer.hpp"
     
    namespace caffe {
     
    template <typename Dtype>
    void NewLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    	const vector<Blob<Dtype>*>& top) {
    	const Dtype* bottom_data = bottom[0]->cpu_data();
    	Dtype* top_data = top[0]->mutable_cpu_data();
    	const int count = bottom[0]->count();
    	
    	float coeff = this->layer_param_.new_param().coeff1(); // 获取参数
    	LOG(INFO) << "NewLayer, Forward_cpu:" << coeff;
     
    	for (int i = 0; i < count; ++i) {
    			top_data[i] = bottom_data[i];
    	}
    }
     
    template <typename Dtype>
    void NewLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    	const vector<bool>& propagate_down,
    	const vector<Blob<Dtype>*>& bottom) {
     
    	float coeff = this->layer_param_.new_param().coeff2();	// 获取参数
    	LOG(INFO) << "NewLayer, Backward_cpu:" << coeff;
     
    	if (propagate_down[0]) {
    		const Dtype* bottom_data = bottom[0]->cpu_data();
    		const Dtype* top_diff = top[0]->cpu_diff();
    		Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    		const int count = bottom[0]->count();
    		for (int i = 0; i < count; ++i) {
    			bottom_diff[i] = top_diff[i];
    		}
    	}
    }
     
    #ifdef CPU_ONLY
    	STUB_GPU(NewLayer);
    #endif
     
    INSTANTIATE_CLASS(NewLayer);  //类名,对应prototxt文件中的层名
    REGISTER_LAYER_CLASS(New); // 对应层的类型
     
    }  // namespace caffe
    

    :::

  • 由于修改了 caffe.proto 文件,在执行 make 时会将 Caffe 重新编译一遍。

注意:添加的这些文件名、变量名要保持一致。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值