首先我們來看一下nn和nn.functional有什麼區別
nn.functional.xxx是函數接口,而nn.Xxx是nn.functional.xxx的類封裝,並且nn.Xxx都繼承於一個共同祖先nn.Module。這一點導致nn.Xxx除了具有nn.functional.xxx功能之外,內部附帶了nn.Module相關的屬性和方法,例如train(), eval(),load_state_dict, state_dict 等。
nn.functional.xxx 就是直接調用
nn.functional.NLLLoss(nn.functional.log_softmax(data),target)
nn.Xxx 就是先定義,之後用的時候再賦值,如
loss = nn.NLLLoss()
conv = nn.Conv2d(16, C, (3, 3))
m = nn.LogSoftmax(dim=1)
#下面再賦值
output = loss(m(conv(data)), target)
參考:https://zhuanlan.zhihu.com/p/61379965
多分類損失函數
多分類任務用到最多的就是nn.NLLLOSS和nn.CrossEntropyLoss。這兩者的關係實際上是
nn.CrossEntropyLoss = nn.NLLLOSS + LogSoftmax
nn.NLLLoss
網絡的最後一層後有LogSoftmax,就用nn.NLLLoss。也就是我們要先對input用一下log_softmax函數,再作爲nn.NLLLoss的輸入。
如果不想讓網絡的最後一層是log_softmax層的話,就可以採用CrossEntropyLoss完全代替此函數。
NLLLoss就是的計算公式可以這樣表示
loss(input, class) = -input[class] 也就是把這個類對應的像素的值找出來,再取一個負號
對圖像來說,我們現在有C個通道的hxw圖像,然後有一個target,那麼對某一個像素來說,我們的target的值爲幾,則我們就選擇第幾個通道的這個像素位置值的負值。
nn.functional.null_loss
torch.nn.functional.nll_loss(input, target, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=‘mean’)
- input 預測值
一維:(N,C),二維:(N,C,H,W) ,k維:
C是要分類的類別的數量,N是batchsize
注意input在輸入NLLLoss()之前,需要對input進行log_softmax函數激活,即將input轉換成概率分佈的形式,並且取對數。 - target 真實值
一維:(N),二維:(N,H,W),k維:
其中每個值都是大於等於0小於等於C-1的,也就代表了屬於哪一類。
對於二維也就是圖像的多分類問題來說,就表示這個像素點屬於哪一類,這也就是語義分割問題 - weight (Tensor, optional)
給每一個類設置一個權重,必須爲大小爲C的tensor。常用於類別不均衡問題。 - size_average(bool)
當reduce=True時有效。爲True時,返回的loss爲除以權重之和的平均值;爲False時,返回的各樣本的loss之和。 - reduce(bool)
返回值是否爲標量,默認爲True。 - ignore_index(int)
忽略某一類別,不計算其loss,其loss會爲0,並且,在採用size_average時,不會計算那一類的loss,除的時候的分母也不會統計那一類的樣本。
特別注意,當帶上權值,reduce = True, size_average = True, 其計算公式爲:
當input爲[[0.6, 0.2, 0.2], [0.4, 1.2, 0.4]],target= [0, 1],
①不加權重
l1 = -0.6 , l2=-1.2 loss=l1+l2=-0.6-1.2=-1.8
②加權重
weight = [0.6, 0.2, 0.2]
l1 = - 0.60.6 = - 0.36
l2 = - 1.20.2 = - 0.24
loss = -0.36/(0.6+0.2) + -0.24/(0.6+0.2) = -0.75
例子:
>>> # input is of size N x C = 3 x 5
>>> input = torch.randn(3, 5, requires_grad=True)
>>> # each element in target has to have 0 <= value < C
>>> target = torch.tensor([1, 0, 4])
>>> output = F.nll_loss(F.log_softmax(input), target)
>>> output.backward()
nn.NLLLoss
torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=‘mean’)
參數和上面的一樣
例子:
>>> # 2D loss example (used, for example, with image inputs)
>>> N, C = 5, 4
>>> loss = nn.NLLLoss()
>>> # input is of size N x C x height x width
>>> data = torch.randn(N, 16, 10, 10)
>>> conv = nn.Conv2d(16, C, (3, 3))
>>> m = nn.LogSoftmax(dim=1)
>>> # each element in target has to have 0 <= value < C
>>> target = torch.empty(N, 8, 8, dtype=torch.long).random_(0, C)
>>> output = loss(m(conv(data)), target)
>>> output.backward()