caffe中loss函数代码分析--caffe学习(16)
来源:互联网 发布:点点虫 知乎 编辑:程序博客网 时间:2024/05/18 01:15
接上篇:caffe中样本的label一定要从序号0开始标注吗?–caffe学习(15)
A:
1:数学上来说,损失函数loss值和label从0开始还是从1或者100开始是没有直接联系的,以欧式距离损失函数(Euclidean Loss)为例子:
2:铰链损失函数(Hinge Loss)这个loss就是SVM用到的loss。
对于多类的版本中,Crammer and Singer使用这种定义来分类多类:
loss最小化就是尽可能地使得所有和正确类别y差别最大的类别之和最小。WyX就是正确类别的分数Y。这里都没有加入正则化权重W,是为了简单。现在基本都有使用权重正则化来计算loss。
从SVM的分类函数来看我们依然没有看到和类别标号起始数值有关的证明。下面就开始分析caffe中的loss计算方法。
关于算法具体部分参考:http://blog.csdn.net/u014114990/article/details/47802993
WIKI:https://en.wikipedia.org/wiki/Hinge_loss
B:caffe中loss函数代码分析:
首先caffe是支持多个层计算loss的,所以有loss_weight这一个参数,当只有一个loss层时,该层的loss_weight自然为1,如果有两个loss层,权重可以死0.5+0.5或者自己生0.6+0.4之类的:
参考caffe官网中译版:
代码分析:
loss_layer.cpp:
void LossLayer<Dtype>::LayerSetUp( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { // LossLayers have a non-zero (1) loss by default. if (this->layer_param_.loss_weight_size() == 0) { //看这里 this->layer_param_.add_loss_weight(Dtype(1)); }}
这只是初始化,下面看具体的前向计算以Hinge_Loss_layer.cpp为例:
void HingeLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); const Dtype* label = bottom[1]->cpu_data(); int num = bottom[0]->num(); int count = bottom[0]->count(); int dim = count / num; caffe_copy(count, bottom_data, bottom_diff); for (int i = 0; i < num; ++i) { bottom_diff[i * dim + static_cast<int>(label[i])] *= -1; } for (int i = 0; i < num; ++i) { for (int j = 0; j < dim; ++j) { bottom_diff[i * dim + j] = std::max( Dtype(0), 1 + bottom_diff[i * dim + j]); } } Dtype* loss = top[0]->mutable_cpu_data(); switch (this->layer_param_.hinge_loss_param().norm()) { case HingeLossParameter_Norm_L1: loss[0] = caffe_cpu_asum(count, bottom_diff) / num; break; case HingeLossParameter_Norm_L2: loss[0] = caffe_cpu_dot(count, bottom_diff, bottom_diff) / num; break; default: LOG(FATAL) << "Unknown Norm"; }
可以看到label 仅使用了一次,在:
for (int i = 0; i < num; ++i) { bottom_diff[i * dim + static_cast<int>(label[i])] *= -1; }
实际上对比上面的公式这里是很容易理解的,从实现的角度也没有看到和label的起始值有关的数据。因此这应该是一个magic,我们使用的时候还是遵照从0开始标号就好。
代码的最后实现了两种归一化函数L1和L2,见下篇分析:
L1归一化和L2归一化范数的详解和区别
- caffe中loss函数代码分析--caffe学习(16)
- caffe中各种loss函数
- caffe中的loss函数
- Caffe学习:Loss
- Caffe学习:Loss
- Caffe学习:Loss
- 梳理caffe代码loss(二十二)
- 梳理caffe代码loss(二十二)
- 学习Caffe(四)Loss Layer解析
- caffe 中的损失函数分析以及loss function
- caffe 中的损失函数分析以及loss function
- caffe学习笔记3.3--Loss
- 深度学习之caffe Loss
- caffe loss
- caffe loss
- caffe loss
- Caffe loss
- Caffe 中loss计算过程
- 微信小程序如何请求数据,如何配置服务器
- 程序中“导出列表”功能出错的解决方法
- ftl中特殊关键字原样输出
- 前端应该掌握setTimeout的秘密
- Zookeeper笔记
- caffe中loss函数代码分析--caffe学习(16)
- Java 多线程常见面试问题
- Linux从控制台一次读取一个字符,无需等待回车键
- dockerfile介绍
- For A, B such that AB is square, prove trAB = trBA.
- redis的基本信息
- 好的文章记录
- 一个进程在内存中的布局
- Trafodion Bulk Load 对比 Native HBase Bulk Load