CenterLoss的caffe实现

github的地址:https://github.com/ydwen/caffe-face

CenterLoss_layer可以在原分类的基础上(某种程度上)可提升几个点左右(博主测试提升6个点),还不占前向时间,好东西啊!

原理这里不介绍了,网上应有尽有!这里只是介绍如何在caffe中如何添加CenterLoss_layer这样的新层!


第一步:修改caffe.proto以添加消息机制

1、在message LayerParameter{}中添加如下代码:

[cpp]  view plain  copy
  1. optional CenterLossParameter center_loss_param = 147;  

2、在 caffe.proto文末 添加

[cpp]  view plain  copy
  1. message CenterLossParameter {  
  2.   optional uint32 num_output = 1; // The number of outputs for the layer  
  3.   optional FillerParameter center_filler = 2; // The filler for the centers  
  4.   // The first axis to be lumped into a single inner product computation;  
  5.   // all preceding axes are retained in the output.  
  6.   // May be negative to index from the end (e.g., -1 for the last axis).  
  7.   optional int32 axis = 3 [default = 1];  
  8. }  


第二步:添加头文件center_loss_layer.hpp

[cpp]  view plain  copy
  1. #ifndef CAFFE_CENTER_LOSS_LAYER_HPP_  
  2. #define CAFFE_CENTER_LOSS_LAYER_HPP_  
  3.   
  4. #include   
  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.   
  14. template <typename Dtype>  
  15. class CenterLossLayer : public LossLayer {  
  16.  public:  
  17.   explicit CenterLossLayer(const LayerParameter& param)  
  18.       : LossLayer(param) {}  
  19.   virtual void LayerSetUp(const vector*>& bottom,  
  20.       const vector*>& top);  
  21.   virtual void Reshape(const vector*>& bottom,  
  22.       const vector*>& top);  
  23.   
  24.   virtual inline const char* type() const { return "CenterLoss"; }  
  25.   virtual inline int ExactNumBottomBlobs() const { return 2; }  
  26.   virtual inline int ExactNumTopBlobs() const { return -1; }  
  27.   
  28.  protected:  
  29.   virtual void Forward_cpu(const vector*>& bottom,  
  30.       const vector*>& top);  
  31.   virtual void Forward_gpu(const vector*>& bottom,  
  32.       const vector*>& top);  
  33.   virtual void Backward_cpu(const vector*>& top,  
  34.       const vector<bool>& propagate_down, const vector*>& bottom);  
  35.   virtual void Backward_gpu(const vector*>& top,  
  36.       const vector<bool>& propagate_down, const vector*>& bottom);  
  37.   
  38.   int M_;  
  39.   int K_;  
  40.   int N_;  
  41.     
  42.   Blob distance_;  
  43.   Blob variation_sum_;  
  44. };  
  45.   
  46. }  // namespace caffe  
  47.   
  48. #endif  // CAFFE_CENTER_LOSS_LAYER_HPP_  


第三步:添加center_loss_layer.cpp以及center_loss_layer.cu

[cpp]  view plain  copy
  1. #include   
  2.   
  3. #include "caffe/filler.hpp"  
  4. #include "caffe/layers/center_loss_layer.hpp"  
  5. #include "caffe/util/math_functions.hpp"  
  6.   
  7. namespace caffe {  
  8.   
  9. template <typename Dtype>  
  10. void CenterLossLayer::LayerSetUp(const vector*>& bottom,  
  11.       const vector*>& top) {  
  12.   const int num_output = this->layer_param_.center_loss_param().num_output();    
  13.   N_ = num_output;  
  14.   const int axis = bottom[0]->CanonicalAxisIndex(  
  15.       this->layer_param_.center_loss_param().axis());  
  16.   // Dimensions starting from "axis" are "flattened" into a single  
  17.   // length K_ vector. For example, if bottom[0]'s shape is (N, C, H, W),  
  18.   // and axis == 1, N inner products with dimension CHW are performed.  
  19.   K_ = bottom[0]->count(axis);  
  20.   // Check if we need to set up the weights  
  21.   if (this->blobs_.size() > 0) {  
  22.     LOG(INFO) << "Skipping parameter initialization";  
  23.   } else {  
  24.     this->blobs_.resize(1);  
  25.     // Intialize the weight  
  26.     vector<int> center_shape(2);  
  27.     center_shape[0] = N_;  
  28.     center_shape[1] = K_;  
  29.     this->blobs_[0].reset(new Blob(center_shape));  
  30.     // fill the weights  
  31.     shared_ptr > center_filler(GetFiller(  
  32.         this->layer_param_.center_loss_param().center_filler()));  
  33.     center_filler->Fill(this->blobs_[0].get());  
  34.   
  35.   }  // parameter initialization  
  36.   this->param_propagate_down_.resize(this->blobs_.size(), true);  
  37. }  
  38.   
  39. template <typename Dtype>  
  40. void CenterLossLayer::Reshape(const vector*>& bottom,  
  41.       const vector*>& top) {  
  42.   CHECK_EQ(bottom[1]->channels(), 1);  
  43.   CHECK_EQ(bottom[1]->height(), 1);  
  44.   CHECK_EQ(bottom[1]->width(), 1);  
  45.   M_ = bottom[0]->num();  
  46.   // The top shape will be the bottom shape with the flattened axes dropped,  
  47.   // and replaced by a single axis with dimension num_output (N_).  
  48.   LossLayer::Reshape(bottom, top);  
  49.   distance_.ReshapeLike(*bottom[0]);  
  50.   variation_sum_.ReshapeLike(*this->blobs_[0]);  
  51. }  
  52.   
  53. template <typename Dtype>  
  54. void CenterLossLayer::Forward_cpu(const vector*>& bottom,  
  55.     const vector*>& top) {  
  56.   const Dtype* bottom_data = bottom[0]->cpu_data();  
  57.   const Dtype* label = bottom[1]->cpu_data();  
  58.   const Dtype* center = this->blobs_[0]->cpu_data();  
  59.   Dtype* distance_data = distance_.mutable_cpu_data();  
  60.     
  61.   // the i-th distance_data  
  62.   for (int i = 0; i < M_; i++) {  
  63.     const int label_value = static_cast<int>(label[i]);  
  64.     // D(i,:) = X(i,:) - C(y(i),:)  
  65.     caffe_sub(K_, bottom_data + i * K_, center + label_value * K_, distance_data + i * K_);  
  66.   }  
  67.   Dtype dot = caffe_cpu_dot(M_ * K_, distance_.cpu_data(), distance_.cpu_data());  
  68.   Dtype loss = dot / M_ / Dtype(2);  
  69.   top[0]->mutable_cpu_data()[0] = loss;  
  70. }  
  71.   
  72. template <typename Dtype>  
  73. void CenterLossLayer::Backward_cpu(const vector*>& top,  
  74.     const vector<bool>& propagate_down,  
  75.     const vector*>& bottom) {  
  76.   // Gradient with respect to centers  
  77.   if (this->param_propagate_down_[0]) {  
  78.     const Dtype* label = bottom[1]->cpu_data();  
  79.     Dtype* center_diff = this->blobs_[0]->mutable_cpu_diff();  
  80.     Dtype* variation_sum_data = variation_sum_.mutable_cpu_data();  
  81.     const Dtype* distance_data = distance_.cpu_data();  
  82.   
  83.     // \sum_{y_i==j}  
  84.     caffe_set(N_ * K_, (Dtype)0., variation_sum_.mutable_cpu_data());  
  85.     for (int n = 0; n < N_; n++) {  
  86.       int count = 0;  
  87.       for (int m = 0; m < M_; m++) {  
  88.         const int label_value = static_cast<int>(label[m]);  
  89.         if (label_value == n) {  
  90.           count++;  
  91.           caffe_sub(K_, variation_sum_data + n * K_, distance_data + m * K_, variation_sum_data + n * K_);  
  92.         }  
  93.       }  
  94.       caffe_axpy(K_, (Dtype)1./(count + (Dtype)1.), variation_sum_data + n * K_, center_diff + n * K_);  
  95.     }  
  96.   }  
  97.   // Gradient with respect to bottom data   
  98.   if (propagate_down[0]) {  
  99.     caffe_copy(M_ * K_, distance_.cpu_data(), bottom[0]->mutable_cpu_diff());  
  100.     caffe_scal(M_ * K_, top[0]->cpu_diff()[0] / M_, bottom[0]->mutable_cpu_diff());  
  101.   }  
  102.   if (propagate_down[1]) {  
  103.     LOG(FATAL) << this->type()  
  104.                << " Layer cannot backpropagate to label inputs.";  
  105.   }  
  106. }  
  107.   
  108. #ifdef CPU_ONLY  
  109. STUB_GPU(CenterLossLayer);  
  110. #endif  
  111.   
  112. INSTANTIATE_CLASS(CenterLossLayer);  
  113. REGISTER_LAYER_CLASS(CenterLoss);  
  114.   
  115. }  // namespace caffe  

[cpp]  view plain  copy
  1. #include   
  2.   
  3. #include "caffe/filler.hpp"  
  4. #include "caffe/layers/center_loss_layer.hpp"  
  5. #include "caffe/util/math_functions.hpp"  
  6.   
  7. namespace caffe {  
  8.   
  9. template <typename Dtype>  
  10. __global__ void Compute_distance_data_gpu(int nthreads, const int K, const Dtype* bottom,  
  11.           const Dtype* label, const Dtype* center, Dtype* distance) {  
  12.   CUDA_KERNEL_LOOP(index, nthreads) {  
  13.     int m = index / K;  
  14.     int k = index % K;  
  15.     const int label_value = static_cast<int>(label[m]);  
  16.     // distance(i) = x(i) - c_{y(i)}  
  17.     distance[index] = bottom[index] - center[label_value * K + k];  
  18.   }  
  19. }  
  20.   
  21. template <typename Dtype>  
  22. __global__ void Compute_center_diff_gpu(int nthreads, const int M, const int K,   
  23.         const Dtype* label, const Dtype* distance, Dtype* variation_sum,   
  24.         Dtype* center_diff) {  
  25.   CUDA_KERNEL_LOOP(index, nthreads) {  
  26.     int count = 0;  
  27.     for (int m = 0; m < M; m++) {  
  28.       const int label_value = static_cast<int>(label[m]);  
  29.       if (label_value == index) {  
  30.         count++;  
  31.         for (int k = 0; k < K; k++) {  
  32.           variation_sum[index * K + k] -= distance[m * K + k];  
  33.         }  
  34.       }  
  35.     }  
  36.     for (int k = 0; k < K; k++) {  
  37.       center_diff[index * K + k] = variation_sum[index * K + k] /(count + (Dtype)1.);  
  38.     }  
  39.   }  
  40. }  
  41.   
  42.   
  43. template <typename Dtype>  
  44. void CenterLossLayer::Forward_gpu(const vector*>& bottom,  
  45.     const vector*>& top) {  
  46.   int nthreads = M_ * K_;  
  47.   Compute_distance_data_gpu<<
  48.       CAFFE_CUDA_NUM_THREADS>>>(nthreads, K_, bottom[0]->gpu_data(), bottom[1]->gpu_data(),  
  49.                                 this->blobs_[0]->gpu_data(), distance_.mutable_gpu_data());  
  50.   Dtype dot;  
  51.   caffe_gpu_dot(M_ * K_, distance_.gpu_data(), distance_.gpu_data(), &dot);  
  52.   Dtype loss = dot / M_ / Dtype(2);  
  53.   top[0]->mutable_cpu_data()[0] = loss;  
  54. }  
  55.   
  56. template <typename Dtype>  
  57. void CenterLossLayer::Backward_gpu(const vector*>& top,  
  58.     const vector<bool>& propagate_down,  
  59.     const vector*>& bottom) {  
  60.   int nthreads = N_;  
  61.   caffe_gpu_set(N_ * K_, (Dtype)0., variation_sum_.mutable_cpu_data());  
  62.   Compute_center_diff_gpu<<
  63.       CAFFE_CUDA_NUM_THREADS>>>(nthreads, M_, K_, bottom[1]->gpu_data(), distance_.gpu_data(),   
  64.                                 variation_sum_.mutable_cpu_data(), this->blobs_[0]->mutable_gpu_diff());  
  65.   
  66.   if (propagate_down[0]) {  
  67.     caffe_gpu_scale(M_ * K_, top[0]->cpu_diff()[0] / M_,   
  68.                              distance_.gpu_data(), bottom[0]->mutable_gpu_diff());  
  69.   }  
  70.   if (propagate_down[1]) {  
  71.     LOG(FATAL) << this->type()  
  72.                << " Layer cannot backpropagate to label inputs.";  
  73.   }  
  74. }  
  75.   
  76. INSTANTIATE_LAYER_GPU_FUNCS(CenterLossLayer);  
  77.   
  78. }  // namespace caffe  


第四步:重新编译caffe

你可能感兴趣的:(人脸检测,目标检测,深度学习通用策略)