pytorch 計算 CrossEntropyLoss 不需要經 softmax 層激活!
用 pytorch
實現自己的網絡時,如果使用CrossEntropyLoss
我總是將網路輸出經 softmax
激活層後再計算交叉熵損失是不對的。
考慮樣本空間的類集合爲 {0,1,2}
,網絡最後一層有 3
個神經元(每個神經元激活值代表對不同類的響應強度),某個樣本送入網絡後的輸出記爲 net_out: [1,2,3]
, 該樣本的真實標籤爲 0
.
那麼交叉熵損失的手動計算結果爲:
- ln 【 e1 / ( e1 + e2 + e3 ) 】 = 2.4076
- 網絡輸出不經 softmax 層,直接由 CrossEntropyLoss 計算交叉熵損失
from torch.autograd import Variable
from torch import nn
in:
net_out = Variable(torch.Tensor([[1,2,3]]))
target = Variable( torch.LongTensor([0]))
criterion = nn.CrossEntropyLoss()
criterion(net_out,target)
out:
Variable containing:
2.4076
[torch.FloatTensor of size 1]
輸出結果爲 2.4076
,與手動計算結果一致。
- 網絡輸出先經 softmax 層,再由 CrossEntropyLoss 計算交叉熵損失
in:
from torch.autograd import Variable
net_out = Variable(torch.Tensor([[1,2,3]]))
target = Variable( torch.LongTensor([0]))
softmax = nn.Softmax()
print(softmax(net_out))
criterion = nn.CrossEntropyLoss()
print(criterion(softmax(net_out),target))
out:
Variable containing:
0.0900 0.2447 0.6652
[torch.FloatTensor of size 1x3]
Variable containing:
1.3724
[torch.FloatTensor of size 1]
輸出結果爲 1.3724
, 與手動計算結果不一致。事實上,CrossEntropyLoss()
是 softmax
和 負對數損失的結合。明確這點後,就不難明白1.374
是怎麼來的了:
- ln 【 e0.09 / ( e0.09 + e0.2447 + e0.6552 ) 】 = 1.374
補充:
如果用 nn.BCELoss()
計算二進制交叉熵, 需要先將 logit
經 sigmod()
層激活再送入 nn.BCELoss()
計算損失。