2016-09-19 56 views
4

當我試圖在tensorflow中使用sparse_softmax_cross_entropy_with_logits損失函數時,我得到了NaN。我有一個簡單的網絡,是這樣的:NaN from Sparse_softmax_cross_entropy_with_logits in Tensorflow

layer = tf.nn.relu(tf.matmul(inputs, W1) + b1) 
layer = tf.nn.relu(tf.matmul(inputs, W2) + b2) 
logits = tf.matmul(inputs, W3) + b3 
loss = tf.sparse_softmax_cross_entropy_with_logits(logits, labels) 

我有很多類(〜10000),所以我想我得到NaN的,因爲相應的糾正我的例子至少一個班的Logit得到截斷爲零。有沒有辦法避免這種情況?

回答

6

事實上,我的一些標籤超出範圍(例如14000的標籤,當我的logits矩陣只有150 x 10000)。事實證明,這導致NaN而不是錯誤。

+0

你能解釋一下你的意思是「標籤超出範圍」嗎?我認爲對於每個樣本,標籤都是與logit匹配的向量長度。我試過'a = tf.constant(np.array([[200.1,20000.3,.5,.9],[1.0,10000.0,10.0,10.0])) l = tf.constant(np.array([ [1,1,1,1,1],[1,0,0]])) s.run(tf.nn.softmax_cross_entropy_with_logits(logits = a,labels = 1))'。當維度不匹配時,會抱怨維度;如果概率> 1,則不會導致錯誤或「NaN」。 「14000標籤」是什麼意思? –

+0

區別在於我使用'tf。sparse_softmax_cross_entropy_with_logits「,因此輸入是標籤的索引。當我說超出範圍時,我的意思是我提供了(例如)索引23,而每個例子只提供了7個logits。 –

3

tf.sparse_softmax_cross_entropy_with_logits爲您處理log(0)的情況,您不必擔心它。

通常NaN是由於您的優化算法的高學習率。嘗試降低它,直到NaN錯誤消失,損失開始減少

0

NaN錯誤可能發生時,其中一個softmaxed logits被截斷爲0,如您所說,然後它執行log(0)來計算交叉熵錯誤。

爲了避免這種情況,正如在this other answer中建議的那樣,您可以剪切softmax輸出的值,使其不會爲零。

out = tf.clip_by_value(out,1e-10,100.0) 

或者你可以添加一個很小的常數,以避免零:

out = out + 1e-10 

它的問題是,SOFTMAX功能上logits內部施加通過sparse_softmax_cross_entropy_with_logits()所以你不能改變它的行爲。

爲了克服這個問題,您自己編碼交叉熵錯誤,並將常數1e-10添加到softmax的輸出中,而不是添加到logits中。

loss = -tf.reduce_sum(labels*tf.log(tf.nn.softmax(logits) + 1e-10)) 

注意與sparse_softmax_cross_entropy_with_logits()函數變量labels是標籤的數值,但如果實現了交叉熵損失自己,labels必須是這些數字標籤的一個熱編碼。

更新:我已更正了答案,感謝@mdaoust的評論。正如他所說的,只有在softmax函數應用於logits之後,零纔有意義,而不是之前。

+1

零的logit沒有特別之處。 logits可能是負面的。剪切到[-100,100]會更合理,但可能無法解決問題。 – mdaoust

+1

你說得對,只有當softmax輸出爲零時纔有意義,如果logit爲零則不重要。謝謝! – gcucurull