1

我需要帮助来理解 Caffe 函数,SigmoidCrossEntropyLossLayer它是逻辑激活的交叉熵误差。

基本上,具有 N 个独立目标的单个示例的交叉熵误差表示为:

 - sum-over-N( t[i] * log(x[i]) + (1 - t[i]) * log(1 - x[i] ) 

其中t是目标,0 或 1,x是输出,由 索引ix,当然要经过逻辑激活。

用于更快交叉熵计算的代数技巧将计算减少到:

 -t[i] * x[i] + log(1 + exp(x[i])) 

您可以从此处的第 3 节验证这一点。

问题是,如何将上面的代码转换为下面的损失计算代码:

   loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) -
        log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0)));

谢谢你。

为方便起见,将功能复制如下。

   template <typename Dtype>
    void SigmoidCrossEntropyLossLayer<Dtype>::Forward_cpu(
        const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
      // The forward pass computes the sigmoid outputs.                                                                                                                                                                                    
      sigmoid_bottom_vec_[0] = bottom[0];
      sigmoid_layer_->Forward(sigmoid_bottom_vec_, sigmoid_top_vec_);
      // Compute the loss (negative log likelihood)                                                                                                                                                                                        
      // Stable version of loss computation from input data                                                                                                                                                                                
      const Dtype* input_data = bottom[0]->cpu_data();
      const Dtype* target = bottom[1]->cpu_data();
      int valid_count = 0;
      Dtype loss = 0;
      for (int i = 0; i < bottom[0]->count(); ++i) {
        const int target_value = static_cast<int>(target[i]);
        if (has_ignore_label_ && target_value == ignore_label_) {
          continue;
        }
        loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) -
            log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0)));
        ++valid_count;
      }
      normalizer_ = get_normalizer(normalization_, valid_count);
      top[0]->mutable_cpu_data()[0] = loss / normalizer_;
    }
4

1 回答 1

2

在表达式中,如果非常大log(1 + exp(x[i])),您可能会遇到数值不稳定。x[i]为了克服这种数值不稳定性,可以像这样缩放 sigmoid 函数:

 sig(x) = exp(x)/(1+exp(x)) 
        = [exp(x)*exp(-x(x>=0))]/[(1+exp(x))*exp(-x(x>=0))]

现在,如果您将新的稳定表达式 forsig(x)插入到损失中,您最终将得到与 caffe 使用的相同的表达式。

享受!

于 2017-01-23T09:04:28.107 回答