时间节点2016.04,即caffe重大更新后(每一种层都对应一个同名cpp和hpp文件)。
描述一下本次要实现层的功能:
正向直接copy传播,反向时将梯度放缩指定倍。
这个层对一些特定的网络结构有很重要的辅助作用,比如有时我们的网络存在分支,但我们不希望某一分支影响之前层的更新,那么我们就将梯度放缩0倍。
(1)创建HPP头文件diff_cutoff_layer.hpp
不同功能类型的层所引的头文件也不同,具体大家可以到“caffe/include/caffe/layers”目录下找相似的现成的文件参考 。我们这次写的hpp文件最后也要放在这个目录下。
注意:下面注释包起来的部分为需要注意的部分。
特别注意:命名的时候应严格一致和注意大小写,这一点是导致很多人加层失败的主要原因。
#ifndef CAFFE_DIFFCUTOFF_LAYER_HPP_
#define CAFFE_DIFFCUTOFF_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 DiffCutoffLayer : public NeuronLayer<Dtype> {
public:
explicit DiffCutoffLayer(const LayerParameter& param) : NeuronLayer<Dtype>(param) {}
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>&top);
virtual inline int ExactNumBottomBlobs() const { return 1; }
virtual inline const char* type() const { return "DiffCutoff"; }
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 diff_scale;
};
}
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
(2)创建diff_cutoff_layer.cpp文件
CPP文件应当位于src/caffe/layers下
#include <algorithm>
#include <vector>
#include "caffe/layers/diff_cutoff_layer.hpp"
#include "caffe/util/math_functions.hpp"
namespace caffe {
template <typename Dtype>
void DiffCutoffLayer<Dtype>::LayerSetUp(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
NeuronLayer<Dtype>::LayerSetUp(bottom, top);
top[0]->Reshape(bottom[0]->shape());
}
template <typename Dtype>
void DiffCutoffLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const int count = top[0]->count();
caffe_copy(
count,
bottom[0]->cpu_data(),
top[0]->mutable_cpu_data());
}
template <typename Dtype>
void DiffCutoffLayer<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();
diff_scale= this->layer_param_.diffcutoff_param().diff_scale();
if (propagate_down[0]) {
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
caffe_cpu_axpby(
count,
diff_scale,
top_diff,
Dtype(0),
bottom_diff);
}
}
#ifdef CPU_ONLY
STUB_GPU(DiffCutoffLayer);
#endif
INSTANTIATE_CLASS(DiffCutoffLayer);
REGISTER_LAYER_CLASS(DiffCutoff);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
(3)修改src\caffe\proto\caffe.proto文件
这里我们要为我们新写的层添加参数和消息函数。
【1】由于我们的层有一个diff_scale参数,因此我们首先应该在message LayerParameter {}中添加新参数信息。添加信息时,首先要制定一个唯一ID,这个ID的可选值可以由这句话看出:
// NOTE
// Update the next available ID when you add a new LayerParameter field.
//
// LayerParameter next available layer-specific ID: 143 (last added: BatchCLuster)
message LayerParameter {
由上图可以看出,可选的ID为143。
于是我们就可以添加这样一行:
optional DiffCutoffParameter diffcutoff_param = 143;
【2】在任意位置添加消息函数
message DiffCutoffParameter {
optional float diff_scale = 1 [default = 1];
}
【3】 在message V1LayerParameter {}中添加以下内容
在enum LayerType {}中添加唯一ID,只要在这里不重复即可。
DIFF_CUTOFF=45;
外面接着添加,同样ID也是只要不重复即可
optional DiffCutoffParameter diffcutoff_param = 46;
【4】 在message V0LayerParameter {}添加参数定义
optional float diff_scale = 47 [default = 1];
(4)最后重新编译caffe即可
使用方法举例如下:
layer {
name: "diff_1"
type: "DiffCutoff"
bottom: "conv1"
top: "diff_1"
diff_cutoff_param {
diff_scale: 0.0001
}
}
(5)忠告与建议
(1)一定要注意大小写、一定要注意大小写、一定要注意大小写
(2)不会写、不确定,就去找caffe现有的层来参考模仿
(3)caffe数据操作的函数定义在src/caffe/util/math_functions.cpp,
大家也可以参考这位同学的博客
http://blog.csdn.net/seven_first/article/details/47378697