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() 計算損失。
