Pytorch loss function函式總結
注意: 很多的loss 函式都有size_average
和reduce
倆個布林型別的引數。因為一般損失函式都是直接計算batch的資料,因此返回的loss結果都是維度(batch_size, )的向量。
-
如果 reduce = False,那麼 size_average 引數失效,直接返回向量形式的 loss;
-
如果 reduce = True,那麼 loss 返回的是標量
2.1 如果 size_average = True,返回 loss.mean();
2.2 如果 size_average = True,返回 loss.sum();
注意,預設情況下,reduce=True, size_average=True
在下面情況下,一般都把這倆個引數設定為False, 這樣比較好理解原始的損失函式定義
toch.nn.L1Loss
x和y可以是向量,可以是矩陣,但是其維度需要一致,同時loss的維度和x、y是一致的,其中下標i
表示第幾個元素。
loss_fn = torch.nn.L1Loss(reduce=False, size_average=False)
input = torch.autograd.Variable(torch.randn(3,4))
target = torch.autograd.Variable(torch.randn(3,4))
loss = loss_fn(input, target)
print(input); print(target); print(loss)
print(input.size(), target.size(), loss.size())
toch.nn.SmoothL1Loss
也叫作Huber Loss,誤差在(-1,1)上是平方損失,其他情況是L1損失。
此loss對於異常點的敏感性不如MSELoss
, 但是在某些情況下防止了梯度爆炸(參考 Fast R-CNN)。跟L1loss
類似,都是element-wise
的操作,下標i
代表第i
個元素。
loss_fn = torch.nn.SmoothL1Loss(reduce=False, size_average=False)
input = torch.autograd.Variable(torch.randn(3,4))
target = torch.autograd.Variable(torch.randn(3,4))
loss = loss_fn(input, target)
print(input); print(target); print(loss)
print(input.size(), target.size(), loss.size())
toch.nn.MSELoss
均方損失函式,類似於nn.L1Loss
函式:
loss_fn = torch.nn.MSELoss(reduce=False, size_average=False)
input = torch.autograd.Variable(torch.randn(3,4))
target = torch.autograd.Variable(torch.randn(3,4))
loss = loss_fn(input, target)
print(input); print(target); print(loss)
print(input.size(), target.size(), loss.size())
toch.nn.BCELoss
二分類用的交叉熵,用的時候需要在該層前面加上Sigmoid
函式。
因為離散版的交叉熵定義是
, 其中p,q都是向量,且都是概率分佈。如果是二分類的話,因為只有正例和反例,且倆者概率和為1,那麼只需要預測一個概率就好了,因此可以簡化成:
其中這裡的x, y 可以是向量也可以是矩陣,i
代表下標,
表示第 i
個樣本預測為 正例 的概率,
表示第 i
個樣本的標籤,
表示該項的權重大小,loss, x, y, w 的維度都是一樣的。
import torch.nn.functional as F
from torch.autograd import Variable
loss_fn = torch.nn.BCELoss(reduce=False, size_average=False)
input = Variable(torch.randn(3, 4))
target = Variable(torch.FloatTensor(3, 4).random_(2))
loss = loss_fn(F.sigmoid(input), target)
print(input); print(target); print(loss)
其中權重的維度和x,y一樣,有時候遇到正負樣本不均衡的時候,可能要多寫一句話
class_weight = Variable(torch.FloatTensor([1, 10])) # 這裡正例比較少,因此權重要大一些
target = Variable(torch.FloatTensor(3, 4).random_(2))
weight = class_weight[target.long()] # (3, 4)
loss_fn = torch.nn.BCELoss(weight=weight, reduce=False, size_average=False)
toch.nn.CrossEntropyLoss
多分類用的交叉熵損失函式,用這個loss前面不需要加softmax層。值得注意的是,該函式限制了target的型別為torch.LongTensor,而且不是多標籤就意味著是one-hot的形式,即只有一個位置是1,其他位置都是0, 那麼代入交叉熵公式中化簡後就成了下面的簡化形式。
這裡的
,是沒有經過 Softmax 的啟用值,N 是 x 的維度大小(或者叫特徵維度);
是標量,是對應的標籤,可以看到兩者維度是不一樣的。C 是要分類的個數。
是維度為 C 的向量,表示標籤的權重,樣本少的類別,可以考慮把權重設定大一點。
import torch
from torch.autograd import Variable
weight = torch.Tensor([1,2,1,1,10])
loss_fn = torch.nn.CrossEntropyLoss(reduce=False, size_average=False, weight=weight)
input = Variable(torch.randn(3, 5)) # (batch_size, C)
target = Variable(torch.LongTensor(3).random_(5)) #這裡應該為LongTensor
loss = loss_fn(input, target)
print(input); print(target); print(loss)
toch.nn.KLDivLoss
計算KL散度數,KL散度常用來描述倆個分佈的距離,並在輸出分佈的空間上執行直接回歸。
KL散度,又叫做相對熵,算的是倆個分佈之間的距離,越相似則越接近零。給定的輸入應該是log-probabilities, target和input的輸入應該一致。