caffe源碼解析之添加新的Layer(maxout)

本文分爲兩部分,先寫一個入門的教程,然後再給出自己添加maxout與NIN的layer的方法

(一)

其實在Github上已經有答案了(https://github.com/BVLC/caffe/issues/684

Here's roughly the process I follow.

  1. Add a class declaration for your layer to the appropriate one of common_layers.hppdata_layers.hpp,loss_layers.hppneuron_layers.hpp, or vision_layers.hpp. Include an inline implementation oftype and the *Blobs() methods to specify blob number requirements. Omit the *_gpu declarations if you'll only be implementing CPU code.
  2. Implement your layer in layers/your_layer.cpp.
    • SetUp for initialization: reading parameters, allocating buffers, etc.
    • Forward_cpu for the function your layer computes
    • Backward_cpu for its gradient
  3. (Optional) Implement the GPU versions Forward_gpu and Backward_gpu in layers/your_layer.cu.
  4. Add your layer to proto/caffe.proto, updating the next available ID. Also declare parameters, if needed, in this file.
  5. Make your layer createable by adding it to layer_factory.cpp.
  6. Write tests in test/test_your_layer.cpp. Use test/test_gradient_check_util.hpp to check that your Forward and Backward implementations are in numerical agreement.
上面是一個大致的流程,我就直接翻譯過來吧,因爲我自己琢磨出來的步驟跟這個是一樣的。在這裏,我們就添加一個Wtf_Layer,然後作用跟Convolution_Layer一模一樣。注意這裏的命名方式,Wtf第一個字母大寫,剩下的小寫,算是一個命名規範吧,強迫症表示很舒服。

1. 首先確定要添加的layer的類型,是common_layer 還是 data_layer 還是loss_layer, neuron_layer, vision_layer ,這裏的Wtf_Layer肯定是屬vision_layer了,所以打開vision_layers.hpp 然後複製convolution_layer的相關代碼,把類名還有構造函數的名字改爲WtfLayer,如果沒有用到GPU運算,那麼把裏面的帶GPU的函數都刪掉

2. 將Wtf_layer.cpp 添加到src\caffe\layers文件夾中,代碼內容複製convolution_layer.cpp 把對應的類名修改(可以搜一下conv關鍵字,然後改爲Wtf)

3. 假如有gpu的代碼就添加響應的Wtf_layer.cu (這裏不添加了)

4. 修改proto/caffe.proto文件,找到LayerType,添加WTF,並更新ID(新的ID應該是34)。假如說Wtf_Layer有參數,比如Convolution肯定是有參數的,那麼添加WtfParameter類

5. 在layer_factory.cpp中添加響應的代碼,就是一堆if ... else的那片代碼

6. 這個可以不做,但是爲了結果還是做一個,就是寫一個測試文件,檢查前向後向傳播的數據是否正確。gradient_check的原理可以參考UFLDL教程的對應章節


之後我會更新我自己寫的maxout_layer的demo,在這立一個flag以鞭策自己完成吧╮(╯▽╰)╭


(二) 如何添加maxout_layer

表示被bengio的maxout給搞鬱悶了,自己擺出一個公式巴拉巴拉說了一堆,結果用到卷積層的maxout卻給的另一種方案,吐槽無力,不過後來又想了下應該是bengio沒表述清楚的問題。


我的maxout的算法思路是這樣的,首先要確定一個group_size變量,表示最大值是在group_size這樣一個規模的集合下挑選出來的,簡而言之就是給定group_size個數,取最大。確定好group_size變量,然後讓卷積層的output_num變爲原來的group_size倍,這樣輸出的featuremap的個數就變爲原來的group_size倍,然後以group_size爲一組劃分這些featuremap,每組裏面挑出響應最大的點構成一個新的featuremap,這樣就得到了maxout層的輸出。


                                                       

要是還不明白我就拿上面的圖來說一下,上面一共9張圖,相當於卷積層輸出9張featuremap,我們每3個爲一組,那麼maxout層輸出9/3=3張featuremap,對於每組featuremaps,比如我們挑出綠色的三張featuremaps,每張大小爲w*h,那麼聲明一個新的output_featuremap大小爲w*h,遍歷output_featuremap的每個點,要賦的數值爲三張綠色featuremap對應點的最大的那個,也就是三個數裏面選最大的,這樣就輸出了一張output_featuremap,剩下的組類似操作。


我覺得到這應該明白maxout的原理跟算法了吧= =,下面就直接貼代碼了

新建一個maxout_layer.cpp放到src/caffe/layer文件夾下

  1. #include <cstdio>  
  2.   
  3. #include <vector>  
  4.   
  5.   
  6.   
  7. #include "caffe/filler.hpp"  
  8.   
  9. #include "caffe/layer.hpp"  
  10.   
  11. #include "caffe/util/im2col.hpp"  
  12.   
  13. #include "caffe/util/math_functions.hpp"  
  14.   
  15. #include "caffe/vision_layers.hpp"  
  16.   
  17.   
  18.   
  19. namespace caffe {  
  20.   
  21.   
  22.   
  23. template <typename Dtype>  
  24.   
  25. void MaxoutLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,  
  26.   
  27.       vector<Blob<Dtype>*>* top) {  
  28.   
  29.   Layer<Dtype>::SetUp(bottom, top);  
  30.   
  31.   printf("===============================================================has go into setup !==============================================\n");  
  32.   
  33.   MaxoutParameter maxout_param = this->layer_param_.maxout_param();  
  34.   
  35.     
  36.   
  37.     
  38.   
  39.   // maxout_size  
  40.   
  41.   //CHECK(!maxout_param.has_num_output())  
  42.   
  43.   //    << "maxout size are required.";  
  44.   
  45.   //if (maxout_param.has_num_output()) {  
  46.   
  47.   //  num_output_ = maxout_param.num_output();  
  48.   
  49.   //}  
  50.   
  51.   num_output_ = this->layer_param_.maxout_param().num_output();  
  52.   
  53.   CHECK_GT(num_output_, 0) << "output number cannot be zero.";  
  54.   
  55.     
  56.   
  57.   // bottom ÊÇFEATURE_MAP  
  58.   
  59.   num_ = bottom[0]->num();  
  60.   
  61.   channels_ = bottom[0]->channels();  
  62.   
  63.   height_ = bottom[0]->height();  
  64.   
  65.   width_ = bottom[0]->width();  
  66.   
  67.     
  68.   
  69.   // Ã²ËÆÏÂÃæÕâžöif²»»áÅÜœøÈ¥  
  70.   
  71.   // TODO: generalize to handle inputs of different shapes.  
  72.   
  73.   for (int bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) {  
  74.   
  75.     CHECK_EQ(num_, bottom[bottom_id]->num()) << "Inputs must have same num.";  
  76.   
  77.     CHECK_EQ(channels_, bottom[bottom_id]->channels())  
  78.   
  79.         << "Inputs must have same channels.";  
  80.   
  81.     CHECK_EQ(height_, bottom[bottom_id]->height())  
  82.   
  83.         << "Inputs must have same height.";  
  84.   
  85.     CHECK_EQ(width_, bottom[bottom_id]->width())  
  86.   
  87.         << "Inputs must have same width.";  
  88.   
  89.   }  
  90.   
  91.     
  92.   
  93.   // Set the parameters ž³Öµ²ÎÊý  
  94.   
  95.   CHECK_EQ(channels_ % num_output_, 0)  
  96.   
  97.       << "Number of channel should be multiples of output number.";  
  98.   
  99.         
  100.   
  101.   group_size_ = channels_ / num_output_;  
  102.   
  103.     
  104.   
  105.   // Figure out the dimensions for individual gemms. ŒÆËãŸØÕóµÄÐÐÁР 
  106.   
  107.     
  108.   
  109.   // ÆäʵBengioµÄÂÛÎÄÖжÔÓÚK_µÄŽóС¶šÒåºÜÄ£ºý£¬¶ÔÓÚÍŒÏñœöœöÊÇžøÁËe.g.  
  110.   
  111.   // Ò²Ã»ÓÐ˵µœµ×ʵŒÊÊDz»ÊÇÕâÃŽ²Ù×÷µÄ£¬ÒòΪÈç¹ûÕæµÄÊÇchannelÖ±œÓœøÐбȜϠ 
  112.   
  113.   // ÄÇÃŽŸÍžúÀíÂ۵Ĺ«ÊœÎǺϵIJ»ºÃ£¬µ«ÊÇÄܹ»œâÊÍÍŒÏñ£¬±ÈÈç˵Äóö×îºÃµÄÒ»²ã  
  114.   
  115.   // ¶øÇÒÍŒÏñžú·ÇÍŒÏñµÄmaxoutµÄ×ö·š²îÌ«¶àÁË°¡¡£ŒÙÈç×öµœŒæÈݵĻ°Ö»ÄÜÈÃÇ°Ò»²ã  
  116.   
  117.   // µÄoutput_numÅäºÏmaxout  
  118.   
  119.     
  120.   
  121.   //for (int top_id = 0; top_id < top->size(); ++top_id) {  
  122.   
  123.     (*top)[0]->Reshape(num_, num_output_, height_, width_); // œöœöÊǞıäµÄchannelžöÊý  
  124.     max_idx_.Reshape(num_, num_output_, height_, width_);  
  125.   
  126.   //}  
  127.   
  128. }  
  129.   
  130.   
  131.   
  132.   
  133.   
  134. template <typename Dtype>  
  135.   
  136. Dtype MaxoutLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,  
  137.   
  138.       vector<Blob<Dtype>*>* top) {  
  139.   
  140.        
  141.   
  142.     int featureSize = height_ * width_;  
  143.   
  144.     Dtype* mask = NULL;  
  145.   
  146.     mask = max_idx_.mutable_cpu_data();  
  147.   
  148.   
  149.   
  150. //printf("1.maxout_forward\n");  
  151.       
  152.     const int top_count = (*top)[0]->count();  
  153.   
  154.     caffe_set(top_count, Dtype(0), mask);  
  155.   
  156.       
  157.   
  158. //printf("2.maxout_forward\n");  
  159.       
  160.   
  161.   
  162.   
  163.     for (int i = 0; i < bottom.size(); ++i) {  
  164.   
  165.         const Dtype* bottom_data = bottom[i]->cpu_data();  
  166.   
  167.         Dtype* top_data = (*top)[i]->mutable_cpu_data();    
  168.   
  169.                   
  170.   
  171.         for (int n = 0; n < num_; n ++) {  
  172.   
  173.             // È¡µÚnÕÅÍŒÏñ  
  174.   
  175.             for (int o = 0; o < num_output_; o ++) {  
  176.   
  177.                 for (int g = 0; g < group_size_; g ++) {  
  178.   
  179.                     if (g == 0) {  
  180.   
  181.                         for (int h = 0; h < height_; h ++) { // Áœ²ãÑ­»·Óеã¶ù†ªà  
  182.   
  183.                             for (int w = 0; w < width_; w ++) {  
  184.   
  185.                                 int index = w + h * width_;  
  186.   
  187.                                 top_data[index] = bottom_data[index];  
  188.   
  189.                                 mask[index] = index;  
  190.   
  191.                             }  
  192.   
  193.                         }  
  194.   
  195.                     }  
  196.   
  197.                     else {  
  198.   
  199.                         for (int h = 0; h < height_; h ++) {  
  200.   
  201.                             for (int w = 0; w < width_; w ++) {  
  202.   
  203.                                 int index0 = w + h * width_;  
  204.   
  205.                                 int index1 = index0 + g * featureSize;  
  206.   
  207.                                 if (top_data[index0] < bottom_data[index1]) {  
  208.   
  209.                                     top_data[index0] = bottom_data[index1];  
  210.   
  211.                                     mask[index0] = index1;  
  212.   
  213.                                 }                                 
  214.   
  215.                             }  
  216.   
  217.                         }  
  218.   
  219.                     }  
  220.   
  221.                 }  
  222.   
  223.                 bottom_data += featureSize * group_size_;  
  224.   
  225.                 top_data += featureSize;  
  226.   
  227.                 mask += featureSize;  
  228.   
  229.             }  
  230.   
  231.         }  
  232.   
  233.     }  
  234.   
  235.   
  236.   
  237.     return Dtype(0.);  
  238.   
  239. }  
  240.   
  241.   
  242.   
  243. template <typename Dtype>  
  244.   
  245. void MaxoutLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,  
  246.   
  247.       const vector<bool>& propagate_down, vector<Blob<Dtype>*>* bottom) {  
  248.   
  249.     if (!propagate_down[0]) {  
  250.   
  251.         return;  
  252.   
  253.     }  
  254.   
  255.     const Dtype* top_diff = top[0]->cpu_diff();  
  256.   
  257.     Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();  
  258.   
  259.     caffe_set((*bottom)[0]->count(), Dtype(0), bottom_diff);  
  260.   
  261.     const Dtype* mask = max_idx_.mutable_cpu_data();  
  262.   
  263.     int featureSize = height_ * width_;  
  264.   
  265.   
  266.     for (int i = 0; i < top.size(); i ++) {  
  267.   
  268.         const Dtype* top_diff = top[i]->cpu_diff();  
  269.   
  270.         Dtype* bottom_diff = (*bottom)[i]->mutable_cpu_diff();    
  271.   
  272.                   
  273.   
  274.         for (int n = 0; n < num_; n ++) {  
  275.   
  276.             // È¡µÚnÕÅÍŒÏñ  
  277.   
  278.             for (int o = 0; o < num_output_; o ++) {  
  279.   
  280.                 for (int h = 0; h < height_; h ++) { // Áœ²ãÑ­»·Óеã¶ù†ªà  
  281.   
  282.                     for (int w = 0; w < width_; w ++) {  
  283.   
  284.                         int index = w + h * width_;  
  285.   
  286.                         int bottom_index = mask[index];  
  287.   
  288.                         bottom_diff[bottom_index] += top_diff[index];  
  289.   
  290.                     }  
  291.   
  292.                 }  
  293.   
  294.                 bottom_diff += featureSize * group_size_;  
  295.   
  296.                 top_diff += featureSize;  
  297.   
  298.                 mask += featureSize;  
  299.   
  300.             }  
  301.   
  302.         }  
  303.   
  304.     }  
  305.   
  306. }  
  307.   
  308.   
  309.   
  310. //#ifdef CPU_ONLY  
  311.   
  312. //STUB_GPU(MaxoutLayer);  
  313.   
  314. //#endif  
  315.   
  316.   
  317.   
  318. INSTANTIATE_CLASS(MaxoutLayer);  
  319.   
  320.   
  321.   
  322. }  // namespace caffe  

裏面的亂碼是中文,到了linux裏面就亂碼了,不影響,還一個printf是測試用的(要被笑話用printf了= =)


vision_layers.hpp 裏面添加下面的代碼

  1. /* MaxoutLayer 
  2. */  
  3. template <typename Dtype>  
  4. class MaxoutLayer : public Layer<Dtype> {  
  5.  public:  
  6.   explicit MaxoutLayer(const LayerParameter& param)  
  7.       : Layer<Dtype>(param) {}  
  8.   virtual void SetUp(const vector<Blob<Dtype>*>& bottom,  
  9.       vector<Blob<Dtype>*>* top); // 爲什麼需要bottom與top,肯定的啊,  
  10.       //要初始化bottom top的形狀  
  11.   virtual inline LayerParameter_LayerType type() const {  
  12.     return LayerParameter_LayerType_MAXOUT;  
  13.   }  
  14.   
  15.  protected:  
  16.   virtual Dtype Forward_cpu(const vector<Blob<Dtype>*>& bottom,  
  17.       vector<Blob<Dtype>*>* top);  
  18.   //virtual Dtype Forward_gpu(const vector<Blob<Dtype>*>& bottom,  
  19.   //    vector<Blob<Dtype>*>* top);  
  20.   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,  
  21.       const vector<bool>& propagate_down, vector<Blob<Dtype>*>* bottom);  
  22.   //virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,  
  23.   //    const vector<bool>& propagate_down, vector<Blob<Dtype>*>* bottom);  
  24.     
  25.   int num_output_;  
  26.   int num_;  
  27.   int channels_;  
  28.   int height_;  
  29.   int width_;  
  30.   int group_size_;  
  31.   Blob<Dtype> max_idx_;  
  32.     
  33. };  

剩下的是layer_factory.cpp 的改動,不說明了,然後是proto文件的改動

  1. message MaxoutParameter {  
  2.   optional uint32 num_output = 1; // The number of outputs for the layer  
  3. }  

額,當然還有proto文件的其他改動也不說明了,還有test文件,我沒寫,因爲我自己跑了下demo,沒啥問題,所以代碼可以說是正確的。

不過要說明的是,目前的代碼不能接在全連接層後面,是我裏面有幾句代碼寫的有問題,之後我會改動一下,問題不大。

然後就是NIN的實現了,表示自己寫的渣一樣的代碼啊,效率目測很低。哦對了,這些都是CPU算的,GPU不大會,還沒打算寫。


NIN_layer 的實現

我之前一直以爲Github上的network in network 是有問題的,事實證明,我最後也寫成了Github上面的樣子= =所以大家自行搜索caffe+network in network吧……不過得翻牆下載,所以我就把網絡格式的代碼直接貼出來(cifar10數據庫的網絡結構)

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. layers {  
  2.   name: "cifar"  
  3.   type: DATA  
  4.   top: "data"  
  5.   top: "label"  
  6.   data_param {  
  7.     source: "cifar-train-leveldb"  
  8.     batch_size: 128  
  9.   }  
  10.   include: { phase: TRAIN }  
  11. }  
  12. layers {  
  13.   name: "cifar"  
  14.   type: DATA  
  15.   top: "data"  
  16.   top: "label"  
  17.   data_param {  
  18.     source: "cifar-test-leveldb"  
  19.     batch_size: 100  
  20.   }  
  21.   include: { phase: TEST }  
  22. }  
  23. layers {  
  24.   name: "conv1"  
  25.   type: CONVOLUTION  
  26.   bottom: "data"  
  27.   top: "conv1"  
  28.   blobs_lr: 1  
  29.   blobs_lr: 2  
  30.   weight_decay: 1.  
  31.   weight_decay: 0.  
  32.   convolution_param {  
  33.     num_output: 192  
  34.     pad: 2  
  35.     kernel_size: 5  
  36.     weight_filler {  
  37.       type: "gaussian"  
  38.       std: 0.05  
  39.     }  
  40.     bias_filler {  
  41.       type: "constant"  
  42.     }  
  43.   }  
  44. }  
  45. layers {  
  46.   name: "relu1"  
  47.   type: RELU  
  48.   bottom: "conv1"  
  49.   top: "conv1"  
  50. }  
  51. layers {  
  52.   name: "cccp1"  
  53.   type: CONVOLUTION  
  54.   bottom: "conv1"  
  55.   top: "cccp1"  
  56.   blobs_lr: 1  
  57.   blobs_lr: 2  
  58.   weight_decay: 1  
  59.   weight_decay: 0  
  60.   convolution_param {  
  61.     num_output: 160  
  62.     group: 1  
  63.     kernel_size: 1  
  64.     weight_filler {  
  65.       type: "gaussian"  
  66.       std: 0.05  
  67.     }  
  68.     bias_filler {  
  69.       type: "constant"  
  70.       value: 0  
  71.     }  
  72.   }  
  73. }  
  74. layers {  
  75.   name: "relu_cccp1"  
  76.   type: RELU  
  77.   bottom: "cccp1"  
  78.   top: "cccp1"  
  79. }  
  80. layers {  
  81.   name: "cccp2"  
  82.   type: CONVOLUTION  
  83.   bottom: "cccp1"  
  84.   top: "cccp2"  
  85.   blobs_lr: 1  
  86.   blobs_lr: 2  
  87.   weight_decay: 1  
  88.   weight_decay: 0  
  89.   convolution_param {  
  90.     num_output: 96  
  91.     group: 1  
  92.     kernel_size: 1  
  93.     weight_filler {  
  94.       type: "gaussian"  
  95.       std: 0.05  
  96.     }  
  97.     bias_filler {  
  98.       type: "constant"  
  99.       value: 0  
  100.     }  
  101.   }  
  102. }  
  103. layers {  
  104.   name: "relu_cccp2"  
  105.   type: RELU  
  106.   bottom: "cccp2"  
  107.   top: "cccp2"  
  108. }  
  109. layers {  
  110.   name: "pool1"  
  111.   type: POOLING  
  112.   bottom: "cccp2"  
  113.   top: "pool1"  
  114.   pooling_param {  
  115.     pool: MAX  
  116.     kernel_size: 3  
  117.     stride: 2  
  118.   }  
  119. }  
  120. layers {  
  121.   name: "drop3"  
  122.   type: DROPOUT  
  123.   bottom: "pool1"  
  124.   top: "pool1"  
  125.   dropout_param {  
  126.     dropout_ratio: 0.5  
  127.   }  
  128. }  
  129. layers {  
  130.   name: "conv2"  
  131.   type: CONVOLUTION  
  132.   bottom: "pool1"  
  133.   top: "conv2"  
  134.   blobs_lr: 1  
  135.   blobs_lr: 2  
  136.   weight_decay: 1.  
  137.   weight_decay: 0.  
  138.   convolution_param {  
  139.     num_output: 192  
  140.     pad: 2  
  141.     kernel_size: 5  
  142.     weight_filler {  
  143.       type: "gaussian"  
  144.       std: 0.05  
  145.     }  
  146.     bias_filler {  
  147.       type: "constant"  
  148.     }  
  149.   }  
  150. }  
  151. layers {  
  152.   name: "relu2"  
  153.   type: RELU  
  154.   bottom: "conv2"  
  155.   top: "conv2"  
  156. }  
  157. layers {  
  158.   name: "cccp3"  
  159.   type: CONVOLUTION  
  160.   bottom: "conv2"  
  161.   top: "cccp3"  
  162.   blobs_lr: 1  
  163.   blobs_lr: 2  
  164.   weight_decay: 1  
  165.   weight_decay: 0  
  166.   convolution_param {  
  167.     num_output: 192  
  168.     group: 1  
  169.     kernel_size: 1  
  170.     weight_filler {  
  171.       type: "gaussian"  
  172.       std: 0.05  
  173.     }  
  174.     bias_filler {  
  175.       type: "constant"  
  176.       value: 0  
  177.     }  
  178.   }  
  179. }  
  180. layers {  
  181.   name: "relu_cccp3"  
  182.   type: RELU  
  183.   bottom: "cccp3"  
  184.   top: "cccp3"  
  185. }  
  186. layers {  
  187.   name: "cccp4"  
  188.   type: CONVOLUTION  
  189.   bottom: "cccp3"  
  190.   top: "cccp4"  
  191.   blobs_lr: 1  
  192.   blobs_lr: 2  
  193.   weight_decay: 1  
  194.   weight_decay: 0  
  195.   convolution_param {  
  196.     num_output: 192  
  197.     group: 1  
  198.     kernel_size: 1  
  199.     weight_filler {  
  200.       type: "gaussian"  
  201.       std: 0.05  
  202.     }  
  203.     bias_filler {  
  204.       type: "constant"  
  205.       value: 0  
  206.     }  
  207.   }  
  208. }  
  209. layers {  
  210.   name: "relu_cccp4"  
  211.   type: RELU  
  212.   bottom: "cccp4"  
  213.   top: "cccp4"  
  214. }  
  215. layers {  
  216.   name: "pool2"  
  217.   type: POOLING  
  218.   bottom: "cccp4"  
  219.   top: "pool2"  
  220.   pooling_param {  
  221.     pool: AVE  
  222.     kernel_size: 3  
  223.     stride: 2  
  224.   }  
  225. }  
  226. layers {  
  227.   name: "drop6"  
  228.   type: DROPOUT  
  229.   bottom: "pool2"  
  230.   top: "pool2"  
  231.   dropout_param {  
  232.     dropout_ratio: 0.5  
  233.   }  
  234. }  
  235. layers {  
  236.   name: "conv3"  
  237.   type: CONVOLUTION  
  238.   bottom: "pool2"  
  239.   top: "conv3"  
  240.   blobs_lr: 1.  
  241.   blobs_lr: 2.  
  242.   weight_decay: 1.  
  243.   weight_decay: 0.  
  244.   convolution_param {  
  245.     num_output: 192  
  246.     pad: 1  
  247.     kernel_size: 3  
  248.     weight_filler {  
  249.       type: "gaussian"  
  250.       std: 0.05  
  251.     }  
  252.     bias_filler {  
  253.       type: "constant"  
  254.     }  
  255.   }  
  256. }  
  257. layers {  
  258.   name: "relu3"  
  259.   type: RELU  
  260.   bottom: "conv3"  
  261.   top: "conv3"  
  262. }  
  263. layers {  
  264.   name: "cccp5"  
  265.   type: CONVOLUTION  
  266.   bottom: "conv3"  
  267.   top: "cccp5"  
  268.   blobs_lr: 1  
  269.   blobs_lr: 2  
  270.   weight_decay: 1  
  271.   weight_decay: 0  
  272.   convolution_param {  
  273.     num_output: 192  
  274.     group: 1  
  275.     kernel_size: 1  
  276.     weight_filler {  
  277.       type: "gaussian"  
  278.       std: 0.05  
  279.     }  
  280.     bias_filler {  
  281.       type: "constant"  
  282.       value: 0  
  283.     }  
  284.   }  
  285. }  
  286. layers {  
  287.   name: "relu_cccp5"  
  288.   type: RELU  
  289.   bottom: "cccp5"  
  290.   top: "cccp5"  
  291. }  
  292. layers {  
  293.   name: "cccp6"  
  294.   type: CONVOLUTION  
  295.   bottom: "cccp5"  
  296.   top: "cccp6"  
  297.   blobs_lr: 0.1  
  298.   blobs_lr: 0.1  
  299.   weight_decay: 1  
  300.   weight_decay: 0  
  301.   convolution_param {  
  302.     num_output: 10  
  303.     group: 1  
  304.     kernel_size: 1  
  305.     weight_filler {  
  306.       type: "gaussian"  
  307.       std: 0.05  
  308.     }  
  309.     bias_filler {  
  310.       type: "constant"  
  311.       value: 0  
  312.     }  
  313.   }  
  314. }  
  315. layers {  
  316.   name: "relu_cccp6"  
  317.   type: RELU  
  318.   bottom: "cccp6"  
  319.   top: "cccp6"  
  320. }  
  321. layers {  
  322.   name: "pool3"  
  323.   type: POOLING  
  324.   bottom: "cccp6"  
  325.   top: "pool3"  
  326.   pooling_param {  
  327.     pool: AVE  
  328.     kernel_size: 8  
  329.     stride: 1  
  330.   }  
  331. }  
  332. layers {  
  333.   name: "accuracy"  
  334.   type: ACCURACY  
  335.   bottom: "pool3"  
  336.   bottom: "label"  
  337.   top: "accuracy"  
  338.   include: { phase: TEST }  
  339. }  
  340. layers {  
  341.   name: "loss"  
  342.   type: SOFTMAX_LOSS  
  343.   bottom: "pool3"  
  344.   bottom: "label"  
  345.   top: "loss"  
  346. }  



訓練參數

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. test_iter: 100  
  2. test_interval: 500  
  3. base_lr: 0.1  
  4. momentum: 0.9  
  5. weight_decay: 0.0001  
  6. lr_policy: "step"  
  7. gamma: 0.1  
  8. stepsize: 100000  
  9. display: 100  
  10. max_iter: 120000  
  11. snapshot: 10000  
  12. snapshot_prefix: "cifar10_nin"  


該文章算是告一段落了,剩下的任務就是如何訓練得到state-of-the-art了



裝載自http://blog.csdn.net/kuaitoukid/article/details/41865803。

發佈了17 篇原創文章 · 獲贊 57 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章