1. 程式人生 > >pytorch筆記:03)softmax和log_softmax,以及CrossEntropyLoss

pytorch筆記:03)softmax和log_softmax,以及CrossEntropyLoss

softmax在神經網路裡面比較常見,簡而言之,就是多分類的概率輸出

s o t f
m a x ( x i ) = exp ( x
i
)
j exp ( x j
)

但是在pytorch裡面發現額外有個log_softmax( 對softmax取了一個In的對數),為啥這樣做呢?
其實涉及到 對數似然損失函式,對於用於分類的softmax啟用函式,對應的損失函式一般都是用對數似然函式,即:
J ( W , b , a L , y ) = k y k l n a k L
其中 l n a k 為softmax函式的輸出元, y k 的取值為0或者1,如果某一訓練樣本的輸出為第i類。則 y i = 1 ,其餘的 j i 都有 y j =0。由於每個樣本只屬於一個類別,所以這個對數似然函式可以簡化為:
J ( W , b , a L , y ) = l n a i L
其中 i 即為訓練樣本真實的類別序號。

pytorch裡面提供了一個實現 torch.nn.CrossEntropyLoss(This criterion combines nn.LogSoftmax() and nn.NLLLoss() in one single class),其整合了上面的步驟。這和tensorflow中的tf.nn.softmax_cross_entropy_with_logits函式的功能是一致的。必須明確一點:在pytorch中若模型使用CrossEntropyLoss這個loss函式,則不應該在最後一層再使用softmax進行啟用

然而在keras中,我們固化了模型的搭建,諸如:

model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adadelta(),metrics=['accuracy'])

我們通常在最後一層使用softmax進行啟用,保證輸出神經元的值即分類的概率值,然後在compile中使用損失函式categorical_crossentropy,這符合常理。其實可以看下keras底層的實現,其實它幫我們手動地計算了crossentropy。

def categorical_crossentropy(target, output, from_logits=False):

    if not from_logits:
        # scale preds so that the class probas of each sample sum to 1
        output /= tf.reduce_sum(output,
                                len(output.get_shape()) - 1,
                                True)
        # manual computation of crossentropy
        _epsilon = _to_tensor(epsilon(), output.dtype.base_dtype)
        output = tf.clip_by_value(output, _epsilon, 1. - _epsilon)
        return - tf.reduce_sum(target * tf.log(output),
                               len(output.get_shape()) - 1)
    else:
        return tf.nn.softmax_cross_entropy_with_logits(labels=target,
                                                       logits=output)

題外話:
為什麼要糾結這個問題?
在天池的一個比賽中,要輸出每個類別的取值概率,使用keras直接輸出最後一層即可;然而在pytorch中softmax整合到了損失函式中,最後一層沒有使用softmax進行啟用。

reference:
對數似然損失函式 http://www.cnblogs.com/pinard/p/6437495.html