pytorch常用損失函數


 損失函數的基本用法:

criterion = LossCriterion() #構造函數有自己的參數
loss = criterion(x, y) #調用標准時也有參數

得到的loss結果已經對mini-batch數量取了平均值

 

1.BCELoss(二分類)

CLASS torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')

創建一個衡量目標和輸出之間二進制交叉熵的criterion

 

unreduced loss函數(即reduction參數設置為'none')為:

N表示batch size,xn為輸出,yn為目標

 

如果reduction不為'none'(默認設為'mean'),則:

即默認情況下,loss會基於element求平均值,如果size_average=False的話,loss會被累加。

這是用來測量誤差error的重建,例如一個自動編碼器。注意 0<=target[i]<=1。

 

參數:

  • weight (Tensor,可選) – 每批元素損失的手工重標權重。如果給定,則必須是一個大小為“nbatch”的張量。
  • size_average (bool, 可選) – 棄用(見reduction參數)。默認情況下,設置為True,即對批處理中的每個損失元素進行平均。注意,對於某些損失,每個樣本有多個元素。如果字段size_average設置為False,則對每個小批的損失求和。當reduce為False時,該參數被忽略。默認值:True
  • reduce (bool,可選) – 棄用(reduction參數)。默認情況下,設置為True,即根據size_average參數的值決定對每個小批的觀察值是進行平均或求和。如果reduce為False,則返回每個批處理元素的損失,不進行平均和求和操作,即忽略size_average參數。默認值:True
  • reduction (string,可選) – 指定要應用於輸出的reduction操作:' none ' | 'mean' | ' sum '。“none”:表示不進行任何reduction,“mean”:輸出的和除以輸出中的元素數,即求平均值,“sum”:輸出求和。注意:size_average和reduce正在被棄用,與此同時,指定這兩個arg中的任何一個都將覆蓋reduction參數。默認值:“mean”

 形狀:

  • 輸入:(N,*), *代表任意數目附加維度
  • 目標:(N,*),與輸入擁有同樣的形狀
  • 輸出:標量scalar,即輸出一個值。如果reduce為False,即不進行任何處理,則(N,*),形狀與輸入相同。

 舉例:

 

m = nn.Sigmoid()
loss = nn.BCELoss() input = torch.randn(3,requires_grad=True) target = torch.empty(3).random_(2) output = loss(m(input), target) output.backward()

 

input,target,output

返回:

(tensor([-0.8728,  0.3632, -0.0547], requires_grad=True), tensor([1., 0., 0.]), tensor(0.9264, grad_fn=<BinaryCrossEntropyBackward>))

 

m(input)結果為:

tensor([0.2947, 0.5898, 0.4863])

計算output = (1 * ln 0.2947+(1-1)*ln(1-0.2947) + 0*ln0.5898 + (1-0)*ln(1-0.5898) + 0*ln0.4863 + (1-0)*ln(1-0.4863)) / 3 = 0.9264

 

input.grad

返回:

tensor([-0.2351,  0.1966, 0.1621])

 

當我們進行的是二分類時,即激活函數使用的是sigmoid函數時,常使用交叉熵作為損失函數。這樣就能夠解決因sigmoid函數導致的梯度消失問題

比如當我們使用的不是二進制交叉熵作為損失函數,而是使用的是平方差損失,即MSELoss作為損失函數,如:

那么假設進行的是二分類,損失函數為 ln= (xn - yn)2 / 2, n=1,2 , 激活函數為sigmoid函數,所以xn=σ(z),其中z = wx + b

那么當進行鏈式求導時,得:

  • 對w求導: ∂L / ∂w = (xn - yn) * σ'(z) * z= (xn - yn) * σ'(z) * x
  • 對b求導:  ∂L / ∂b = (xn - yn) * σ'(z)

從上面兩個公式可知梯度計算都與sigmoid函數的梯度相關,而因為sigmoid函數左右兩邊梯度趨於0,這就會導致反向傳播過程中計算得到的梯度會趨於0,即導致發生梯度消失的問題

而如果是以交叉熵作為損失函數,得到的梯度計算公式就會變為:

  • 對w求導: ∂L / ∂w = 1/n *  Σi xn * (σ(z)-yn)
  • 對b求導:  ∂L / ∂b =1/n *  Σi (σ(z)-yn)

可見不會與sigmoid的梯度相關,這樣就不會出現梯度消失的問題

 

2.BCEWithLogitsLoss

CLASS torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)

與BCELoss的不同:

將sigmoid函數和BCELoss方法結合到一個類中

這個版本在數值上比使用一個帶着BCELoss損失函數的簡單的Sigmoid函數更穩定,通過將操作合並到一層中,我們利用log-sum-exp技巧來實現數值穩定性。

損失函數(即reduction參數設置為'none')變為:

 

多出參數:

  • pos_weight (Tensor,可選) –正值例子的權重,必須是有着與分類數目相同的長度的向量

 

該參數用處:

可以通過增加正值示例的權重來權衡召回率和准確性。在多標簽分類的情況下,損失可以描述為: 

c表示類的數量(c>1表明是多標簽二進制分類,c=1表明是單標簽二進制分類),n為一批中的例子數量,pc為類別c的正值的權重,解決正負例樣本不均衡的情況

pc>1增加召回率,pc<1增加准確性

舉例:例如,如果一個數據集包含一個類的100個正示例和300個負示例,那么該類的pos_weigh設為300/100=3。該損失函數將表現得像數據集包含了300個正示例

 

如果不考慮參數pos_weigh,其實BCEWithLogitsLoss就相當於比BCELoss多進行了一個sigmoid操作,所以上面的例子:

m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn(3,requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(m(input), target)

等價於:

loss = nn.BCEWithLogitsLoss()
input = torch.randn(3,requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(input, target)

 

4.NLLLoss(多分類)

CLASS torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

用於多分類的負對數似然損失函數(negative log likelihood loss)

損失函數(即reduction參數設置為'none')為:

如果提供了,可選的參數weight權重應該是一個一維張量,為每個類分配權重。當你有一個不平衡的訓練集時,這是特別有用的。

通過轉發調用給出的輸入 (即nn.LogSoftmax()后的輸出) 應該包含每個類的log-probability。輸入要么是大小為(minibatch,C)或大小(minibatch,C,d1,d2,...,dK)的Tensor,k>=1表示k維的輸入

通過在網絡的最后一層添加LogSoftmax層,可以很容易地獲得神經網絡中的log-probability。如果不喜歡添加額外的層,可以使用CrossEntropyLoss損失函數來替代。

損失預期的目標應該是[0,c - 1]范圍內的類索引,其中C =類的數量;如果指定ignore_index參數,該損失函數也接受這個類索引(這個索引不一定在類范圍內)。

 

如果reduction不為'none'(默認設為'mean'),則: 

 

該損失函數也能被使用在高維輸入中,通過提供大小為(minibatch,C,d1,d2,...,dK)的輸入,k>=1表示k維的輸入,和一個與該大小相同的合適的目標值

在圖片的例子中,該函數計算每一個像素的NLL loss

 

多出參數:

  • ignore_index (int, optional) – 指定一個被忽略的目標值,該目標值不影響輸入梯度。當size_average為真時,對非忽略目標的損失進行平均。

 

 形狀:

  • 輸入:(N,C), C代表類別的數量;或者在計算高維損失函數例子中輸入大小為(N,C,d1,d2,...,dK),k>=1
  • 目標:(N),與輸入擁有同樣的形狀,每一個值大小為為 0≤targets[i]≤C−1 ;或者在計算高維損失函數例子中輸入大小為(N,C,d1,d2,...,dK),k>=1
  • 輸出:標量scalar。如果reduction='none',則其大小與目標相同,為(N)或(N,C,d1,d2,...,dK),k>=1

 低維舉例:

m = nn.LogSoftmax(dim=1)
loss = nn.NLLLoss()
# input is of size N x C = 3 x 5
input = torch.randn(3,5,requires_grad=True)
input

返回:

tensor([[-0.8676,  1.5017,  0.2963, -0.9431, -0.0929],
        [ 0.3540,  1.0994, -1.1085, -0.4001,  0.0102],
        [ 1.3653, -0.3828,  0.6257, -2.4996,  0.1928]], requires_grad=True)

 

nn.LogSoftmax(dim=1)即先進行Softmax計算(得0-1的值),再取Log,得到的都是負數:

m(input)

返回:

tensor([[-2.8899, -0.5205, -1.7259, -2.9653, -2.1152],
        [-1.5082, -0.7628, -2.9707, -2.2623, -1.8520],
        [-0.6841, -2.4323, -1.4237, -4.5490, -1.8566]],
       grad_fn=<LogSoftmaxBackward>)

 

#each element in target has to have 0 <= value < C
target = torch.tensor([1,0,4])
output = loss(m(input), target)
output

返回:

tensor(1.2951, grad_fn=<NllLossBackward>)

 

高維例子:

# 2D loss example (used, for example, with image inputs)
N, C = 5,4
loss = nn.NLLLoss()
# input is of size N x channel x height x width
data = torch.randn(N, 16, 10, 10)
conv = nn.Conv2d(16, C, (3, 3))#輸出為5*8*8
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) #target.size()=target = torch.empty(N, 8, 8, dtype=torch.long).random_(0, C)
output = loss(m(conv(data)), target)
output

返回:

tensor(1.5501, grad_fn=<NllLoss2DBackward>)

 

5.CrossEntropyLoss(多分類)

該criterion將nn.LogSoftmax()和nn.NLLLoss()方法結合到一個類中

當用C類訓練分類問題時,它是有用的。如果提供了,可選的參數weight權重應該是一個一維張量,為每個類分配權重。當你有一個不平衡的訓練集時,這是特別有用的。

每個類的輸入應該包含原始的、未標准化的分數。

輸入應該是大小為(minibatch,C)或大小(minibatch,C,d1,d2,...,dK)的Tensor,k>=1表示k維的輸入

該criterion期望在[0,c - 1]范圍內的一個類指標作為小batch大小的一維張量的每個值的目標值;如果指定ignore_index,該criterion也接受這個類索引值(這個索引不一定在類范圍內)。

損失函數為:

如果帶了weight參數為:

每一個小batch的觀測值都返回平均后的損失。

 該損失函數也能被使用在高維輸入中,通過提供大小為(minibatch,C,d1,d2,...,dK)的輸入,k>=1表示k維的輸入,和一個與該大小相同的合適的目標值

 

所以上面NLLLoss的例子:

m = nn.LogSoftmax(dim=1)
loss = nn.NLLLoss()
# 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 = target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(m(input), target)

等價於這里的:

loss = nn.CrossEntropyLoss()
# 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 = target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)

 

6.L1Loss(L1 norm)

CLASS torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')

創建一個criterion計算input x和target y的每個元素的平均絕對誤差(mean absolute error (MAE))

 unreduced loss函數(即reduction參數設置為'none')為:

N表示batch size

 

如果reduction不為'none'(默認設為'mean'),則:

 

x和y是有着n個向量的任意形狀的張量

mean先對所有元素進行sum操作,然后除以n

如果設置reduction = 'sum',除以n的操作可以省略,即只對所有元素進行sum操作

 形狀:

  • 輸入:(N,*), *代表任意數目附加維度
  • 目標:(N,*),與輸入擁有同樣的形狀
  • 輸出:標量scalar,即輸出一個值。如果reduction='none',即不進行任何處理,則為(N,*),形狀與輸入相同。

 舉例:

loss = nn.L1Loss()
input = torch.randn(1, 2, requires_grad=True)#tensor([[-0.0625, -2.1603]], requires_grad=True)
target = torch.randn(1, 2)#tensor([[0.6789, 0.9831]])
output = loss(input, target)#tensor(1.9424, grad_fn=<L1LossBackward>)

output= (|-0.0625-0.6789| + |-2.1603-0.9831|) / 2 = 1.9424

 

7.MSELoss(L2 norm)

創建一個criterion計算input x和target y的每個元素的均方誤差(mean absolute error (MAE))

unreduced loss函數(即reduction參數設置為'none')為:

 

N表示batch size

 

如果reduction不為'none'(默認設為'mean'),則:

 

x和y是有着n個向量的任意形狀的張量

mean先對所有元素進行sum操作,然后除以n

如果設置reduction = 'sum',除以n的操作可以省略,即只對所有元素進行sum操作

 

 形狀:

  • 輸入:(N,*), *代表任意數目附加維度
  • 目標:(N,*),與輸入擁有同樣的形狀

舉例:

loss = nn.MSELoss()
input = torch.randn(1, 2, requires_grad=True)#tensor([[-1.4445, -2.4888]], requires_grad=True)
target = torch.randn(1, 2)#tensor([[ 0.7117, -0.1200]])
output = loss(input, target)#tensor(5.1303, grad_fn=<MseLossBackward>)

output =( (-1.4445-0.7117)2 + ( -2.4888 + 0.1200 )2 ) / 2 = 5.1303

 

 

8.SmoothL1Loss

CLASS torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean')

創建一個criterion,如果絕對元素誤差低於1,則使用平方項,否則使用L1項。與MSELoss相比,它對異常值的敏感度較低; 在某些情況下,它可以防止梯度的爆炸式增長(例如,參見Ross Girshick的Fast R-CNN論文)。

也被稱為Huber損失:

 

x和y是有着n個向量的任意形狀的張量

mean先對所有元素進行sum操作,然后除以n

如果設置reduction = 'sum',除以n的操作可以省略,即只對所有元素進行sum操作

 

 形狀:

  • 輸入:(N,*), *代表任意數目附加維度
  • 目標:(N,*),與輸入擁有同樣的形狀
  • 輸出:標量scalar,即輸出一個值。如果reduction='none',即不進行任何處理,則為(N,*),形狀與輸入相同。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM