centerloss 理解
来源:互联网 发布:java web start 编辑:程序博客网 时间:2024/06/01 09:35
今天看了一下centerloss 源码 ,觉得还是挺值得借鉴的,所以分享一下。
centerloss主要在caffe的基础上加了三项。
一. caffe.proto
1.加proto 格式 的 ID号147
2.加proto格式的定义
这里面的参数都是层的参数,也是超参,在prototxt中赋值。
axis是默认为1的。
二.加入hpp 文件到include/caffe/layers/ ,
主要包含cpp文件的方法和参数的定义。
三.加入cpp文件到src/caffe/layers/
#include <vector>#include "caffe/filler.hpp"#include "caffe/layers/center_loss_layer.hpp"#include "caffe/util/math_functions.hpp"namespace caffe {template <typename Dtype>void CenterLossLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const int num_output = this->layer_param_.center_loss_param().num_output(); N_ = num_output; const int axis = bottom[0]->CanonicalAxisIndex( //一个常见的blob数据包括(N,C,H,W)四个维度,可以通过设定axis来选取哪一个维度 this->layer_param_.center_loss_param().axis());//把axis后面的都拉为一个向量,最后是chw变成k维的 // Dimensions starting from "axis" are "flattened" into a single // length K_ vector. For example, if bottom[0]'s shape is (N, C, H, W), // and axis == 1, N inner products with dimension CHW are performed. K_ = bottom[0]->count(axis); // Check if we need to set up the weights if (this->blobs_.size() > 0) { LOG(INFO) << "Skipping parameter initialization"; } else { this->blobs_.resize(1); // Intialize the weight vector<int> center_shape(2); center_shape[0] = N_; center_shape[1] = K_; this->blobs_[0].reset(new Blob<Dtype>(center_shape));//尺寸设成centershape的大小 // fill the weights shared_ptr<Filler<Dtype> > center_filler(GetFiller<Dtype>( this->layer_param_.center_loss_param().center_filler()));// Fillers are random number generators that fills a blob using the specified algorithm. //这个很重要,就是如何初始化,这里是使用prototxt中定义的xavier方法初始化,可以看到 //center_loss_param { // num_output: 10572 //center_filler { // type: "xavier" // } // } center_filler->Fill(this->blobs_[0].get()); } // parameter initialization this->param_propagate_down_.resize(this->blobs_.size(), true);}template <typename Dtype>void CenterLossLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_EQ(bottom[1]->channels(), 1); CHECK_EQ(bottom[1]->height(), 1); CHECK_EQ(bottom[1]->width(), 1); M_ = bottom[0]->num(); // The top shape will be the bottom shape with the flattened axes dropped, // and replaced by a single axis with dimension num_output (N_). LossLayer<Dtype>::Reshape(bottom, top); distance_.ReshapeLike(*bottom[0]); variation_sum_.ReshapeLike(*this->blobs_[0]);}template <typename Dtype>void CenterLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data();//输入的倒数第二个卷积层的feature const Dtype* label = bottom[1]->cpu_data();//输入的label const Dtype* center = this->blobs_[0]->cpu_data();//指针指向,后面会赋值给这个地方 Dtype* distance_data = distance_.mutable_cpu_data();//存储每一类xi-cyi的地方 // the i-th distance_data for (int i = 0; i < M_; i++) { const int label_value = static_cast<int>(label[i]);//第i类 // D(i,:) = X(i,:) - C(y(i),:) caffe_sub(K_, bottom_data + i * K_, center + label_value * K_, distance_data + i * K_);//算好减法,这里这个center很有意思,因为只在前向传播中出现,让人怀疑为什么它存储了center的值。其实是这样,它指向的是blob_[0]中的cpu_data,然后在更新参数时,会自动加上反向传播时计算好的center_diff,即blobs_[0]->mutable_cpu_diff()。 } Dtype dot = caffe_cpu_dot(M_ * K_, distance_.cpu_data(), distance_.cpu_data());//这是vector的乘积,而非matrix,算好l2范数 Dtype loss = dot / M_ / Dtype(2);//算好前面的项 top[0]->mutable_cpu_data()[0] = loss;//存好loss}template <typename Dtype>void CenterLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { // Gradient with respect to centers if (this->param_propagate_down_[0]) { const Dtype* label = bottom[1]->cpu_data();//标签 Dtype* center_diff = this->blobs_[0]->mutable_cpu_diff();//存center更新值的地方。 Dtype* variation_sum_data = variation_sum_.mutable_cpu_data(); const Dtype* distance_data = distance_.cpu_data();//上面这两个都是存中间的值。 // \sum_{y_i==j} caffe_set(N_ * K_, (Dtype)0., variation_sum_.mutable_cpu_data());//设置为0 for (int n = 0; n < N_; n++) { int count = 0; for (int m = 0; m < M_; m++) { const int label_value = static_cast<int>(label[m]); if (label_value == n) { count++; caffe_sub(K_, variation_sum_data + n * K_, distance_data + m * K_, variation_sum_data + n * K_); } //distance_data里面存的是前向时存的D(i,:) = X(i,:) - C(y(i),:) } caffe_axpy(K_, (Dtype)1./(count + (Dtype)1.), variation_sum_data + n * K_, center_diff + n * K_);前面第二第三个相乘存到最后一个 } } // Gradient with respect to bottom data //就是Lc对xi求偏导数 if (propagate_down[0]) { caffe_copy(M_ * K_, distance_.cpu_data(), bottom[0]->mutable_cpu_diff()); caffe_scal(M_ * K_, top[0]->cpu_diff()[0] / M_, bottom[0]->mutable_cpu_diff());//这里求l2范数的导数 ,bottom[0]->mutable_cpu_diff()只是D(i,:) = X(i,:) - C(y(i),:)。 } if (propagate_down[1]) { LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; }}#ifdef CPU_ONLYSTUB_GPU(CenterLossLayer);#endifINSTANTIATE_CLASS(CenterLossLayer);REGISTER_LAYER_CLASS(CenterLoss);} // namespace caffe
最后附上我随手写的非常潦草的论文阅读笔记,上面一些备注有利于加深对centerloss的理解
阅读全文
1 0
- centerloss 理解
- centerloss new lfw result
- CenterLoss的caffe实现
- centerloss的论文解读
- centerloss论文学习笔记
- 人脸识别系列-Centerloss论文阅读笔记
- 人脸识别之端到端框架(四)--CenterLoss
- centerloss系列文章笔记——人脸检测Face R-CNN
- 17.11.15 centerloss使用的时候需要注意的一些点
- centerloss系列文章笔记——人脸识别:A Discriminative Feature Learning Approach forDeep Face Recognition
- 理解
- 理解
- 理解
- 理解
- 理解
- 理解
- 理解
- 理解
- Cannot forward after response has beencommitted问题分析及解决
- React-Native基础_3.Flex布局
- java学习(23)_运行时异常总结
- ffmpeg-php 安装
- JavaScript数据类型
- centerloss 理解
- Android Material Design 之 Toolbar
- Struts2.5通配符失效问题的解决
- java连接redis
- Java SSH Web实例
- ubuntu 12.04下搭建web服务器(MySQL+PHP+Apache) 教程
- 包含min函数的栈
- 文章标题
- 特征缩放