修改caffe源代码从添加loss(层)函数开始

DeepLearning(基于caffe)实战项目(8)--修改caffe源代码从添加loss(层)函数开始

标签: Caffe实战项目LossLayer修改源代码
479人阅读 评论(0) 收藏 举报
分类:

在caffe中摸爬滚打了一个多月了,修改caffe源代码,早就想练练手了,loss层是一个比较独立的一个层,而且可以仿照caffe给的样例进行添加,难度会稍微小点。caffe自带了十种loss层(contrastive、euclidean、hinge、multinomial_logistic、sigmoid_cross_entropy、smooth_L1、smooth_L1_ohem、softmax、softmax_ohem、infogain)

详细见:http://blog.csdn.net/sihailongwang/article/details/72657637

公式含义推荐:http://blog.csdn.net/u012177034/article/details/52144325

接下来,就是自己添加一个新的loss(层)函数了,我打算添加:Absolute loss

第一步:在caffe.proto增加对应的LayerParameter message

  1. optional AbsoluteLossParameter Absolute_loss_param = 151;  
optional AbsoluteLossParameter Absolute_loss_param = 151;

  1. message AbsoluteLossParameter   
  2. {  
  3.   optional float dis = 1 [default = 1];  
  4. }  
message AbsoluteLossParameter 
{
  optional float dis = 1 [default = 1];
}

第二步:在./include/caffe/layers/下增加相应的layer的声明

  1. #ifndef CAFFE_ABSOLUTE_LOSS_LAYER_HPP_  
  2. #define CAFFE_ABSOLUTE_LOSS_LAYER_HPP_  
  3.   
  4.   
  5. #include <vector>  
  6.   
  7.   
  8. #include "caffe/blob.hpp"  
  9. #include "caffe/layer.hpp"  
  10. #include "caffe/proto/caffe.pb.h"  
  11.   
  12.   
  13. #include "caffe/layers/loss_layer.hpp"  
  14.   
  15.   
  16. namespace caffe {  
  17.   
  18.   
  19. template <typename Dtype>  
  20. class AbsoluteLossLayer : public LossLayer<Dtype> {  
  21.  public:  
  22.   explicit AbsoluteLossLayer(const LayerParameter& param)  
  23.       : LossLayer<Dtype>(param), dis_() {}  
  24.   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,  
  25.       const vector<Blob<Dtype>*>& top);  
  26.   
  27.   
  28.   virtual inline const char* type() const { return "AbsoluteLoss"; }  
  29.   
  30.   
  31.   virtual inline bool AllowForceBackward(const int bottom_index) const {  
  32.     return true;  
  33.   }  
  34.   
  35.   
  36.  protected:  
  37.   /// @copydoc AbsoluteLossLayer  
  38.   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,  
  39.       const vector<Blob<Dtype>*>& top);  
  40.   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,  
  41.       const vector<Blob<Dtype>*>& top);  
  42.   
  43.   
  44.   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,  
  45.       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);  
  46.   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,  
  47.       const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);  
  48.   
  49.   
  50.   Blob<Dtype> dis_;  
  51. };  
  52.   
  53.   
  54. }  // namespace caffe  
  55.   
  56.   
  57. #endif  // CAFFE_EUCLIDEAN_LOSS_LAYER_HPP_  
  58.   
  59. #endif  // CAFFE_EUCLIDEAN_LOSS_LAYER_HPP_  
#ifndef CAFFE_ABSOLUTE_LOSS_LAYER_HPP_
#define CAFFE_ABSOLUTE_LOSS_LAYER_HPP_


#include <vector>


#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"


#include "caffe/layers/loss_layer.hpp"


namespace caffe {


template <typename Dtype>
class AbsoluteLossLayer : public LossLayer<Dtype> {
 public:
  explicit AbsoluteLossLayer(const LayerParameter& param)
      : LossLayer<Dtype>(param), dis_() {}
  virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);


  virtual inline const char* type() const { return "AbsoluteLoss"; }


  virtual inline bool AllowForceBackward(const int bottom_index) const {
    return true;
  }


 protected:
  /// @copydoc AbsoluteLossLayer
  virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top);
  virtual void Forward_gpu(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);
  virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);


  Blob<Dtype> dis_;
};


}  // namespace caffe


#endif  // CAFFE_EUCLIDEAN_LOSS_LAYER_HPP_

#endif  // CAFFE_EUCLIDEAN_LOSS_LAYER_HPP_

第三步:在./src/caffe/util/math_functions.cpp/下增加“绝对值求和”模板函数

说明:因为AbsoluteLoss需要绝对值求和,所以在math_fuction.cpp中需要增加一个“绝对值”模板函数(与此同时,我惊喜的发现了BLAS、CBLAS

/********************************************************************************************************************

TIPS:科普一下什么是BLAS/CBLAS

Basic Linear Algebra Subprograms,即基础线性代数子程序库,里边拥有大量的已经编好的关于线性代数运算的程序,主要用于向量和矩阵的计算的高性能数学库,本身是由Fortran编写的,为了方便C/C++程序使用,就有了BLAS的C接口库CBLAS,详细列表:http://www.netlib.org/blas/

/********************************************************************************************************************

  1. //--------------------------add------------------------------------------  
  2. template <>  
  3. float caffe_cpu_asum<float>(const int n, const float* x) {  
  4.   return cblas_sasum(n, x, 1);      //sum of absolute values  
  5. }  
  6.   
  7. template <>  
  8. double caffe_cpu_asum<double>(const int n, const double* x) {  
  9.   return cblas_dasum(n, x, 1);      //sum of absolute values  
  10. }  
  11.   
  12. template <typename Dtype>  
  13. Dtype caffe_cpu_abs_sum(const int n, const Dtype* x) {  
  14.   return caffe_cpu_asum(n, x);  
  15. }  
  16.   
  17. template  
  18. float caffe_cpu_asum<float>(const int n, const float* x);  
  19.   
  20. template  
  21. double caffe_cpu_asum<double>(const int n, const double* x);  
  22. //-------------------------add-------------------------------------------  
//--------------------------add------------------------------------------
template <>
float caffe_cpu_asum<float>(const int n, const float* x) {
  return cblas_sasum(n, x, 1);      //sum of absolute values
}

template <>
double caffe_cpu_asum<double>(const int n, const double* x) {
  return cblas_dasum(n, x, 1);      //sum of absolute values
}

template <typename Dtype>
Dtype caffe_cpu_abs_sum(const int n, const Dtype* x) {
  return caffe_cpu_asum(n, x);
}

template
float caffe_cpu_asum<float>(const int n, const float* x);

template
double caffe_cpu_asum<double>(const int n, const double* x);
//-------------------------add-------------------------------------------

第四步:在./src/caffe/layers/下增加相应layer的CPU/GPU实现文件

   CPU版本(absolute_loss_layer.cpp)

  1. #include <vector>  
  2.   
  3. #include "caffe/layers/absolute_loss_layer.hpp"  
  4. #include "caffe/util/math_functions.hpp"  
  5.   
  6. namespace caffe {  
  7.   
  8. template <typename Dtype>  
  9. void AbsoluteLossLayer<Dtype>::Reshape(  
  10.   const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {  
  11.   LossLayer<Dtype>::Reshape(bottom, top);   //在LossLayer 中定义  
  12.   CHECK_EQ(bottom[0]->count(1), bottom[1]->count(1))  //保证输入维度相同  
  13.       << "Inputs must have the same dimension.";  
  14.   dis_.ReshapeLike(*bottom[0]);           //Blob 类型的diff_用来存放两个bottom的差,和bottom具有相同的  
  15. }  
  16.   
  17. template <typename Dtype>  
  18. void AbsoluteLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,  
  19.     const vector<Blob<Dtype>*>& top) {  
  20.   int count = bottom[0]->count();   //总共有count个featuremap   
  21.   caffe_sub(  
  22.       count,  
  23.       bottom[0]->cpu_data(),  
  24.       bottom[1]->cpu_data(),  
  25.       dis_.mutable_cpu_data());    //diff_ = bottom[0] - bottom[1]   
  26.   Dtype loss_param = this->layer_param_.absolute_loss_param().dis();  
  27.   Dtype abs_sum = caffe_cpu_abs_sum(count,dis_.cpu_data());  
  28.   //Dtype dot = caffe_cpu_abs_sum()(count, diff_.cpu_data(), dis_.cpu_data());  
  29.   Dtype loss = loss_param * abs_sum / bottom[0]->num();  
  30.   top[0]->mutable_cpu_data()[0] = loss;  
  31. }  
  32.   
  33. template <typename Dtype>  
  34. void AbsoluteLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,  
  35.     const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {  
  36.   for (int i = 0; i < 2; ++i) {  
  37.     if (propagate_down[i]) {  
  38.        //对于输入的label bottom propagate_dowm为0  
  39.       const Dtype sign = (i == 0) ? 1 : -1;  
  40.       const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num();  
  41.       caffe_cpu_axpby(  
  42.           bottom[i]->count(),                       // count  
  43.           alpha,                             // alpha  
  44.           dis_.cpu_data(),                        // a  
  45.           Dtype(0),                           // beta  
  46.           bottom[i]->mutable_cpu_diff());                 // b  
  47.     }     //bottom[i]->mutable_cpu_diff()) = alpha*dis_.cpu_data()  
  48.   }  
  49. }  
  50.   
  51. #ifdef CPU_ONLY  
  52. STUB_GPU(AbsoluteLossLayer);  
  53. #endif  
  54.   
  55. INSTANTIATE_CLASS(AbsoluteLossLayer);  
  56. REGISTER_LAYER_CLASS(AbsoluteLoss);  
  57.   
  58. }  // namespace caffe  
#include <vector>

#include "caffe/layers/absolute_loss_layer.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {

template <typename Dtype>
void AbsoluteLossLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  LossLayer<Dtype>::Reshape(bottom, top);   //在LossLayer 中定义
  CHECK_EQ(bottom[0]->count(1), bottom[1]->count(1))  //保证输入维度相同
      << "Inputs must have the same dimension.";
  dis_.ReshapeLike(*bottom[0]);           //Blob 类型的diff_用来存放两个bottom的差,和bottom具有相同的
}

template <typename Dtype>
void AbsoluteLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  int count = bottom[0]->count();   //总共有count个featuremap 
  caffe_sub(
      count,
      bottom[0]->cpu_data(),
      bottom[1]->cpu_data(),
      dis_.mutable_cpu_data());    //diff_ = bottom[0] - bottom[1] 
  Dtype loss_param = this->layer_param_.absolute_loss_param().dis();
  Dtype abs_sum = caffe_cpu_abs_sum(count,dis_.cpu_data());
  //Dtype dot = caffe_cpu_abs_sum()(count, diff_.cpu_data(), dis_.cpu_data());
  Dtype loss = loss_param * abs_sum / bottom[0]->num();
  top[0]->mutable_cpu_data()[0] = loss;
}

template <typename Dtype>
void AbsoluteLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  for (int i = 0; i < 2; ++i) {
    if (propagate_down[i]) {
       //对于输入的label bottom propagate_dowm为0
      const Dtype sign = (i == 0) ? 1 : -1;
      const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num();
      caffe_cpu_axpby(
          bottom[i]->count(),                       // count
          alpha,                             // alpha
          dis_.cpu_data(),                        // a
          Dtype(0),                           // beta
          bottom[i]->mutable_cpu_diff());                 // b
    }     //bottom[i]->mutable_cpu_diff()) = alpha*dis_.cpu_data()
  }
}

#ifdef CPU_ONLY
STUB_GPU(AbsoluteLossLayer);
#endif

INSTANTIATE_CLASS(AbsoluteLossLayer);
REGISTER_LAYER_CLASS(AbsoluteLoss);

}  // namespace caffe
GPU版本(absolute_loss_layer.cu)
  1. #include <vector>  
  2.   
  3.   
  4. #include "caffe/layers/absolute_loss_layer.hpp"  
  5. #include "caffe/util/math_functions.hpp"  
  6.   
  7. namespace caffe {  
  8.   
  9. template <typename Dtype>  
  10. void AbsoluteLossLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,  
  11.     const vector<Blob<Dtype>*>& top) {  
  12.   int count = bottom[0]->count();   //总共有count个featuremap   
  13.   caffe_gpu_sub(  
  14.       count,  
  15.       bottom[0]->gpu_data(),  
  16.       bottom[1]->gpu_data(),  
  17.       dis_.mutable_gpu_data());  
  18.   Dtype loss_param = this->layer_param_.  
  19.   Dtype abs_sum;  
  20.   caffe_gpu_asum(count, dis_.gpu_data(), &abs_sum);  
  21.   Dtype loss = loss_param * abs_sum/ bottom[0]->num();  
  22.   top[0]->mutable_cpu_data()[0] = loss;  
  23. }  
#include <vector>


#include "caffe/layers/absolute_loss_layer.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {

template <typename Dtype>
void AbsoluteLossLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  int count = bottom[0]->count();   //总共有count个featuremap 
  caffe_gpu_sub(
      count,
      bottom[0]->gpu_data(),
      bottom[1]->gpu_data(),
      dis_.mutable_gpu_data());
  Dtype loss_param = this->layer_param_.
  Dtype abs_sum;
  caffe_gpu_asum(count, dis_.gpu_data(), &abs_sum);
  Dtype loss = loss_param * abs_sum/ bottom[0]->num();
  top[0]->mutable_cpu_data()[0] = loss;
}
  1. template <typename Dtype>  
  2. void AbsoluteLossLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,  
  3.     const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {  
  4.   for (int i = 0; i < 2; ++i) {  
  5.     if (propagate_down[i]) {  
  6.       const Dtype sign = (i == 0) ? 1 : -1;  
  7.       const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num();  
  8.       caffe_gpu_axpby(  
  9.           bottom[i]->count(),                       // count  
  10.           alpha,                             // alpha  
  11.           dis_.gpu_data(),                        // a  
  12.           Dtype(0),                           // beta  
  13.           bottom[i]->mutable_gpu_diff());                 // b  
  14.     }  
  15.   }  
  16. }  
  17.   
  18. INSTANTIATE_LAYER_GPU_FUNCS(AbsoluteLossLayer);  
  19.   
  20. }  // namespace caffe  
template <typename Dtype>
void AbsoluteLossLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  for (int i = 0; i < 2; ++i) {
    if (propagate_down[i]) {
      const Dtype sign = (i == 0) ? 1 : -1;
      const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num();
      caffe_gpu_axpby(
          bottom[i]->count(),                       // count
          alpha,                             // alpha
          dis_.gpu_data(),                        // a
          Dtype(0),                           // beta
          bottom[i]->mutable_gpu_diff());                 // b
    }
  }
}

INSTANTIATE_LAYER_GPU_FUNCS(AbsoluteLossLayer);

}  // namespace caffe

第五步:用vs打开caffe,进行编译,编译成功后,恭喜你,功力又上升一个段位,哈哈

1.修改../windows/libcaffe下的两个文件:libcaffe.vcxproj和libcaffe.vcxproj.filters

libcaffe.vcxproj增加:

  1. <ClCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cpp" />  
  2. <ClInclude Include="..\..\include\caffe\layers\absolute_loss_layer.hpp" />  
  3. <CudaCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cu" />  
<ClCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cpp" />
<ClInclude Include="..\..\include\caffe\layers\absolute_loss_layer.hpp" />
<CudaCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cu" />
libcaffe.vcxproj.filter增加:
  1. <ClInclude Include="..\..\include\caffe\layers\absolute_loss_layer.hpp">  
  2. <Filter>include\layers</Filter>  
  3. </ClInclude>  
  4. <CudaCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cu">  
  5. <Filter>cu\layers</Filter>  
  6. </CudaCompile>  
  7. <ClCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cpp">  
  8. <Filter>src\layers</Filter>  
  9. </ClCompile>  
<ClInclude Include="..\..\include\caffe\layers\absolute_loss_layer.hpp">
<Filter>include\layers</Filter>
</ClInclude>
<CudaCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cu">
<Filter>cu\layers</Filter>
</CudaCompile>
<ClCompile Include="..\..\src\caffe\layers\absolute_loss_layer.cpp">
<Filter>src\layers</Filter>
</ClCompile>
2.打开caffe.sln,再进行重新生成新的解决方案,编译通过后,恭喜你功力又升一级!
0
0
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值