2016-11-01 36 views
6

我正在查看Caffe的SigmoidCrossEntropyLoss layerdocs的代码,我有点困惑。文档列出了丢失函数作为logit损失(我在这里复制它,但没有Latex,公式将难以阅读,请查看文档链接,它位于最上面)。Caffe SigmoidCrossEntropyLoss图层丢失函数

但是,代码本身(Forward_cpu(...))示出了不同的配方

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - 
     log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

是因为这是占S形函数具有已经施加到输入?

但是,即使如此,(input_data[i] >= 0)片段也令我困惑。这些似乎代替了文档中丢失公式中的p_hat,它被认为是由S形函数压缩的预测。那么他们为什么只是采取二元门槛?由于这种损失预测了[0,1]输出,所以更令人困惑,因此(input_data[i] >= 0)将是1,除非它100%确定它不是。

有人可以向我解释这个吗?

回答

6

SigmoidCrossEntropy层在CAFFE结合2个步骤(Sigmoid + CrossEntropy),将上input_data执行成一体的代码:

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - 
     log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

事实上,不管是否input_data >= 0与否,上述代码是始终相当于数学以下代码:

Dtype loss = 0; 
for (int i = 0; i < count; ++i) { 
    loss -= input_data[i] * (target[i] - 1) - 
     log(1 + exp(-input_data[i]); 
} 
top[0]->mutable_cpu_data()[0] = loss/num; 

,该代码是基于简单的数学公式施加Sigmoid和后在input_data上,并在数学中进行一些组合。

但第一代码段(CAFFE使用)拥有多个数值稳定性和需要溢出的风险更小,因为它避免了计算一个大exp(input_data)(或exp(-input_data))时的input_data绝对值过大。这就是为什么你看到咖啡中的代码。

+0

因此,如果有人要使用软的地面实况标签(即[0,1]而不是{0,1}),是否有必要改变? – marcman

+0

如果地面实况标签的总和等于1,那么这层应该没有变化。否则,您应该对网络的每个输出应用交叉熵进行一些更改。 @marcman – Dale

+0

我想我明白为什么不这样,但在实践中,当我标准化每个标签时,我开始承受NaN损失,尽管这可能是一个学习率问题 – marcman