manbetx官方网站

据悉Caffe的DeepID2实现(下)基于Caffe的DeepID2实现(中)

九月 30th, 2018  |  manbetx官方网站

小喵的唠叨话:这次的博客,真心累伤了小喵的胸。但考虑到知识要加固与享用,小喵决定这次把多余的情还勾了。

  小喵的唠叨话:我们当上平等首博客中,介绍了Caffe的Data层的编辑。有了Data层,下一致步则是安错过行使生成好之教练多少。也就算是即刻同首的内容。

小喵的博客:http://www.miaoerduo.com

 

博客原文: http://www.miaoerduo.com/deep-learning/基于caffe的deepid2实现(下).html ‎

小喵的博客:http://www.miaoerduo.com

季、数据的整治,简单的剪切

面前的Data层用于深成成对的输入数据,Normalization层,用于将feature归一化,那么下是无是就得使ContrastiveLoss层进行训练了邪?

且慢,还不一一步。

ContrastiveLoss层要求发出3只bottom:feature1、feature2以及代表对位的feature是否为跟一个identity的label。

我们本收获的feature却是有的都以并,data层直接获取的label也和这里要求的label不同。因此须要指向数据开展同样不良重整。

一个简易的规则就是本奇偶,将feature划分成两有些。这样得到的有数有些正好就是是一模一样位置为平针对性。对于label的理,也足以用接近的章程。小喵这里才对feature进行整治,而label的拍卖则是透过改ContrastiveLoss层来落实。

feature的整理本质上就是是一个片的操作,这里命名也id2_slice_layer,实现方式就是依奇偶把bottom的多寡复制到top。后馈的时节,也尽管是以鲜部分的feature的diff都一直复制到相应位置的bottom_diff中,具体实现如下:

 1 // created by miao
 2 #ifndef CAFFE_ID2_SLICE_LAYER_HPP_
 3 #define CAFFE_ID2_SLICE_LAYER_HPP_
 4 
 5 #include <vector>
 6 
 7 #include "caffe/blob.hpp"
 8 #include "caffe/layer.hpp"
 9 #include "caffe/proto/caffe.pb.h"
10 
11 namespace caffe {
12 
13 /**
14  * @brief Takes a Blob and slices it along either the num or channel dimension,
15  *        outputting multiple sliced Blob results.
16  *
17  * TODO(dox): thorough documentation for Forward, Backward, and proto params.
18  */
19 template <typename Dtype>
20 class Id2SliceLayer : public Layer<Dtype> {
21  public:
22   explicit Id2SliceLayer(const LayerParameter& param)
23       : Layer<Dtype>(param) {}
24   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
25       const vector<Blob<Dtype>*>& top);
26   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
27       const vector<Blob<Dtype>*>& top);
28 
29   virtual inline const char* type() const { return "Id2Slice"; }
30   virtual inline int ExactNumBottomBlobs() const { return 1; }
31   virtual inline int MinTopBlobs() const { return 1; }
32 
33  protected:
34   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
35       const vector<Blob<Dtype>*>& top);
36   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
37       const vector<Blob<Dtype>*>& top);
38   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
39       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
40   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
41       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
42 };
43 
44 }  // namespace caffe
45 
46 #endif  // CAFFE_ID2_SLICE_LAYER_HPP_

头文件,巨简单。。。

Cpp的代码,也非常简单,要留心id2_slice层的top有少独,每个的样都是bottom的一半。

 1 // created by miao
 2 #include <algorithm>
 3 #include <vector>
 4 
 5 #include "caffe/layers/id2_slice_layer.hpp"
 6 #include "caffe/util/math_functions.hpp"
 7 
 8 namespace caffe {
 9 
10 template <typename Dtype>
11 void Id2SliceLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
12       const vector<Blob<Dtype>*>& top) {
13 }
14 
15 template <typename Dtype>
16 void Id2SliceLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
17       const vector<Blob<Dtype>*>& top) {
18     vector<int> top_shape = bottom[0]->shape();
19     top_shape[0] /= 2;
20     top[0]->Reshape(top_shape);
21     top[1]->Reshape(top_shape);
22 }
23 
24 template <typename Dtype>
25 void Id2SliceLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
26       const vector<Blob<Dtype>*>& top) {
27     const int feature_size = bottom[0]->count(1);
28     for (int n = 0; n < bottom[0]->num(); ++ n) {
29         caffe_copy(
30                 feature_size, 
31                 bottom[0]->cpu_data() + n * feature_size, 
32                 top[n & 1]->mutable_cpu_data() + (n / 2) * feature_size
33                 );
34     }
35 }
36 
37 template <typename Dtype>
38 void Id2SliceLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
39       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
40     const int feature_size = bottom[0]->count(1);
41     for (int n = 0; n < bottom[0]->num(); ++ n) {
42         caffe_copy(
43                 feature_size,
44                 top[n & 1]->cpu_diff() + (n / 2) * feature_size,
45                 bottom[0]->mutable_cpu_diff() + n * feature_size
46                 );
47     }
48 }
49 
50 #ifdef CPU_ONLY
51 STUB_GPU(Id2SliceLayer);
52 #endif
53 
54 INSTANTIATE_CLASS(Id2SliceLayer);
55 REGISTER_LAYER_CLASS(Id2Slice);
56 
57 }  // namespace caffe

GPU上之落实,为了简单起见,也是直接调用了CPU的前馈函数。

 1 // created by miao
 2 #include <vector>
 3 
 4 #include "caffe/layers/id2_slice_layer.hpp"
 5 #include "caffe/util/math_functions.hpp"
 6 
 7 namespace caffe {
 8 template <typename Dtype>
 9 void Id2SliceLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
10       const vector<Blob<Dtype>*>& top) {
11     this->Forward_cpu(bottom, top);
12 }
13 
14 template <typename Dtype>
15 void Id2SliceLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
16       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
17     this->Backward_cpu(top, propagate_down, bottom);
18 }
19 
20 INSTANTIATE_LAYER_GPU_FUNCS(Id2SliceLayer);
21 
22 }  // namespace caffe

这么就是完了了feature的盘整。由于无利用新的参数,因此也非需修改caffe.proto。

亲身好效仿这个法对label来举行类似之操作。鉴于小喵比较累。。。这里就只是略的改ContrastiveLoss层的代码了。

先是步,在ContrastiveLossLayer中新增一个用来记录feature
pair是否是和一个identity的积极分子变量,取代原来的老三独bottom的效应。这样单待以前馈的下提前算好,就可替之前的老三独bottom来使,而非待再修改别的地方的代码。

为大家以的有利,小喵直接将修改之后的头文件粘贴出来(删掉注释)。新增的尽,用“added
by miao”这个注释标注出来。头文件就加了一行。

 1 #ifndef CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_
 2 #define CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_
 3 
 4 #include <vector>
 5 
 6 #include "caffe/blob.hpp"
 7 #include "caffe/layer.hpp"
 8 #include "caffe/proto/caffe.pb.h"
 9 
10 #include "caffe/layers/loss_layer.hpp"
11 
12 namespace caffe {
13 template <typename Dtype>
14 class ContrastiveLossLayer : public LossLayer<Dtype> {
15  public:
16   explicit ContrastiveLossLayer(const LayerParameter& param)
17       : LossLayer<Dtype>(param), diff_() {}
18   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
19       const vector<Blob<Dtype>*>& top);
20 
21   virtual inline int ExactNumBottomBlobs() const { return 3; }
22   virtual inline const char* type() const { return "ContrastiveLoss"; }
23   virtual inline bool AllowForceBackward(const int bottom_index) const {
24     return bottom_index != 2;
25   }
26  protected:
27   /// @copydoc ContrastiveLossLayer
28   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
29       const vector<Blob<Dtype>*>& top);
30   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
31       const vector<Blob<Dtype>*>& top);
32   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
33       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
34   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
35       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
36 
37   Blob<Dtype> diff_;  // cached for backward pass
38   Blob<Dtype> dist_sq_;  // cached for backward pass
39   Blob<Dtype> diff_sq_;  // tmp storage for gpu forward pass
40   Blob<Dtype> summer_vec_;  // tmp storage for gpu forward pass
41   Blob<Dtype> is_same_; // added by miao
42 };
43 }  // namespace caffe
44 
45 #endif  // CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_

来文件的改动也杀简单易行,这里只有贴出Cuda的一些。源文件,修改了与原本的bottom3连锁的地方。

  1 #include <algorithm>
  2 #include <vector>
  3 #include <iostream>
  4 #include "caffe/layers/contrastive_loss_layer.hpp"
  5 #include "caffe/util/math_functions.hpp"
  6 
  7 namespace caffe {
  8 
  9 template <typename Dtype>
 10 void ContrastiveLossLayer<Dtype>::Forward_gpu(
 11     const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
 12   const int count = bottom[0]->count();
 13   caffe_gpu_sub(
 14       count,
 15       bottom[0]->gpu_data(),  // a
 16       bottom[1]->gpu_data(),  // b
 17       diff_.mutable_gpu_data());  // a_i-b_i
 18   caffe_gpu_powx(
 19       count,
 20       diff_.mutable_gpu_data(),  // a_i-b_i
 21       Dtype(2),
 22       diff_sq_.mutable_gpu_data());  // (a_i-b_i)^2
 23   caffe_gpu_gemv(
 24       CblasNoTrans,
 25       bottom[0]->num(),
 26       bottom[0]->channels(),
 27       Dtype(1.0),
 28       diff_sq_.gpu_data(),  // (a_i-b_i)^2
 29       summer_vec_.gpu_data(),
 30       Dtype(0.0),
 31       dist_sq_.mutable_gpu_data());  // \Sum (a_i-b_i)^2
 32   Dtype margin = this->layer_param_.contrastive_loss_param().margin();
 33   bool legacy_version =
 34       this->layer_param_.contrastive_loss_param().legacy_version();
 35   Dtype loss(0.0);
 36   for (int i = 0; i < bottom[0]->num(); ++i) {
 37     // added by miao
 38     is_same_.mutable_cpu_data()[i] = (bottom[2]->cpu_data()[2 * i] == bottom[2]->cpu_data()[2 * i + 1])? 1:0;
 39     if (is_same_.cpu_data()[i] == 1) {  // similar pairs
 40       loss += dist_sq_.cpu_data()[i];
 41     } else {  // dissimilar pairs
 42       if (legacy_version) {
 43         loss += std::max(margin - dist_sq_.cpu_data()[i], Dtype(0.0));
 44       } else {
 45         Dtype dist = std::max(margin - sqrt(dist_sq_.cpu_data()[i]),
 46                               Dtype(0.0));
 47         loss += dist*dist;
 48       }
 49     }
 50   }
 51   loss = loss / static_cast<Dtype>(bottom[0]->num()) / Dtype(2);
 52   top[0]->mutable_cpu_data()[0] = loss;
 53 }
 54 
 55 template <typename Dtype>
 56 __global__ void CLLBackward(const int count, const int channels,
 57     const Dtype margin, const bool legacy_version, const Dtype alpha,
 58     const Dtype* y, const Dtype* diff, const Dtype* dist_sq,
 59     Dtype *bottom_diff) {
 60   CUDA_KERNEL_LOOP(i, count) {
 61     int n = i / channels;  // the num index, to access y and dist_sq
 62     if (static_cast<int>(y[n])) {  // similar pairs
 63       bottom_diff[i] = alpha * diff[i];
 64     } else {  // dissimilar pairs
 65       Dtype mdist(0.0);
 66       Dtype beta(0.0);
 67       if (legacy_version) {
 68         mdist = (margin - dist_sq[n]);
 69         beta = -alpha;
 70       } else {
 71         Dtype dist = sqrt(dist_sq[n]);
 72         mdist = (margin - dist);
 73         beta = -alpha * mdist / (dist + Dtype(1e-4)) * diff[i];
 74       }
 75       if (mdist > 0.0) {
 76         bottom_diff[i] = beta;
 77       } else {
 78         bottom_diff[i] = 0;
 79       }
 80     }
 81   }
 82 }
 83 
 84 template <typename Dtype>
 85 void ContrastiveLossLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
 86     const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
 87   for (int i = 0; i < 2; ++i) {
 88     if (propagate_down[i]) {
 89       const int count = bottom[0]->count();
 90       const int channels = bottom[0]->channels();
 91       Dtype margin = this->layer_param_.contrastive_loss_param().margin();
 92       const bool legacy_version =
 93           this->layer_param_.contrastive_loss_param().legacy_version();
 94       const Dtype sign = (i == 0) ? 1 : -1;
 95       const Dtype alpha = sign * top[0]->cpu_diff()[0] /
 96           static_cast<Dtype>(bottom[0]->num());
 97       // NOLINT_NEXT_LINE(whitespace/operators)
 98       CLLBackward<Dtype><<<CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS>>>(
 99           count, channels, margin, legacy_version, alpha,
100           is_same_.gpu_data(),  // pair similarity 0 or 1  added by miao
101           diff_.gpu_data(),  // the cached eltwise difference between a and b
102           dist_sq_.gpu_data(),  // the cached square distance between a and b
103           bottom[i]->mutable_gpu_diff());
104       CUDA_POST_KERNEL_CHECK;
105     }
106   }
107 }
108 
109 INSTANTIATE_LAYER_GPU_FUNCS(ContrastiveLossLayer);
110 
111 }  // namespace caffe

得小心的时节,前馈和后馈都待举行一些代码上之改动,虽说很底略,但也如小心。

 

迄今为止,基于Caffe的DeepID2的改总体到位。

 

只要您觉得本文对而发出扶持,那请小喵喝杯茶吧O(∩_∩)O

图片 1

 

转载请注明出处~

博客原文:http://www.miaoerduo.com/deep-learning/基于caffe的deepid2实现(中).html

二、精髓,DeepID2 Loss层

DeepID2即首论文关于verification
signal的有,给闹了一个用来监督verification的loss。

图片 2

其中,fi和fj举凡归一化之后的特性。

当fi和fj属于同一个identity的上,也即是yij=1时,loss是两者的L2距离,约束使得特征更加相近。

当fi和fj免属于跟一个identity的时刻,即yij=-1,这时的loss表示什么为?参数m又象征什么?

m在此间是margin的意,是一个足以活动安装的参数,表示巴之异identity的feature之间的相距。当半单feature的压倒margin时,说明网络已足以充分好的分别这半个特征,因此这是loss为0,当feature间的去小于margin时,loss则也(m-|fi

fj|)^2,表示尚用少单特征会重新好之分。因此这loss函数比较好的感应了咱们的急需,也尽管是DeepID2的算法思想。

夫Loss层实现起来似乎并无劳,前馈十分之简便。至于后馈,求导也非常简单。但是Caffe加入新层,需要以caffe.proto文件被,做有改,这为是极困扰小喵的地方。

可是出个好信息就是是:Caffe官网增加了ContrastiveLossLayer这个层!

官网的公文讲述如下:

Computes the contrastive loss
图片 3 where
图片 4.
This can be used to train siamese networks.

以及咱们的要是相同的。因此我们无待自己实现之层。

爱坏普奔之衍,小喵为专门关押了Caffe的文档,以及这里提到了siamese
network,发现此网络使用ContrastiveLossLayer的章程于独特,Caffe项目蒙的examples中生例子,感兴趣可以望。

ContrastiveLossLayer的输入,也就是是bottom有三有些,feature1、feature2、label,feature1和feature2凡各自对应之一定量组feature,而label则意味该对feature是否是属同一个identity,是吧,则为1,不是虽然为0。而且该层还提供一个参数margin,也就是是舆论的公式里面的m。

末的结论就是是,虽然咱无待自己写Loss层,但是还是得增加部分外加的交汇。

重中之重出2个,用于将特色归一化的NormalizationLayer以及用于将feature层转换成ContrastiveLossLayer的输入的重合,不妨命名也ID2SliceLayer。

其三、小问题,大智慧之Normalization Layer

斯归一化的重合用于将输入的feature
map进行归一化。Caffe官网并从未提供相关的重叠,因此我们得协调实现(或者从网上查找),这里我们还是选择自己来落实,顺便学习一下Caffe加层的艺。

Normalization层的前馈非常的简短,输入为一个向量x,输出为归一化之后的向量:

图片 5

至于后馈,需要求导,计算小有硌复杂,小喵在推演4全后才为闹如下表达式:

图片 6

里头x为输入的特征向量,为列向量。这里是拿整个feature map看做一个列向量。

懂了前馈后馈的算计规则,那么坏轻编写好之重叠了,这里小喵建议大家找找个Caffe已经产生矣底情节相近的层,照在改写。比如是Normalization层,没有其它层的参数,所以按照在ReLU类似之重叠就那个好编写。

之后便祭出我们的code:

 1 // create by miao
 2 // 主要实现了feature的归一化
 3 #ifndef CAFFE_NORMALIZATION_LAYER_HPP_
 4 #define CAFFE_NORMALIZATION_LAYER_HPP_
 5 
 6 #include <vector>
 7 
 8 #include "caffe/blob.hpp"
 9 #include "caffe/layer.hpp"
10 #include "caffe/proto/caffe.pb.h"
11 
12 #include "caffe/layers/neuron_layer.hpp"
13 
14 namespace caffe {
15 
16 template <typename Dtype>
17 class NormalizationLayer : public NeuronLayer<Dtype> {
18  public:
19   explicit NormalizationLayer(const LayerParameter& param)
20       : NeuronLayer<Dtype>(param) {}
21   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
22       const vector<Blob<Dtype>*>& top);
23   virtual inline const char* type() const { return "Normalization"; }
24   virtual inline int ExactNumBottomBlobs() const { return 1; }
25   virtual inline int ExactNumTopBlobs() const { return 1; }
26   
27  protected:
28   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
29       const vector<Blob<Dtype>*>& top);
30   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
31       const vector<Blob<Dtype>*>& top);
32   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
33       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
34   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
35       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
36   Blob<Dtype> norm_val_; // 记录每个feature的模
37 };
38 
39 }  // namespace caffe
40 
41 #endif  // CAFFE_NORMALIZATION_LAYER_HPP_

其一层的腔文件充分的简短,和ReLU的单局部区别就是看似的名字不相同,而且多了个分子变量norm_val_,用来记录每个feature的模值。

 1 // create by miao
 2 #include <vector>
 3 #include <cmath>
 4 #include "caffe/layers/normalization_layer.hpp"
 5 #include "caffe/util/math_functions.hpp"
 6 
 7 namespace caffe {
 8 
 9 template <typename Dtype>
10 void NormalizationLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
11         const vector<Blob<Dtype>*>& top) {
12     NeuronLayer<Dtype>::LayerSetUp(bottom, top);
13     CHECK_NE(top[0], bottom[0]) << this->type() << " Layer does not "
14         "allow in-place computation.";
15     norm_val_.Reshape(bottom[0]->shape(0), 1, 1, 1); // 申请norm的内存
16 }
17 
18 
19 template <typename Dtype> 
20 void NormalizationLayer<Dtype>::Forward_cpu(
21     const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
22 
23     Dtype *norm_val_cpu_data = norm_val_.mutable_cpu_data();
24     for (int n = 0; n < bottom[0]->shape(0); ++ n) {
25         // 计算每个c * h * w的区域的模
26         norm_val_cpu_data[n] = std::sqrt(static_cast<float>(
27                     caffe_cpu_dot<Dtype>(
28                         bottom[0]->count(1), 
29                         bottom[0]->cpu_data() + bottom[0]->offset(n), 
30                         bottom[0]->cpu_data() + bottom[0]->offset(n)
31                         )
32                     ));
33         // 将每个bottom归一化,输出到top
34         caffe_cpu_scale<Dtype>(
35                 top[0]->count(1), 
36                 1. / norm_val_cpu_data[n], 
37                 bottom[0]->cpu_data() + bottom[0]->offset(n), 
38                 top[0]->mutable_cpu_data() + top[0]->offset(n)
39                 );
40     }
41 }
42 
43 template <typename Dtype>
44 void NormalizationLayer<Dtype>::Backward_cpu(
45     const vector<Blob<Dtype>*>& top, 
46     const vector<bool>& propagate_down,
47     const vector<Blob<Dtype>*>& bottom) {
48     
49     const Dtype *norm_val_cpu_data = norm_val_.cpu_data();
50     const Dtype *top_diff = top[0]->cpu_diff();
51     Dtype *bottom_diff = bottom[0]->mutable_cpu_diff();
52     const Dtype *bottom_data = bottom[0]->cpu_data();
53 
54     caffe_copy(top[0]->count(), top_diff, bottom_diff);
55     
56     for (int n = 0; n < top[0]->shape(0); ++ n) {
57         Dtype a = - 1./(norm_val_cpu_data[n] * norm_val_cpu_data[n] * norm_val_cpu_data[n]) * caffe_cpu_dot<Dtype>(
58                 top[0]->count(1),
59                 top_diff + top[0]->offset(n),
60                 bottom_data + bottom[0]->offset(n)
61                 );
62         Dtype b = 1. / norm_val_cpu_data[n];
63         caffe_cpu_axpby<Dtype>(
64                 top[0]->count(1),
65                 a,
66                 bottom_data + bottom[0]->offset(n),
67                 b,
68                 bottom_diff + top[0]->offset(n)
69                 );
70     }
71 }
72 #ifdef CPU_ONLY
73 STUB_GPU(NormalizationLayer);
74 #endif
75 
76 INSTANTIATE_CLASS(NormalizationLayer);
77 REGISTER_LAYER_CLASS(Normalization);
78 
79 } // namespace caffe

 最后就是是GPU部分的代码,如果无在乎性能的话,直接以CUDA的内外馈里面调用CPU版的内外馈就推行。当然要了解CUDA的言辞,完全可形容一卖GPU版的代码。小喵这里就是偷懒了一下。。。

 1 // create by miao
 2 #include <vector>
 3 #include <cmath>
 4 #include "caffe/layers/normalization_layer.hpp"
 5 #include "caffe/util/math_functions.hpp"
 6 
 7 namespace caffe {
 8 
 9 template <typename Dtype> 
10 void NormalizationLayer<Dtype>::Forward_gpu(
11     const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
12     this->Forward_cpu(bottom, top);
13 }   
14 
15 template <typename Dtype>
16 void NormalizationLayer<Dtype>::Backward_gpu(
17     const vector<Blob<Dtype>*>& top, 
18     const vector<bool>& propagate_down,
19     const vector<Blob<Dtype>*>& bottom) {
20     this->Backward_cpu(top, propagate_down, bottom);
21 }
22 INSTANTIATE_LAYER_GPU_FUNCS(NormalizationLayer);
23 } // namespace caffe

 

这般,我们就形容了了Normalization层的有代码。

对此比较老版的Caffe,还需要修改/caffe_root/src/caffe/caffe.proto文件。而新版的Caffe只要以疯长参数的景况下才需要修改。我们的这Normalization层并不曾以新的参数,因此并不需要修改caffe.proto文件。

关于新版的Caffe为什么这么智能,原因实在就于当时有限执代码:

INSTANTIATE_CLASS(NormalizationLayer);
REGISTER_LAYER_CLASS(Normalization);

宏INSTANTIATE_CLASS在/caffe_root/include/caffe/common.hpp中定义。

宏REGISTER_LAYER_CLASS在/caffe_root/include/caffe/layer_factory.hpp中定义。

谢兴趣可以活动查阅。

 

假若你认为本文对你发出帮扶,那请小喵喝杯茶吧O(∩_∩)O

图片 7

 

 

转载请注明出处~

标签:, , ,

Your Comments

近期评论

    功能


    网站地图xml地图