您的位置:首页 > Web前端

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

2017-04-22 11:22 316 查看
自定义一个计算层,实现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]  #打印处理之后的数据

结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐