我正在查看Caffe SigmoidCrossEntropyLoss layer和docs的代码,我有点困惑。文档将损失函数列为logit loss(我在这里复制它,但是没有Latex,公式将很难阅读。查看文档链接,它位于最顶层)。
但是,代码本身(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;
是否因为这是因为已经应用于输入的sigmoid函数?
然而,即便如此,(input_data[i] >= 0)
片段也让我感到困惑。那些看起来代替了文档中损失公式的p_hat,这应该是由sigmoid函数压缩的预测。那么为什么他们只是采取二进制阈值?由于此丢失预测[0,1]输出,因此更加令人困惑,因此(input_data[i] >= 0)
将是1
,除非它100%确定不是。{/ p>
有人可以向我解释一下吗?
答案 0 :(得分:6)
caffe中的SigmoidCrossEntropy
图层将在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
上应用CrossEntropy
和input_data
并在数学中进行某些组合后的简单数学公式。
但是第一段代码(caffe使用)拥有更多的数值稳定性并且降低了溢出的风险,因为它避免了在绝对值时计算大的exp(input_data)
(或exp(-input_data)
) input_data
太大了。这就是你在caffe中看到代码的原因。