1. 程式人生 > >Pytorch loss function函式總結

Pytorch loss function函式總結

注意: 很多的loss 函式都有size_averagereduce倆個布林型別的引數。因為一般損失函式都是直接計算batch的資料,因此返回的loss結果都是維度(batch_size, )的向量。

  1. 如果 reduce = False,那麼 size_average 引數失效,直接返回向量形式的 loss;

  2. 如果 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

l o s s ( x i ,

y i ) = x i
y i loss(x_{i},y_{i})=|x_{i}-y_{i}|
xy可以是向量,可以是矩陣,但是其維度需要一致,同時loss的維度和xy是一致的,其中下標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損失。
l o s s ( x i , y i ) = { 0.5 ( x i y i ) 2 ,   x i y j < 1 x i y i 0.5 ,   o t h e r w i s e loss(x_{i},y_{i})=\left\{\begin{matrix} 0.5*(x_{i}-y_{i})^{2}, \ |x_{i}-y_{j}|<1\\ |x_{i}-y_{i}|-0.5, \ otherwise \end{matrix}\right.
此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函式:
l o s s ( x i , y i ) = ( x i y i ) 2 loss(x_{i},y_{i})=(x_{i}-y_{i})^{2}

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函式。
因為離散版的交叉熵定義是 H ( p , q ) = i p i l o g q i H(p,q)=- \sum_{i}p_{i}logq_{i} , 其中p,q都是向量,且都是概率分佈。如果是二分類的話,因為只有正例和反例,且倆者概率和為1,那麼只需要預測一個概率就好了,因此可以簡化成:
l o s s ( x i , y i ) = w i [ y i l o g x i + ( 1 y i ) l o g ( 1 x i ) ] loss(x_{i},y_{i})=-w_{i}[y_{i}logx_{i}+(1-y_{i})log(1-x_{i})]
其中這裡的x, y 可以是向量也可以是矩陣,i代表下標, x i x_{i} 表示第 i 個樣本預測為 正例 的概率, y i y_{i} 表示第 i 個樣本的標籤, w i - w_{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, 那麼代入交叉熵公式中化簡後就成了下面的簡化形式。
l o s s ( x , l a b e l ) = w l a b l e l o g e x l a b l e i N e x i = w l a b l e [ x l a b e l + l o g i N e x i ] loss(x,label)=-w_{lable}*log\frac{e^{x_{lable}}}{\sum_{i}^{N} e^{x_{i}}}=-w_{lable}*[-x_{label} + log \sum_{i}^{N} e^{x_{i}}]
這裡的 x R N x∈ℝ^{N} ,是沒有經過 Softmax 的啟用值,N 是 x 的維度大小(或者叫特徵維度); l a b e l [ 0 , C 1 ] label∈[0,C−1] 是標量,是對應的標籤,可以看到兩者維度是不一樣的。C 是要分類的個數。 w R C w∈ℝ^{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的輸入應該一致。
l o s s ( x , y ) = 1 / N i N [ y i ( l o g y i x i ) ] loss(x,y)=1/N * \sum_{i}^{N}[y_{i}*(logy_{i}-x_{i})]