2016-11-01 72 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