caffe中层:label从0开始

最近在做一个分类任务的实验的时候,对标签的取值产生了一些疑惑,所以看了一点对应的源代码,顺利解决了疑惑,在这里和大家分享,如果有什么理解错误还请大家指出。 
之前做分类任务的时候总有听说,标签(label)的取值需要从0开始,按照个人的习惯,我在之前的分类实验中,标签的取值一直也都是从0开始(假如有5类,那么label的取值就是0,1,2,3,4),没有作死取其他值,所以也一直一帆风顺。而在最近的实验中,偷懒了一下,虽然label的取值还是从0开始,但是出现了间断(还是假如有5类,那么label的取值就是类似0,1,2,4,5),训练的过程就出现了异常,这也是这一次探索label取值的起因。 
先把结论写下来,在不改写源码的情况下,label的取值有下面两点需要注意:

label的取值必须从0开始;
label必须是连续的整数(不能间断); 
总结起来就是:label的取值必须是从0开始的连续整数。 (假如有5类,那么label的取值1,2,3,4,5或者0,1,2,4,5都是不行的)。
下面来看看相应的源代码就比较清晰了。caffe中,单一标签的分类任务中一般在Accuracy和SoftmaxWithLoss这两个层中会用到label值,而这两个层对应的代码文件分别为accuracy_layer.cpp和softmax_loss_layer.cpp。

首先看一看accuracy_layer.cpp(关于accuracy_layer.cpp 的详细解读可以参考博文:link )。 
accuracy_layer.cpp 中的Forward_cpu 函数,有下面这段代码:

std::vector<std::pair<Dtype, int> > bottom_data_vector;
for (int k = 0; k < num_labels; ++k){
    bottom_data_vector.push_back(std::make_pair(bottom_data[i * dim + k * inner_num_ + j], k));
}
假如我们是5分类问题,那么这里的num_labels 就等于5,上面的for循环的目的在于将一个样本的最后一个全连接层(5个神经元)的值和对应的标签序号配对(这里是通过make_pair 的方式)。因为循环变量k是从0开始的,所以这里k的取值为0,1,2,3,4。是不是已经看出一点端倪了?嗯,继续往下看。

std::partial_sort(bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_,bottom_data_vector.end(),std::greater<std::pair<Dtype, int> >());
// check if true label is in top k predictions
for (int k = 0; k < top_k_; k++) {
  if (bottom_data_vector[k].second == label_value) {
    ++accuracy;
    if (top.size() > 1) ++top[1]->mutable_cpu_data()[label_value];
    break;
  }
}
这里的partial_sort 函数是对bottom_data_vector 中的元素根据其第一项的值(也就是全连接层神经元的值)进行降序排列(这一步的目的是将值越大也就是响应越大的神经元放在越前面)。top_k_ 指的是top几的准确率,比如在之前的ILSVRC中会有top_1或者top_5的的准确率,我们这里简单起见取top_1,也就是top_k_ 为1。 
下面的for循环对top_k_ 进行,我们这里top_k_为1,仅仅进行一次循环。if语句是,判断bottom_data_vector 的第1个元素的第二项(也就是响应最大的神经元的序号)和label_value 是否相等,如果相等,那么计数器accuracy 就加1。这里的label_value 就是我们在txt文件中定义的label值。如果label_value 不从0开始且连续的话,就会出现混乱。举个例子: 
假如我们在txt中的label取值(即label_value)为0,1,2,4,5,有一个样本A,它的label为5。当A样本作为网络的输入之后,最后一个神经元的响应最强烈,到这里一切都是完美和正确的!但是,经过上面的make_pair 所在的for循环,程序认为最后一个神经元的序号为4。所以在下面判断是否分类正确的时候(if (bottom_data_vector[k].second == label_value)),因为4不等于5,所以程序认为这个样本分类错误了!

同样等混乱会出现在softmax_loss_layer.cpp 中,在Forward_cpu 函数中有下面这句代码:

loss -= log(std::max(prob_data[i * dim + label_value * inner_num_ + j], Dtype(FLT_MIN)));
这句代码是在计算loss,而label_value 在这里是作为一个构成指针偏移量的项(构成指针偏移量的其它项的具体含义可以参见上面关于accuracy_layer.cpp的参考博文),所以如果label_value 不是从0开始的连续整数,会使索引出现混乱,出现loss爆炸的情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值