如何在caffe中增加layer以及caffe中triplet loss layer的实现

2.在./include/caffe/loss_layers.hpp中增加triplet loss layer的类的声明

具体解释见注释,主要的是定义了一些变量,用来在前传中存储中间计算结果,以便在反传的时候避免重复计算。

/** * @brief Computes the triplet loss */template <typename Dtype>class TripletLossLayer : public LossLayer<Dtype> { public: explicit TripletLossLayer(const LayerParameter& param): LossLayer<Dtype>(param){} virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top); virtual inline int ExactNumBottomBlobs() const { return 4; } virtual inline const char* type() const { return "TripletLoss"; } /** * Unlike most loss layers, in the TripletLossLayer we can backpropagate * to the first three inputs. */ virtual inline bool AllowForceBackward(const int bottom_index) const {return bottom_index != 3; } protected: 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> diff_ap_; // cached for backward pass Blob<Dtype> diff_an_; // cached for backward pass Blob<Dtype> diff_pn_; // cached for backward pass Blob<Dtype> diff_sq_ap_; // cached for backward pass Blob<Dtype> diff_sq_an_; // tmp storage for gpu forward pass Blob<Dtype> dist_sq_ap_; // cached for backward pass Blob<Dtype> dist_sq_an_; // cached for backward pass Blob<Dtype> summer_vec_; // tmp storage for gpu forward pass Blob<Dtype> dist_binary_; // tmp storage for gpu forward pass};3.在./src/caffe/layers/目录下新建triplet_loss_layer.cpp,实现类

主要实现三个功能:

LayerSetUp:主要是做一些CHECK工作,,然后根据bottom和top对类中的数据成员初始化。

Forward_cpu:前传,计算loss

Backward_cpu:反传,计算梯度。

/* * triplet_loss_layer.cpp * * Created on: Jun 2, 2015 *Author: tangwei */#include <algorithm>#include <vector>#include "caffe/layer.hpp"#include "caffe/loss_layers.hpp"#include "caffe/util/io.hpp"#include "caffe/util/math_functions.hpp"namespace caffe {template <typename Dtype>void TripletLossLayer<Dtype>::LayerSetUp( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { LossLayer<Dtype>::LayerSetUp(bottom, top); CHECK_EQ(bottom[0]->num(), bottom[1]->num()); CHECK_EQ(bottom[1]->num(), bottom[2]->num()); CHECK_EQ(bottom[0]->channels(), bottom[1]->channels()); CHECK_EQ(bottom[1]->channels(), bottom[2]->channels()); CHECK_EQ(bottom[0]->height(), 1); CHECK_EQ(bottom[0]->width(), 1); CHECK_EQ(bottom[1]->height(), 1); CHECK_EQ(bottom[1]->width(), 1); CHECK_EQ(bottom[2]->height(), 1); CHECK_EQ(bottom[2]->width(), 1); CHECK_EQ(bottom[3]->channels(),1); CHECK_EQ(bottom[3]->height(), 1); CHECK_EQ(bottom[3]->width(), 1); diff_ap_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); diff_an_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); diff_pn_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); diff_sq_ap_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); diff_sq_an_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); dist_sq_ap_.Reshape(bottom[0]->num(), 1, 1, 1); dist_sq_an_.Reshape(bottom[0]->num(), 1, 1, 1); // vector of ones used to sum along channels summer_vec_.Reshape(bottom[0]->channels(), 1, 1, 1); for (int i = 0; i < bottom[0]->channels(); ++i) summer_vec_.mutable_cpu_data()[i] = Dtype(1); dist_binary_.Reshape(bottom[0]->num(), 1, 1, 1);for (int i = 0; i < bottom[0]->num(); ++i)dist_binary_.mutable_cpu_data()[i] = Dtype(1);}template <typename Dtype>void TripletLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) { int count = bottom[0]->count(); const Dtype* sampleW = bottom[3]->cpu_data(); caffe_sub(count,bottom[0]->cpu_data(), // abottom[1]->cpu_data(), // pdiff_ap_.mutable_cpu_data()); // a_i-p_i caffe_sub(count,bottom[0]->cpu_data(), // abottom[2]->cpu_data(), // ndiff_an_.mutable_cpu_data()); // a_i-n_i caffe_sub(count,bottom[1]->cpu_data(), // pbottom[2]->cpu_data(), // ndiff_pn_.mutable_cpu_data()); // p_i-n_i const int channels = bottom[0]->channels(); Dtype margin = this->layer_param_.triplet_loss_param().margin(); Dtype loss(0.0); for (int i = 0; i < bottom[0]->num(); ++i) {dist_sq_ap_.mutable_cpu_data()[i] = caffe_cpu_dot(channels,diff_ap_.cpu_data() + (i*channels), diff_ap_.cpu_data() + (i*channels));dist_sq_an_.mutable_cpu_data()[i] = caffe_cpu_dot(channels,diff_an_.cpu_data() + (i*channels), diff_an_.cpu_data() + (i*channels));Dtype mdist = sampleW[i]*std::max(margin + dist_sq_ap_.cpu_data()[i] – dist_sq_an_.cpu_data()[i], Dtype(0.0));loss += mdist;if(mdist==Dtype(0)){//dist_binary_.mutable_cpu_data()[i] = Dtype(0);//prepare for backward passcaffe_set(channels, Dtype(0), diff_ap_.mutable_cpu_data() + (i*channels));caffe_set(channels, Dtype(0), diff_an_.mutable_cpu_data() + (i*channels));caffe_set(channels, Dtype(0), diff_pn_.mutable_cpu_data() + (i*channels));} } loss = loss / static_cast<Dtype>(bottom[0]->num()) / Dtype(2); top[0]->mutable_cpu_data()[0] = loss;}template <typename Dtype>void TripletLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { //Dtype margin = this->layer_param_.contrastive_loss_param().margin(); const Dtype* sampleW = bottom[3]->cpu_data(); for (int i = 0; i < 3; ++i) {if (propagate_down[i]) {const Dtype sign = (i < 2) ? -1 : 1;const Dtype alpha = sign * top[0]->cpu_diff()[0] /static_cast<Dtype>(bottom[i]->num());int num = bottom[i]->num();int channels = bottom[i]->channels();for (int j = 0; j < num; ++j) {Dtype* bout = bottom[i]->mutable_cpu_diff();if (i==0) { // a//if(dist_binary_.cpu_data()[j]>Dtype(0)){caffe_cpu_axpby(channels,alpha*sampleW[j],diff_pn_.cpu_data() + (j*channels),Dtype(0.0),bout + (j*channels));//}else{// caffe_set(channels, Dtype(0), bout + (j*channels));//}} else if (i==1) { // p//if(dist_binary_.cpu_data()[j]>Dtype(0)){caffe_cpu_axpby(channels,alpha*sampleW[j],diff_ap_.cpu_data() + (j*channels),Dtype(0.0),bout + (j*channels));//}else{// caffe_set(channels, Dtype(0), bout + (j*channels));//}} else if (i==2) { // n//if(dist_binary_.cpu_data()[j]>Dtype(0)){caffe_cpu_axpby(channels,alpha*sampleW[j],diff_an_.cpu_data() + (j*channels),Dtype(0.0),bout + (j*channels));//}else{// caffe_set(channels, Dtype(0), bout + (j*channels));//}}} // for num} //if propagate_down[i] } //for i}#ifdef CPU_ONLYSTUB_GPU(TripletLossLayer);#endifINSTANTIATE_CLASS(TripletLossLayer);REGISTER_LAYER_CLASS(TripletLoss);} // namespace caffe4.在./src/caffe/layers/目录下新建triplet_loss_layer.cu,实现GPU下的前传和反传

在GPU下实现前传和反传

每当我看天的时候我就不喜欢再说话,每当我说话的时候我却敢看天。

如何在caffe中增加layer以及caffe中triplet loss layer的实现

相关文章:

你感兴趣的文章:

标签云: