依据Caffe的Large Margin Softmax葡京娱乐网 Loss的落成(上)

小喵的唠叨话:在写完上1遍的博客之后,已经过去了二个月的时刻,小喵在此时期,做了大批量的尝试工作,最后在动用的DeepID2的点子之后,取得了很不利的结果。此次呢,首要讲述三个相比较新的舆论中的方法,L-Softmax,传说单model在LFW上能落得98.71%的等错误率。更主要的是,小喵认为那几个点子和DeepID2并不争持,假使双方能够填补,只怕单model达到99%+将不是愿意。

小喵的唠叨话:在写完上1次的博客之后,已经离世了一个月的小运,小喵在此期间,做了汪洋的试行工作,最后在采纳的DeepID2的不二法门之后,取得了很正确的结果。这一次呢,首要描述三个比较新的杂谈中的方法,L-Softmax,听他们讲单model在LFW上能达到规定的标准98.71%的等错误率。更器重的是,小喵认为这几个主意和DeepID2并不抵触,假使两者可以互补,或者单model达到99%+将不是可望。

 

 

重复推销一下~

再也推销一下~

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

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

博客原著:  http://www.miaoerduo.com/deep-learning/基于caffe的large-ma…ftmax-loss的实现(上).html 

博客原来的作品:  http://www.miaoerduo.com/deep-learning/基于caffe的large-ma…ftmax-loss的实现(上).html 

 

 

和上一篇博客一样,小喵对读者做了之类的假使:

和上一篇博客一样,小喵对读者做了如下的假使:

  1. 询问Deep Learning的基本知识。
  2. 细心阅读过L-Softmax的舆论,通晓当中的数学推理。
  3. 接纳Caffe作为教练框架。
  4. 不畏不满意上述3条,也能持久的学习。
  1. 刺探Deep Learning的基本知识。
  2. 密切阅读过L-Softmax的舆论,精通在那之中的数学推理。
  3. 应用Caffe作为教练框架。
  4. 不畏不满足上述3条,也能持久的学习。

L-Softmax的论文:Large-Margin Softmax Loss for Convolutional Neutral
Networks

L-Softmax的论文:Large-Margin Softmax Loss for Convolutional Neutral
Networks

谷歌一下,第②条应该正是舆论的地点,鉴于大家时刻有限,小喵把原来的书文地址也贴出来了,但不保险长时间有效。http://jmlr.org/proceedings/papers/v48/liud16.pdf
那里大家也将全方位类别分几片段来讲。

谷歌一下,第③条应该便是舆论的地方,鉴于大家时刻少于,小喵把原来的书文地址也贴出来了,但不保证长期有效。http://jmlr.org/proceedings/papers/v48/liud16.pdf
那里大家也将整体体系分几有的来讲。

一、margin与lambda

margin和lambda那四个参数是大家那篇博客的首要。也是整篇随想的要紧。对于分类的职责,每种样本都会有N的输出的分数(N的品种),要是在教练中,人为的使科学体系的得分变小,相当于说加大了界别正确类别的难度,那么网络就会学习出更有分别能力的个性,并且加大类间的相距。作者选择的加大难度的不二法门便是改变最终一个FC层中的weight和个性之间的角度值,角度增大的翻番正是margin,从而使特定类型的得分变小。而第3个参数lambda是为着幸免互连网不毁灭而设定的,我们现在会讲到。

为了贯彻这几个效应,我们要求统一筹划两个新的层,large_margin_inner_product_layer。那么些层和一般的inner_product_layer很一般,但是多了一定项目削弱的意义。
考虑到这么些层是有参数的,大家需求在caffe.proto(caffe_home/src/caffe/proto/caffe.proto)中做一些改动。那里的概念是依照protobuf的语法写的,不难的修改只要照着其余的参数来改写就好。
首先定义大家的这几个层的参数。

 1 message LargeMarginInnerProductParameter {
 2   optional uint32 num_output = 1; // The number of outputs for the layer
 3   optional bool bias_term = 2 [default = true]; // whether to have bias terms
 4   optional FillerParameter weight_filler = 3; // The filler for the weight
 5   optional FillerParameter bias_filler = 4; // The filler for the bias
 6 
 7   // The first axis to be lumped into a single inner product computation;
 8   // all preceding axes are retained in the output.
 9   // May be negative to index from the end (e.g., -1 for the last axis).
10   optional int32 axis = 5 [default = 1];
11   // Specify whether to transpose the weight matrix or not.
12   // If transpose == true, any operations will be performed on the transpose
13   // of the weight matrix. The weight matrix itself is not going to be transposed
14   // but rather the transfer flag of operations will be toggled accordingly.
15   optional bool transpose = 6 [default = false];
16   optional uint32 margin = 7 [default = 1];
17   optional float lambda = 8 [default = 0];
18 }

参数的概念和InnerProductParameter分外相像,只是多了多少个参数margin和lambda。
之后在LayerParameter添加3个可选参数(照着InnerProductParameter写就好)。

optional LargeMarginInnerProductParameter large_margin_inner_product_param = 147;

此刻,喵粉恐怕很在意这几个147是怎么回事。其实呢,在protobuf中,各个组织中的变量都亟需贰个id,只要保障不重复即可。我们在LayerParameter的最发轫能够见见那般一行注释:
葡京娱乐网 1

证实下3个灵光的id是147。那里大家新加的参数就一挥而就占用了这几个id。

修改之后,提议把注释改一下(不要人为的挖坑): LayerParameter next
available layer-specific ID: 148 (last added:
large_margin_inner_product_param)

幸免事后再新加层的时候出问题。

工作完成,大家就足以在train_val.prototxt中用那种艺术使用那些新层了(具体的运用,前面再说):

 1 layer {
 2   name: "fc2"
 3   type: "LargeMarginInnerProduct"
 4   bottom: "fc1"
 5   bottom: "label"
 6   top: "fc2"
 7   param {
 8     lr_mult: 1
 9     decay_mult: 1
10   }
11   param {
12     lr_mult: 0
13     decay_mult: 0
14   }
15   large_margin_inner_product_param {
16     num_output: 10000
17     margin: 2
18     lambda: 0
19     weight_filler {
20       type: "xavier"
21     }    
22   }
23 }

 

一、margin与lambda

margin和lambda那五个参数是我们那篇博客的首要。也是整篇杂谈的主要。对于分类的职务,每个样本都会有N的出口的分数(N的品种),倘使在陶冶中,人为的使科学类别的得分变小,也正是说加大了界别正确类别的难度,那么互联网就会学习出更有分别能力的特色,并且加大类间的相距。小编选取的加大难度的点子便是改变最终三个FC层中的weight和特点之间的角度值,角度增大的倍数就是margin,从而使特定项目标得分变小。而第②个参数lambda是为着防止互连网不消退而设定的,大家之后会讲到。

为了落实那一个功效,大家要求规划二个新的层,large_margin_inner_product_layer。那几个层和一般的inner_product_layer很相像,但是多了特定类型削弱的职能。
考虑到那些层是有参数的,大家要求在caffe.proto(caffe_home/src/caffe/proto/caffe.proto)中做一些改动。那里的定义是比照protobuf的语法写的,简单的改动只要照着其余的参数来改写就好。
首先定义我们的这么些层的参数。

 1 message LargeMarginInnerProductParameter {
 2   optional uint32 num_output = 1; // The number of outputs for the layer
 3   optional bool bias_term = 2 [default = true]; // whether to have bias terms
 4   optional FillerParameter weight_filler = 3; // The filler for the weight
 5   optional FillerParameter bias_filler = 4; // The filler for the bias
 6 
 7   // The first axis to be lumped into a single inner product computation;
 8   // all preceding axes are retained in the output.
 9   // May be negative to index from the end (e.g., -1 for the last axis).
10   optional int32 axis = 5 [default = 1];
11   // Specify whether to transpose the weight matrix or not.
12   // If transpose == true, any operations will be performed on the transpose
13   // of the weight matrix. The weight matrix itself is not going to be transposed
14   // but rather the transfer flag of operations will be toggled accordingly.
15   optional bool transpose = 6 [default = false];
16   optional uint32 margin = 7 [default = 1];
17   optional float lambda = 8 [default = 0];
18 }

参数的定义和InnerProductParameter非凡相似,只是多了五个参数margin和lambda。
之后在LayerParameter添加三个可选参数(照着InnerProductParameter写就好)。

optional LargeMarginInnerProductParameter large_margin_inner_product_param = 147;

此时,喵粉或然很在意那几个147是怎么回事。其实呢,在protobuf中,种种组织中的变量都须求3个id,只要保障不另行即可。大家在LayerParameter的最开头能够见见如此一行注释:
葡京娱乐网 2

申明下三个管用的id是147。那里大家新加的参数就决然占用了那些id。

修改之后,提出把注释改一下(不要人为的挖坑): LayerParameter next
available layer-specific ID: 148 (last added:
large_margin_inner_product_param)

防止今后再新加层的时候出题目。

做事甘休,大家就能够在train_val.prototxt中用那种格局选取那几个新层了(具体的施用,后边再说):

 1 layer {
 2   name: "fc2"
 3   type: "LargeMarginInnerProduct"
 4   bottom: "fc1"
 5   bottom: "label"
 6   top: "fc2"
 7   param {
 8     lr_mult: 1
 9     decay_mult: 1
10   }
11   param {
12     lr_mult: 0
13     decay_mult: 0
14   }
15   large_margin_inner_product_param {
16     num_output: 10000
17     margin: 2
18     lambda: 0
19     weight_filler {
20       type: "xavier"
21     }    
22   }
23 }

 

二,运筹帷幄之成员变量

大家恰万幸caffe.proto中,添加了新参数的定义。而实在,我们还从未那个层的现实落到实处。那部分,首要介绍我们需求的近日变量。
首先,大家要理清一切总计的流水生产线。

先看前馈。

第2步,需供给出W和x的夹角的余弦值:

\[\cos(\theta_j)=\frac{W_j^Tx_i}{\|W_j\|\|x_i\|}\]

第①步,总括m倍角度的余弦值:

\[\cos(m\theta_i)=\sum_n(-1)^n{C_m^{2n}\cos^{m-2n}(\theta_i)\cdot(1-\cos(\theta_i)^2)^n},
(2n\leq m)\]

其三步,总结前馈:

\[f_{y_{i}}=(-1)^k\cdot\|W_{y_{i}}\|\|x_{i}\|\cos(m\theta_i)-2k\cdot\|W_{y_i}\|\|x_i\|\]

k是根据$\cos(\theta)$的取值决定的。

后馈比前馈要复杂一些,可是使用的变量也是同样的。
由此大家得以编写制定自身的头文件了。

 1 #ifndef CAFFE_LARGE_MARGIN_INNER_PRODUCT_LAYER_HPP_
 2 #define CAFFE_LARGE_MARGIN_INNER_PRODUCT_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 namespace caffe {
11 
12 template <typename Dtype>
13 class LargeMarginInnerProductLayer : public Layer<Dtype> {
14  public:
15   explicit LargeMarginInnerProductLayer(const LayerParameter& param)
16       : Layer<Dtype>(param) {}
17   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
18       const vector<Blob<Dtype>*>& top);
19   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
20       const vector<Blob<Dtype>*>& top);
21 
22   virtual inline const char* type() const { return "LargeMarginInnerProduct"; }
23   // edited by miao
24   // LM_FC层有两个bottom
25   virtual inline int ExactNumBottomBlobs() const { return 2; }
26   // end edited
27   virtual inline int ExactNumTopBlobs() const { return 1; }
28 
29  protected:
30   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
31       const vector<Blob<Dtype>*>& top);
32   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
33       const vector<Blob<Dtype>*>& top);
34   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
35       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
36   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
37       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
38 
39   int M_;
40   int K_;
41   int N_;
42   bool bias_term_;
43   Blob<Dtype> bias_multiplier_;
44   bool transpose_;  ///< if true, assume transposed weights
45 
46   // added by miao
47 
48   // 一些常数
49   Blob<Dtype> cos_theta_bound_;   // 区间边界的cos值
50   Blob<int> k_;                   // 当前角度theta所在的区间的位置
51   Blob<int> C_M_N_;               // 组合数
52   unsigned int margin;            // margin
53   float lambda;                   // lambda
54 
55   Blob<Dtype> wx_;                // wjT * xi
56   Blob<Dtype> abs_w_;             // ||wj|| 
57   Blob<Dtype> abs_x_;             // ||xi||
58   Blob<Dtype> cos_t_;             // cos(theta)
59   Blob<Dtype> cos_mt_;            // cos(margin * theta)
60 
61   Blob<Dtype> dydw_;              // 输出对w的导数
62   Blob<Dtype> dydx_;              // 输出对x的导数
63   // end added
64 };
65 
66 }  // namespace caffe
67 
68 #endif  // CAFFE_LARGE_MARGIN_INNER_PRODUCT_LAYER_HPP_

此地首如果复制了inner_product_layer.hpp,然后做了一些修改。具体是充实了几个成员变量,同时改了ExactNumBottomBlobs的再次来到值,因为我们的这么些层磁带bottom须求八个,前一层的feature和范本的label。

二,运筹帷幄之成员变量

大家刚刚在caffe.proto中,添加了新参数的定义。而其实,大家还尚无那几个层的现实贯彻。这一部分,首要介绍大家供给的一时半刻变量。
首先,咱们要理清一切总括的流程。

先看前馈。

率先步,需须求出W和x的夹角的余弦值:

\[\cos(\theta_j)=\frac{W_j^Tx_i}{\|W_j\|\|x_i\|}\]

其次步,总括m倍角度的余弦值:

\[\cos(m\theta_i)=\sum_n(-1)^n{C_m^{2n}\cos^{m-2n}(\theta_i)\cdot(1-\cos(\theta_i)^2)^n},
(2n\leq m)\]

其三步,计算前馈:

\[f_{y_{i}}=(-1)^k\cdot\|W_{y_{i}}\|\|x_{i}\|\cos(m\theta_i)-2k\cdot\|W_{y_i}\|\|x_i\|\]

k是根据$\cos(\theta)$的取值决定的。

后馈比前馈要复杂一些,可是使用的变量也是均等的。
因而大家可以编写本人的头文件了。

 1 #ifndef CAFFE_LARGE_MARGIN_INNER_PRODUCT_LAYER_HPP_
 2 #define CAFFE_LARGE_MARGIN_INNER_PRODUCT_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 namespace caffe {
11 
12 template <typename Dtype>
13 class LargeMarginInnerProductLayer : public Layer<Dtype> {
14  public:
15   explicit LargeMarginInnerProductLayer(const LayerParameter& param)
16       : Layer<Dtype>(param) {}
17   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
18       const vector<Blob<Dtype>*>& top);
19   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
20       const vector<Blob<Dtype>*>& top);
21 
22   virtual inline const char* type() const { return "LargeMarginInnerProduct"; }
23   // edited by miao
24   // LM_FC层有两个bottom
25   virtual inline int ExactNumBottomBlobs() const { return 2; }
26   // end edited
27   virtual inline int ExactNumTopBlobs() const { return 1; }
28 
29  protected:
30   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
31       const vector<Blob<Dtype>*>& top);
32   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
33       const vector<Blob<Dtype>*>& top);
34   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
35       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
36   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
37       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
38 
39   int M_;
40   int K_;
41   int N_;
42   bool bias_term_;
43   Blob<Dtype> bias_multiplier_;
44   bool transpose_;  ///< if true, assume transposed weights
45 
46   // added by miao
47 
48   // 一些常数
49   Blob<Dtype> cos_theta_bound_;   // 区间边界的cos值
50   Blob<int> k_;                   // 当前角度theta所在的区间的位置
51   Blob<int> C_M_N_;               // 组合数
52   unsigned int margin;            // margin
53   float lambda;                   // lambda
54 
55   Blob<Dtype> wx_;                // wjT * xi
56   Blob<Dtype> abs_w_;             // ||wj|| 
57   Blob<Dtype> abs_x_;             // ||xi||
58   Blob<Dtype> cos_t_;             // cos(theta)
59   Blob<Dtype> cos_mt_;            // cos(margin * theta)
60 
61   Blob<Dtype> dydw_;              // 输出对w的导数
62   Blob<Dtype> dydx_;              // 输出对x的导数
63   // end added
64 };
65 
66 }  // namespace caffe
67 
68 #endif  // CAFFE_LARGE_MARGIN_INNER_PRODUCT_LAYER_HPP_

此地关键是复制了inner_product_layer.hpp,然后做了少数改动。具体是扩大了多少个分子变量,同时改了ExactNumBottomBlobs的重临值,因为我们的那个层磁带bottom要求多个,前一层的feature和样本的label。

叁 、内部存款和储蓄器和常量的初步化

那部分,重要给我们的依次成员变量分配内部存款和储蓄器,同时给多少个常量举办开首化。那里也是照着inner_product_layer.cpp来写的,在setup的时候,扩大了有个别用于先导化的代码,并删除了forward_cpu和backwark_cpu的现实性完结。

修改之后的代码如下:

  1 #include <vector>
  2 #include <cmath>
  3 
  4 #include "caffe/filler.hpp"
  5 #include "caffe/layers/large_margin_inner_product_layer.hpp"
  6 #include "caffe/util/math_functions.hpp"
  7 
  8 #define PI 3.14159265
  9 
 10 namespace caffe {
 11 
 12 int factorial(int n) {
 13   if (0 == n) return 1;
 14   int f = 1;
 15   while (n) {
 16     f *= n;
 17     -- n;
 18   }
 19   return f;
 20 }
 21 
 22 template <typename Dtype>
 23 void LargeMarginInnerProductLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
 24       const vector<Blob<Dtype>*>& top) {
 25 
 26   const int axis = bottom[0]->CanonicalAxisIndex(
 27       this->layer_param_.large_margin_inner_product_param().axis());
 28   // added by miao
 29   std::vector<int> wx_shape(1);
 30   wx_shape[0] = bottom[0]->shape(0);
 31   this->wx_.Reshape(wx_shape);
 32   this->abs_w_.Reshape(wx_shape);
 33   this->abs_x_.Reshape(wx_shape);
 34   this->k_.Reshape(wx_shape);
 35   this->cos_t_.Reshape(wx_shape);
 36   this->cos_mt_.Reshape(wx_shape);
 37 
 38   std::vector<int> cos_theta_bound_shape(1);
 39   this->margin = static_cast<unsigned int>(this->layer_param_.large_margin_inner_product_param().margin());
 40   cos_theta_bound_shape[0] = this->margin + 1;
 41   this->cos_theta_bound_.Reshape(cos_theta_bound_shape);
 42   for (int k = 0; k <= this->margin; ++ k) {
 43     this->cos_theta_bound_.mutable_cpu_data()[k] = std::cos(PI * k / this->margin);
 44   }
 45   this->C_M_N_.Reshape(cos_theta_bound_shape);
 46   for (int n = 0; n <= this->margin; ++ n) {
 47     this->C_M_N_.mutable_cpu_data()[n] = factorial(this->margin) / factorial(this->margin - n) / factorial(n);
 48   }
 49 
 50   // d size
 51   std::vector<int> d_shape(2);
 52   d_shape[0] = bottom[0]->shape(0);
 53   d_shape[1] = bottom[0]->count(axis);
 54   this->dydw_.Reshape(d_shape);
 55   this->dydx_.Reshape(d_shape);
 56 
 57   this->lambda = this->layer_param_.large_margin_inner_product_param().lambda();
 58   // end added
 59 
 60   transpose_ = false; // 坚决不转置!
 61 
 62   const int num_output = this->layer_param_.large_margin_inner_product_param().num_output();
 63   bias_term_ = this->layer_param_.large_marin_inner_product_param().bias_term();
 64   N_ = num_output;
 65   
 66   // Dimensions starting from "axis" are "flattened" into a single
 67   // length K_ vector. For example, if bottom[0]'s shape is (N, C, H, W),
 68   // and axis == 1, N inner products with dimension CHW are performed.
 69   K_ = bottom[0]->count(axis);
 70   // Check if we need to set up the weights
 71   if (this->blobs_.size() > 0) {
 72     LOG(INFO) << "Skipping parameter initialization";
 73   } else {
 74     if (bias_term_) {
 75       this->blobs_.resize(2);
 76     } else {
 77       this->blobs_.resize(1);
 78     }
 79     // Initialize the weights
 80     vector<int> weight_shape(2);
 81     if (transpose_) {
 82       weight_shape[0] = K_;
 83       weight_shape[1] = N_;
 84     } else {
 85       weight_shape[0] = N_;
 86       weight_shape[1] = K_;
 87     }
 88     this->blobs_[0].reset(new Blob<Dtype>(weight_shape));
 89     // fill the weights
 90     shared_ptr<Filler<Dtype> > weight_filler(GetFiller<Dtype>(
 91         this->layer_param_.large_margin_inner_product_param().weight_filler()));
 92     weight_filler->Fill(this->blobs_[0].get());
 93     // If necessary, intiialize and fill the bias term
 94     if (bias_term_) {
 95       vector<int> bias_shape(1, N_);
 96       this->blobs_[1].reset(new Blob<Dtype>(bias_shape));
 97       shared_ptr<Filler<Dtype> > bias_filler(GetFiller<Dtype>(
 98           this->layer_param_.inner_product_param().bias_filler()));
 99       bias_filler->Fill(this->blobs_[1].get());
100     }   
101 
102   }  // parameter initialization
103   this->param_propagate_down_.resize(this->blobs_.size(), true);
104 }
105 
106 template <typename Dtype>
107 void LargeMarginInnerProductLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
108       const vector<Blob<Dtype>*>& top) {
109   // Figure out the dimensions
110   const int axis = bottom[0]->CanonicalAxisIndex(
111       this->layer_param_.large_margin_inner_product_param().axis());
112   const int new_K = bottom[0]->count(axis);
113   CHECK_EQ(K_, new_K)
114       << "Input size incompatible with large margin inner product parameters.";
115   // The first "axis" dimensions are independent inner products; the total
116   // number of these is M_, the product over these dimensions.
117   M_ = bottom[0]->count(0, axis);
118   // The top shape will be the bottom shape with the flattened axes dropped,
119   // and replaced by a single axis with dimension num_output (N_).
120   vector<int> top_shape = bottom[0]->shape();
121   top_shape.resize(axis + 1);
122   top_shape[axis] = N_;
123   top[0]->Reshape(top_shape);
124 }
125 
126 template <typename Dtype>
127 void LargeMarginInnerProductLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
128     const vector<Blob<Dtype>*>& top) {
129   // not implement
130 }
131 
132 template <typename Dtype>
133 void LargeMarginInnerProductLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
134     const vector<bool>& propagate_down,
135     const vector<Blob<Dtype>*>& bottom) {
136   // not implement
137 }
138 
139 #ifdef CPU_ONLY
140 STUB_GPU(LargeMarginInnerProductLayer);
141 #endif
142 
143 INSTANTIATE_CLASS(LargeMarginInnerProductLayer);
144 REGISTER_LAYER_CLASS(LargeMarginInnerProduct);
145 
146 }  // namespace caffe

至此,large_margin_inner_product_layer的预备工作就做完了。下一篇博客,咱们来详细的座谈前馈的求实达成。

 

即便你认为本文对您有扶持,那请小喵喝杯茶啊O(∩_∩)O
小喵为了写公式,还特地学习了$\LaTeX$。

葡京娱乐网 3

 

转发请注解出处~

叁 、内部存款和储蓄器和常量的起始化

那有的,首要给大家的相继成员变量分配内部存款和储蓄器,同时给多少个常量实行初叶化。这里也是照着inner_product_layer.cpp来写的,在setup的时候,增添了有的用以开首化的代码,并删除了forward_cpu和backwark_cpu的有血有肉落到实处。

修改以后的代码如下:

  1 #include <vector>
  2 #include <cmath>
  3 
  4 #include "caffe/filler.hpp"
  5 #include "caffe/layers/large_margin_inner_product_layer.hpp"
  6 #include "caffe/util/math_functions.hpp"
  7 
  8 #define PI 3.14159265
  9 
 10 namespace caffe {
 11 
 12 int factorial(int n) {
 13   if (0 == n) return 1;
 14   int f = 1;
 15   while (n) {
 16     f *= n;
 17     -- n;
 18   }
 19   return f;
 20 }
 21 
 22 template <typename Dtype>
 23 void LargeMarginInnerProductLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
 24       const vector<Blob<Dtype>*>& top) {
 25 
 26   const int axis = bottom[0]->CanonicalAxisIndex(
 27       this->layer_param_.large_margin_inner_product_param().axis());
 28   // added by miao
 29   std::vector<int> wx_shape(1);
 30   wx_shape[0] = bottom[0]->shape(0);
 31   this->wx_.Reshape(wx_shape);
 32   this->abs_w_.Reshape(wx_shape);
 33   this->abs_x_.Reshape(wx_shape);
 34   this->k_.Reshape(wx_shape);
 35   this->cos_t_.Reshape(wx_shape);
 36   this->cos_mt_.Reshape(wx_shape);
 37 
 38   std::vector<int> cos_theta_bound_shape(1);
 39   this->margin = static_cast<unsigned int>(this->layer_param_.large_margin_inner_product_param().margin());
 40   cos_theta_bound_shape[0] = this->margin + 1;
 41   this->cos_theta_bound_.Reshape(cos_theta_bound_shape);
 42   for (int k = 0; k <= this->margin; ++ k) {
 43     this->cos_theta_bound_.mutable_cpu_data()[k] = std::cos(PI * k / this->margin);
 44   }
 45   this->C_M_N_.Reshape(cos_theta_bound_shape);
 46   for (int n = 0; n <= this->margin; ++ n) {
 47     this->C_M_N_.mutable_cpu_data()[n] = factorial(this->margin) / factorial(this->margin - n) / factorial(n);
 48   }
 49 
 50   // d size
 51   std::vector<int> d_shape(2);
 52   d_shape[0] = bottom[0]->shape(0);
 53   d_shape[1] = bottom[0]->count(axis);
 54   this->dydw_.Reshape(d_shape);
 55   this->dydx_.Reshape(d_shape);
 56 
 57   this->lambda = this->layer_param_.large_margin_inner_product_param().lambda();
 58   // end added
 59 
 60   transpose_ = false; // 坚决不转置!
 61 
 62   const int num_output = this->layer_param_.large_margin_inner_product_param().num_output();
 63   bias_term_ = this->layer_param_.large_marin_inner_product_param().bias_term();
 64   N_ = num_output;
 65   
 66   // Dimensions starting from "axis" are "flattened" into a single
 67   // length K_ vector. For example, if bottom[0]'s shape is (N, C, H, W),
 68   // and axis == 1, N inner products with dimension CHW are performed.
 69   K_ = bottom[0]->count(axis);
 70   // Check if we need to set up the weights
 71   if (this->blobs_.size() > 0) {
 72     LOG(INFO) << "Skipping parameter initialization";
 73   } else {
 74     if (bias_term_) {
 75       this->blobs_.resize(2);
 76     } else {
 77       this->blobs_.resize(1);
 78     }
 79     // Initialize the weights
 80     vector<int> weight_shape(2);
 81     if (transpose_) {
 82       weight_shape[0] = K_;
 83       weight_shape[1] = N_;
 84     } else {
 85       weight_shape[0] = N_;
 86       weight_shape[1] = K_;
 87     }
 88     this->blobs_[0].reset(new Blob<Dtype>(weight_shape));
 89     // fill the weights
 90     shared_ptr<Filler<Dtype> > weight_filler(GetFiller<Dtype>(
 91         this->layer_param_.large_margin_inner_product_param().weight_filler()));
 92     weight_filler->Fill(this->blobs_[0].get());
 93     // If necessary, intiialize and fill the bias term
 94     if (bias_term_) {
 95       vector<int> bias_shape(1, N_);
 96       this->blobs_[1].reset(new Blob<Dtype>(bias_shape));
 97       shared_ptr<Filler<Dtype> > bias_filler(GetFiller<Dtype>(
 98           this->layer_param_.inner_product_param().bias_filler()));
 99       bias_filler->Fill(this->blobs_[1].get());
100     }   
101 
102   }  // parameter initialization
103   this->param_propagate_down_.resize(this->blobs_.size(), true);
104 }
105 
106 template <typename Dtype>
107 void LargeMarginInnerProductLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
108       const vector<Blob<Dtype>*>& top) {
109   // Figure out the dimensions
110   const int axis = bottom[0]->CanonicalAxisIndex(
111       this->layer_param_.large_margin_inner_product_param().axis());
112   const int new_K = bottom[0]->count(axis);
113   CHECK_EQ(K_, new_K)
114       << "Input size incompatible with large margin inner product parameters.";
115   // The first "axis" dimensions are independent inner products; the total
116   // number of these is M_, the product over these dimensions.
117   M_ = bottom[0]->count(0, axis);
118   // The top shape will be the bottom shape with the flattened axes dropped,
119   // and replaced by a single axis with dimension num_output (N_).
120   vector<int> top_shape = bottom[0]->shape();
121   top_shape.resize(axis + 1);
122   top_shape[axis] = N_;
123   top[0]->Reshape(top_shape);
124 }
125 
126 template <typename Dtype>
127 void LargeMarginInnerProductLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
128     const vector<Blob<Dtype>*>& top) {
129   // not implement
130 }
131 
132 template <typename Dtype>
133 void LargeMarginInnerProductLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
134     const vector<bool>& propagate_down,
135     const vector<Blob<Dtype>*>& bottom) {
136   // not implement
137 }
138 
139 #ifdef CPU_ONLY
140 STUB_GPU(LargeMarginInnerProductLayer);
141 #endif
142 
143 INSTANTIATE_CLASS(LargeMarginInnerProductLayer);
144 REGISTER_LAYER_CLASS(LargeMarginInnerProduct);
145 
146 }  // namespace caffe

至此,large_margin_inner_product_layer的准备干活就做完了。下一篇博客,大家来详细的座谈前馈的切实落到实处。

 

一经你觉得本文对您有援救,那请小喵喝杯茶啊O(∩_∩)O
小喵为了写公式,还尤其学习了$\LaTeX$。

葡京娱乐网 4

 

转发请声明出处~