caffe添加新层教程
2017-06-08 16:05
288 查看
时间节点2016.04,即caffe重大更新后(每一种层都对应一个同名cpp和hpp文件)。
正向直接copy传播,反向时将梯度放缩指定倍。
这个层对一些特定的网络结构有很重要的辅助作用,比如有时我们的网络存在分支,但我们不希望某一分支影响之前层的更新,那么我们就将梯度放缩0倍。
不同功能类型的层所引的头文件也不同,具体大家可以到“caffe/include/caffe/layers”目录下找相似的现成的文件参考 。我们这次写的hpp文件最后也要放在这个目录下。
注意:下面注释包起来的部分为需要注意的部分。
特别注意:命名的时候应严格一致和注意大小写,这一点是导致很多人加层失败的主要原因。
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
CPP文件应当位于src/caffe/layers下
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
这里我们要为我们新写的层添加参数和消息函数。
【1】由于我们的层有一个diff_scale参数,因此我们首先应该在message LayerParameter {}中添加新参数信息。添加信息时,首先要制定一个唯一ID,这个ID的可选值可以由这句话看出:
2
3
4
5
1
2
3
4
5
由上图可以看出,可选的ID为143。
于是我们就可以添加这样一行:
1
【2】在任意位置添加消息函数
2
3
1
2
3
【3】 在message V1LayerParameter {}中添加以下内容
在enum LayerType {}中添加唯一ID,只要在这里不重复即可。
1
外面接着添加,同样ID也是只要不重复即可
1
【4】 在message V0LayerParameter {}添加参数定义
1
使用方法举例如下:
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
(1)一定要注意大小写、一定要注意大小写、一定要注意大小写
(2)不会写、不确定,就去找caffe现有的层来参考模仿
(3)caffe数据操作的函数定义在src/caffe/util/math_functions.cpp,
大家也可以参考这位同学的博客
http://blog.csdn.net/seven_first/article/details/47378697
描述一下本次要实现层的功能:
正向直接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> //******以后我们层的type: "DiffCutoff" ******* 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); //****我们只需要一个bottom和一个top***** virtual inline int ExactNumBottomBlobs() const { return 1; } //******以后我们层的type: "DiffCutoff" ******* virtual inline const char* type() const { return "DiffCutoff"; } protected: //******这里只写了CPU功能,故删掉了原本的GPU函数 ******* 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型的标量,用来存储梯度放缩倍数*** Dtype diff_scale; }; } #endif1
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的shape应和bottom的shape相同 top[0]->Reshape(bottom[0]->shape()); } template <typename Dtype> void DiffCutoffLayer<Dtype>::Forward_cpu( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { // 前向传播直接将bottom的数据copy到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 diff_scale= this->layer_param_.diffcutoff_param().diff_scale(); // 如果bottom前向传播完成,我们就把top的diff放缩后赋给bottom的diff 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 {1
2
3
4
5
1
2
3
4
5
由上图可以看出,可选的ID为143。
于是我们就可以添加这样一行:
optional DiffCutoffParameter diffcutoff_param = 143;1
1
【2】在任意位置添加消息函数
message DiffCutoffParameter { optional float diff_scale = 1 [default = 1]; //默认梯度不缩放 }1
2
3
1
2
3
【3】 在message V1LayerParameter {}中添加以下内容
在enum LayerType {}中添加唯一ID,只要在这里不重复即可。
DIFF_CUTOFF=45;1
1
外面接着添加,同样ID也是只要不重复即可
optional DiffCutoffParameter diffcutoff_param = 46;1
1
【4】 在message V0LayerParameter {}添加参数定义
optional float diff_scale = 47 [default = 1];1
1
(4)最后重新编译caffe即可
使用方法举例如下:layer { name: "diff_1" type: "DiffCutoff" bottom: "conv1" top: "diff_1" diff_cutoff_param { diff_scale: 0.0001 } }1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
(5)忠告与建议
(1)一定要注意大小写、一定要注意大小写、一定要注意大小写(2)不会写、不确定,就去找caffe现有的层来参考模仿
(3)caffe数据操作的函数定义在src/caffe/util/math_functions.cpp,
大家也可以参考这位同学的博客
http://blog.csdn.net/seven_first/article/details/47378697
相关文章推荐
- Caffe源码中添加新层 详细教程
- caffe添加新层教程
- caffe添加新层教程
- caffe添加新层教程
- caffe添加新层教程
- Scott Mitchell 的ASP.NET 2.0数据教程之56:添加新记录时包含一个文件上传选项
- DotNetTextBox控件添加外挂插件功能的图文教程。
- Scott Mitchell 的ASP.NET 2.0数据教程之三十九:: 在编辑和插入界面里添加验证控件
- Scott Mitchell 的ASP.NET 2.0数据教程之四十二::为删除数据添加客户端确认
- SQL语言入门教程:第四课向表格中添加、更新、删除记录
- javascript asp教程添加和修改
- Jquery实现简单的表格添加、编辑、删除教程
- Scott Mitchell 的ASP.NET 2.0数据教程之四十二::为删除数据添加客户端确认
- Scott Mitchell 的ASP.NET 2.0数据教程之70:为DataTable添加额外的列
- Scott Mitchell 的ASP.NET 2.0数据教程之三十九:: 在编辑和插入界面里添加验证控件
- 菜鸟也能当PS高手!PhotoWorks为你的图片添加漂亮的边框(教程+下载)
- Scott Mitchell 的ASP.NET 2.0数据教程之51章:为GridView控件添加Radio Buttons列
- Scott Mitchell 的ASP.NET 2.0数据教程之二十二:为删除数据添加客户端确认
- javascript asp教程添加和修改
- Scott Mitchell 的ASP.NET 2.0数据教程之四十二::为删除数据添加客户端确认