(15)caffe总结之自定义Layer的实现

自定义一个计算层,实现y = x^power + b的功能。


自定义神经层具体可以分成5个步:

1.创建定义的头文件include/caffe/layers/my_neuron_layer.hpp

   重新Layer名的方法:virtual inline const char* type() const {return "MyNeuron";}

   如果只是需要cpu的方法的话,可以注释掉forward/backward_gpu()这两个方法

#ifndef CAFFE_MY_NEURON_LAYER_HPP_
#define CAFFE_MY_NEURON_LAYER_HPP_

#include <vector>

#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"

#include "caffe/layers/neuron_layer.hpp"

namespace caffe {

template <typename Dtype>
class MyNeuronLayer : public NeuronLayer<Dtype> {
 public:
  
  explicit MyNeuronLayer(const LayerParameter& param)
      : NeuronLayer<Dtype>(param) {}
  virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);

  virtual inline const char* type() const { return "MyNeuron"; }

 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);


  Dtype power_;
  Dtype b_;
 };

}  // namespace caffe

#endif  // CAFFE_MY_NEURON_LAYER_HPP_

2.创建对应src/caffe/src/my_neuron_layer.cpp的源文件

   重写方法LayerSetUp,实现能从protoxt读取参数

   重写方法Reshape,如果对继承类没有修改的话,就不需要重写

   重写方法Forward_cpu

   重写方法Backward_cpu(非必须)

   *如果要GPU支持,则还需要创建src/caffe/src/my_neuron_layer.cu,同理重写方法Forward_gpu/Backward_gpu(非必须)

#include <vector>

#include "caffe/layers/my_neuron_layer.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {

template <typename Dtype>
void MyNeuronLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top){
  
  NeuronLayer<Dtype>::LayerSetUp(bottom,top);
  power_ = this->layer_param_.my_neuron_param().power();
  b_ = this->layer_param_.my_neuron_param().b();
 }

// Compute y = x^power + b
template <typename Dtype>
void MyNeuronLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top){

  Dtype* top_data = top[0]->mutable_cpu_data();
  const int count = bottom[0]->count();
  caffe_powx(count, bottom[0]->cpu_data(), Dtype(power_), top_data);
    for (int i = 0; i < count; ++i)
  {
    top_data[i] = top_data[i] + b_;
  }
}

template <typename Dtype>
void MyNeuronLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down,const vector<Blob<Dtype>*>& bottom){
  const int count = top[0]->count();
  const Dtype* top_diff = top[0]->cpu_diff();
  if(propagate_down[0]){
    const Dtype* bottom_data = bottom[0]->cpu_data();
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    caffe_powx(count, bottom_data, Dtype(power_ - 1), bottom_diff);
    caffe_scal(count, Dtype(power_), bottom_diff);
    caffe_mul(count, bottom_diff, top_diff, bottom_diff);
  }

}


INSTANTIATE_CLASS(MyNeuronLayer);
REGISTER_LAYER_CLASS(MyNeuron);

}// namespace caffe


3.proto/caffe.proto注册新的Layer

message LayerParameter{
...
++ optional MyNeuronParameter
my_neuron_param = 150;
...
}
...
++ message MyNeuronParameter{
++ optional float power = 1 [default = 2];
++ optional float b = 2 [default = 1];
}
...
message V1LayerParameter{
...
++ MYNEURON = 40;
...
}
4.my_neuron_layer.cpp添加注册的宏定义

INSTANTIATE_CLASS(MyNeuronLayer);
REGISTER_LAYER_CLASS(MyNeuron);
如果有my_neuron_layer.cu,则添加

INSTANTIATE_LAYER_GPU_FUNCS(MyNeuronLayer);

5,重写编译


接下来,我们测试定义的Layer

定义deploy.prototxt

name: "CaffeNet"
input: "data"
input_shape {
  dim: 1 # batchsize
  dim: 1 # number of colour channels - rgb
  dim: 28 # width
  dim: 28 # height
}

layer {
  name: "myneuron"
  type: "MyNeuron"
  bottom: "data"
  top: "data_out"
  my_neuron_param {
    power : 2
    b : 1
 }
}
运行test_my_neuron.py

import numpy as np
import matplotlib.pyplot as plt
import os
import sys
import caffe

deploy_file = "./deploy.prototxt"
test_data   = "./5.jpg"

if __name__ == '__main__':
  
  net = caffe.Net(deploy_file,caffe.TEST) #加载model 和network
#设置图像预处理
  transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})  #设定图像的格式(1,1,28,28)

  transformer.set_transpose('data', (2, 0, 1)) #改变维度顺序,由原始图片(28,28,1)变为(1,28,28)

  img = caffe.io.load_image(test_data,color=False)  #读取图片

  net.blobs['data'].data[...] = transformer.preprocess('data', img) #执行上面的预处理,并加载到blob中

  print net.blobs['data'].data[0][0][14] #打印出原始数据

  out = net.forward() //执行测试

  print out['data_out'][0][0][14]  #打印处理之后的数据

结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值