加入極市專業CV交流群,與6000+來自騰訊,華為,百度,北大,清華,中科院等名企名校視覺開發者互動交流!更有機會與李開復老師等大牛群內互動!
同時提供每月大咖直播分享、真實項目需求對接、乾貨資訊匯總,行業技術交流。點擊文末「閱讀原文」立刻申請入群~
作者 | 餘霆嵩
來源專欄 | PyTorch學習筆記
https://blog.csdn.net/u011995719/article/details/85107524
本文截取自一個github上千星的火爆教程——《PyTorch 模型訓練實用教程》,教程內容主要為在 PyTorch 中訓練一個模型所可能涉及到的方法及函數的詳解等,本文為作者整理的學習筆記(六),後續會繼續更新這個系列,歡迎關注。
項目代碼:https://github.com/tensor-yu/PyTorch_Tutorial
系列回顧:
我們所說的優化,即優化網絡權值使得損失函數值變小。但是,損失函數值變小是否能代表模型的分類/回歸精度變高呢?那麼多種損失函數,應該如何選擇呢?請來了解PyTorch中給出的十七種損失函數吧。
1.L1loss
2.MSELoss
3.CrossEntropyLoss
4.NLLLoss
5.PoissonNLLLoss
6.KLDivLoss
7.BCELoss
8.BCEWithLogitsLoss
9.MarginRankingLoss
10.HingeEmbeddingLoss
11.MultiLabelMarginLoss
12.SmoothL1Loss
13.SoftMarginLoss
14.MultiLabelSoftMarginLoss
15.CosineEmbeddingLoss
16.MultiMarginLoss
17.TripletMarginLoss
請運行配套代碼,代碼中有詳細解釋,有手動計算,這些都有助於理解損失函數原理。 本小節配套代碼: /Code/3_optimizer/3_1_lossFunction
class torch.nn.L1Loss(size_average=None, reduce=None) 官方文檔中仍有reduction='elementwise_mean'參數,但代碼實現中已經刪除該參數
功能: 計算output和target之差的絕對值,可選返回同維度的tensor或者是一個標量。
計算公式:
參數: reduce(bool)- 返回值是否為標量,默認為True
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
實例: /Code/3_optimizer/3_1_lossFunction/1_L1Loss.py
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='elementwise_mean')
官方文檔中仍有reduction='elementwise_mean'參數,但代碼實現中已經刪除該參數
功能: 計算output和target之差的平方,可選返回同維度的tensor或者是一個標量。
計算公式:
參數: reduce(bool)- 返回值是否為標量,默認為True
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
實例: /Code/3_optimizer/3_1_lossFunction/2_MSELoss.py
class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
功能: 將輸入經過softmax激活函數之後,再計算其與target的交叉熵損失。即該方法將nn.LogSoftmax()和 nn.NLLLoss()進行了結合。嚴格意義上的交叉熵損失函數應該是nn.NLLLoss()。
補充:小談交叉熵損失函數 交叉熵損失(cross-entropy Loss) 又稱為對數似然損失(Log-likelihood Loss)、對數損失;二分類時還可稱之為邏輯斯諦回歸損失(Logistic Loss)。交叉熵損失函數表達式為 L = - sigama(y_i * log(x_i))。pytroch這裡不是嚴格意義上的交叉熵損失函數,而是先將input經過softmax激活函數,將向量「歸一化」成概率形式,然後再與target計算嚴格意義上交叉熵損失。 在多分類任務中,經常採用softmax激活函數+交叉熵損失函數,因為交叉熵描述了兩個概率分布的差異,然而神經網絡輸出的是向量,並不是概率分布的形式。所以需要softmax激活函數將一個向量進行「歸一化」成概率分布的形式,再採用交叉熵損失函數計算loss。 再回顧PyTorch的CrossEntropyLoss(),官方文檔中提到時將nn.LogSoftmax()和 nn.NLLLoss()進行了結合,nn.LogSoftmax() 相當於激活函數 , nn.NLLLoss()是損失函數,將其結合,完整的是否可以叫做softmax+交叉熵損失函數呢?
計算公式:
參數: weight(Tensor)- 為每個類別的loss設置權值,常用於類別不均衡問題。weight必須是float類型的tensor,其長度要於類別C一致,即每一個類別都要設置有weight。帶weight的計算公式:
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。 reduce(bool)- 返回值是否為標量,默認為True ignore_index(int)- 忽略某一類別,不計算其loss,其loss會為0,並且,在採用size_average時,不會計算那一類的loss,除的時候的分母也不會統計那一類的樣本。
實例: /Code/3_optimizer/3_1_lossFunction/3_CroosEntropyLoss.py
補充: output不僅可以是向量,還可以是圖片,即對圖像進行像素點的分類,這個例子可以從NLLLoss()中看到,這在圖像分割當中很有用。
class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
功能: 不好用言語描述其功能!請看計算公式:loss(input, class) = -input[class]。舉個例,三分類任務,input=[-1.233, 2.657, 0.534], 真實標籤為2(class=2),則loss為-0.534。就是對應類別上的輸出,取一個負號!感覺被NLLLoss的名字欺騙了。 實際應用: 常用於多分類任務,但是input在輸入NLLLoss()之前,需要對input進行log_softmax函數激活,即將input轉換成概率分布的形式,並且取對數。其實這些步驟在CrossEntropyLoss中就有,如果不想讓網絡的最後一層是log_softmax層的話,就可以採用CrossEntropyLoss完全代替此函數。
參數: weight(Tensor)- 為每個類別的loss設置權值,常用於類別不均衡問題。weight必須是float類型的tensor,其長度要於類別C一致,即每一個類別都要設置有weight。 size_average(bool)- 當reduce=True時有效。為True時,返回的loss為除以權重之和的平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。
ignore_index(int)- 忽略某一類別,不計算其loss,其loss會為0,並且,在採用size_average時,不會計算那一類的loss,除的時候的分母也不會統計那一類的樣本。
實例: /Code/3_optimizer/3_1_lossFunction/4_NLLLoss.py
特別注意: 當帶上權值,reduce = True, size_average = True, 其計算公式為:
例如當input為[[0.6, 0.2, 0.2], [0.4, 1.2, 0.4]],target= [0, 1], 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
5.PoissonNLLLossclass torch.nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e-08, reduce=None, reduction='elementwise_mean')
功能: 用於target服從泊松分布的分類任務。
計算公式:
參數:
log_input(bool)- 為True時,計算公式為:loss(input,target)=exp(input) - target * input; 為False時,loss(input,target)=input - target * log(input+eps)
full(bool)- 是否計算全部的loss。
例如,當採用斯特林公式近似階乘項時,此為 target*log(target) - target+0.5∗log(2πtarget) eps(float)- 當log_input = False時,用來防止計算log(0),而增加的一個修正項。即 loss(input,target)=input - target * log(input+eps)
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True
實例: /Code/3_optimizer/3_1_lossFunction/5_PoissonNLLLoss.py
class torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能: 計算input和target之間的KL散度( Kullback–Leibler divergence) 。
計算公式:
(後面有代碼手動計算,證明計算公式確實是這個,但是為什麼沒有對x_n計算對數呢?)
補充:KL散度 KL散度( Kullback–Leibler divergence) 又稱為相對熵(Relative Entropy),用於描述兩個概率分布之間的差異。計算公式(離散時):
其中p表示真實分布,q表示p的擬合分布, D(P||Q)表示當用概率分布q來擬合真實分布p時,產生的信息損耗。這裡的信息損耗,可以理解為損失,損失越低,擬合分布q越接近真實分布p。同時也可以從另外一個角度上觀察這個公式,即計算的是 p 與 q 之間的對數差在 p 上的期望值。 特別注意,D(p||q) ≠ D(q||p), 其不具有對稱性,因此不能稱為K-L距離。
信息熵 = 交叉熵 - 相對熵 從資訊理論角度觀察三者,其關係為信息熵 = 交叉熵 - 相對熵。在機器學習中,當訓練數據固定,最小化相對熵 D(p||q) 等價於最小化交叉熵 H(p,q) 。
參數:
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值,平均值為element-wise的,而不是針對樣本的平均;為False時,返回是各樣本各維度的loss之和。 reduce(bool)- 返回值是否為標量,默認為True。
使用注意事項: 要想獲得真正的KL散度,需要如下操作:
1. reduce = True ;size_average=False
2. 計算得到的loss 要對batch進行求平均
實例: /Code/3_optimizer/3_1_lossFunction/6_KLDivLoss.py
7.BCELossclass torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 二分類任務時的交叉熵計算函數。此函數可以認為是nn.CrossEntropyLoss函數的特例。其分類限定為二分類,y必須是{0,1}。還需要注意的是,input應該為概率分布的形式,這樣才符合交叉熵的應用。所以在BCELoss之前,input一般為sigmoid激活層的輸出,官方例子也是這樣給的。該損失函數在自編碼器中常用。 計算公式:
參數:
weight(Tensor)- 為每個類別的loss設置權值,常用於類別不均衡問題。
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True
8.BCEWithLogitsLossclass torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean', pos_weight=None)
功能: 將Sigmoid與BCELoss結合,類似於CrossEntropyLoss(將nn.LogSoftmax()和 nn.NLLLoss()進行結合)。即input會經過Sigmoid激活函數,將input變成概率分布的形式。 計算公式:
σ() 表示Sigmoid函數 特別地,當設置weight時:
參數:
weight(Tensor)- : 為batch中單個樣本設置權值,If given, has to be a Tensor of size 「nbatch」.
pos_weight-: 正樣本的權重, 當p>1,提高召回率,當P<1,提高精確度。可達到權衡召回率(Recall)和精確度(Precision)的作用。 Must be a vector with length equal to the number of classes.
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True
9.MarginRankingLossclass torch.nn.MarginRankingLoss(margin=0, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 計算兩個向量之間的相似度,當兩個向量之間的距離大於margin,則loss為正,小於margin,loss為0。
計算公式:
y == 1時,x1要比x2大,才不會有loss,反之,y == -1 時,x1要比x2小,才不會有loss。
參數: margin(float)- x1和x2之間的差異。
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。
10.HingeEmbeddingLossclass torch.nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 未知。為折頁損失的拓展,主要用于衡量兩個輸入是否相似。 used for learning nonlinear embeddings or semi-supervised 。 計算公式:
參數:
margin(float)- 默認值為1,容忍的差距。
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。
11.MultiLabelMarginLossclass torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能: 用於一個樣本屬於多個類別時的分類任務。例如一個四分類任務,樣本x屬於第0類,第1類,不屬於第2類,第3類。 計算公式:
x[y[j]] 表示 樣本x所屬類的輸出值,x[i]表示不等於該類的輸出值。
參數:
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。 Input: (C) or (N,C) where N is the batch size and C is the number of classes. Target: (C) or (N,C), same shape as the input.
12.SmoothL1Lossclass torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='elementwise_mean')
功能: 計算平滑L1損失,屬於 Huber Loss中的一種(因為參數δ固定為1了)。
補充: Huber Loss常用於回歸問題,其最大的特點是對離群點(outliers)、噪聲不敏感,具有較強的魯棒性。 公式為:
理解為,當誤差絕對值小於δ,採用L2損失;若大於δ,採用L1損失。 回到SmoothL1Loss,這是δ=1時的Huber Loss。 計算公式為:
對應下圖紅色線:
參數: size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。 reduce(bool)- 返回值是否為標量,默認為True。
13.SoftMarginLossclass torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能: Creates a criterion that optimizes a two-class classification logistic loss between input tensor xand target tensor y (containing 1 or -1). (暫時看不懂怎麼用,有了解的朋友歡迎補充!)
計算公式:
參數: size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。 reduce(bool)- 返回值是否為標量,默認為True。
14.MultiLabelSoftMarginLossclass torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能: SoftMarginLoss多標籤版本,a multi-label one-versus-all loss based on max-entropy,
計算公式:
參數: weight(Tensor)- 為每個類別的loss設置權值。weight必須是float類型的tensor,其長度要於類別C一致,即每一個類別都要設置有weight。
15.CosineEmbeddingLossclass torch.nn.CosineEmbeddingLoss(margin=0, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 用Cosine函數來衡量兩個輸入是否相似。 used for learning nonlinear embeddings or semi-supervised 。
計算公式:
參數:
margin(float)- : 取值範圍[-1,1], 推薦設置範圍 [0, 0.5]
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。
16.MultiMarginLossclass torch.nn.MultiMarginLoss(p=1, margin=1, weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 計算多分類的折頁損失。
計算公式:
其中,0≤y≤x.size(1) ; i == 0 to x.size(0) and i≠y; p==1 or p ==2; w[y]為各類別的weight。
參數:
p(int)- 默認值為1,僅可選1或者2。
margin(float)- 默認值為1
weight(Tensor)- 為每個類別的loss設置權值。weight必須是float類型的tensor,其長度要於類別C一致,即每一個類別都要設置有weight。
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。
reduce(bool)- 返回值是否為標量,默認為True。
17.TripletMarginLossclass torch.nn.TripletMarginLoss(margin=1.0, p=2, eps=1e-06, swap=False, size_average=None, reduce=None, reduction='elementwise_mean')
功能: 計算三元組損失,人臉驗證中常用。 如下圖Anchor、Negative、Positive,目標是讓Positive元和Anchor元之間的距離儘可能的小,Positive元和Negative元之間的距離儘可能的大。
從公式上看,Anchor元和Positive元之間的距離加上一個threshold之後,要小於Anchor元與Negative元之間的距離。
計算公式:
參數:
margin(float)- 默認值為1
p(int)- The norm degree ,默認值為2
swap(float)– The distance swap is described in detail in the paper Learning shallow convolutional feature descriptors with triplet losses by V. Balntas, E. Riba et al. Default: False
size_average(bool)- 當reduce=True時有效。為True時,返回的loss為平均值;為False時,返回的各樣本的loss之和。 reduce(bool)- 返回值是否為標量,默認為True。
*延伸閱讀
點擊左下角「閱讀原文」,即可申請加入極市目標跟蹤、目標檢測、工業檢測、人臉方向、視覺競賽等技術交流群,更有每月大咖直播分享、真實項目需求對接、乾貨資訊匯總,行業技術交流,一起來讓思想之光照的更遠吧~
覺得有用麻煩給個在看啦~