[翻譯] softmax和softmax_cross_entropy_with_logits的區別


 

翻譯自:https://stackoverflow.com/questions/34240703/whats-the-difference-between-softmax-and-softmax-cross-entropy-with-logits

 

問題:

在Tensorflow官方文檔中,他們使用一個關鍵詞,稱為logits。這個logits是什么?比如說在API文檔中有很多方法(methods),經常像下面這么寫:

tf.nn.softmax(logits, name=None)

另外一個問題是,有2個方法我不知道該怎么區分,它們是:

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

它們之間的區別是什么?

 

回答:

簡短版本:

假設你有2個tensors,其中y_hat包含每個類預測的得分(比如說,從y = W*x +b計算得到),y_true包含one-hot編碼后的正確的label。

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

如果你將y_hat的得分解釋為未歸一化的log概率,那么它們就是logits

另外,總的交叉熵損失可以用如下方式計算得到:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

從本質上來說,與用softmax_cross_entropy_with_logits()函數計算得到的總的交叉熵損失是一樣的,計算方法為:

total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

完整版:

舉個例子,我們創建一個2x3大小的y_hat,其中行對應着訓練樣本,列對應類別。因此,這里有2個訓練樣本和3個類別。

import tensorflow as tf
import numpy as np

sess = tf.Session()

# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5,  1.5,  0.1],
#       [ 2.2,  1.3,  1.7]])

注意到這些值並沒有歸一化(每一行加起來並不等於1)。為了歸一化這些數,我們可以使用softmax函數,這個函數的輸入就是未歸一化的log概率(也稱為logits),輸出是歸一化的線性概率。

y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863  ,  0.61939586,  0.15274114],
#      [ 0.49674623,  0.20196195,  0.30129182]])

完全理解softmax輸出的內容是很重要的。下面我將展示一個表格來更加清楚地解釋上面的輸出。從表格中可以看出來,訓練樣本實例1屬於類別2的概率是0.619,每個訓練樣本實例的類概率被歸一化,所有每一行的和是1.0。

                      Pr(Class 1)  Pr(Class 2)  Pr(Class 3)
                     --------------------------------------
Training instance 1 | 0.227863   | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182

 

現在我們有了每個訓練樣本在每個類上的概率,我們可以對每一行使用argmax()來產生一個最終的分類結果。從上面的表格上來看,我們可以判斷出訓練樣本實例1屬於類別2,訓練樣本實例2屬於類別1。

 

那么,這些分類正確么?我們需要根據訓練樣本正確的標簽來衡量。你需要一個one-hot編碼的y_true數組,其中每一行表示訓練樣本實例,每一列表示類別。下面我將創建一個例子,y_true為one-hot編碼的數組,其中對於訓練樣本1正確的標簽是類別2,對於訓練樣本2正確的標簽是類別3。

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0.,  1.,  0.],
#        [ 0.,  0.,  1.]])

y_hat_softmax的概率分布接近y_true的概率分布么?我們可以使用交叉熵損失( cross-entropy loss)來衡量錯誤程度。

根據下面的式子,我們可以計算出每一行的交叉熵損失。從下面的結果中可以看出訓練樣本1的損失為0.479,訓練樣本2的損失比較高,是1.200。這個結果是有道理的,因為y_hat_softmax顯示訓練樣本1的最高概率是類別2,與正確標簽y_true匹配,而訓練樣本2的最高概率預測為類別1,與實際標簽(類別3)不匹配。

loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 ,  1.19967598])

我們想要的是訓練集上的所有的loss,因此我們需要將每個訓練樣本的loss加起來,如下:

total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944

 

使用softmax_cross_entropy_with_logits()

 

我們也可以使用tf.nn.softmax_cross_entropy_with_logits()函數來計算整個交叉熵損失,代碼如下:

loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 ,  1.19967598])

total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922

注意到,total_loss_1和total_loss_2計算得到的結果是基本一樣的(有一點點小的差別)。然而,還是建議使用第二種方法,原因是1)代碼量更少,2)方法二的內部考慮到了一些邊界情況,不容易產生錯誤。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM