PyTorch學習筆記(21) ——損失函數

0. 前言

本博客內容翻譯自紐約大學數據科學中心在2020發佈的《Deep Learning》課程的Activation Functions and Loss Functions
部分.

廢話不多說,下面直接開始吧 ^ . ^

1. 損失函數

本文是PyTorch學習筆記(20)——激活函數的姊妹篇。

PyTorch實現了許多損失函數,這些我們將介紹其中的一些。

  • nn.MSELoss()

MSELoss也叫做L2 loss, 這個函數的作用是: 對輸入x和目標y進行element-wise的計算均方誤差(mean squared error).

(xnyn)2 (x_n - y_n) ^2

在PyTorch中,MSELoss有2種方式: 一種是reduce,另一種是unreduce。

其中,unreduce的含義是將mini-batch中的每個樣本的loss分別保存,即以一個 向量(Vector) 的方式保存;而reduce是指將mini-batch的每個樣本的loss按照一定的方式進行平均,最後只保存一個標量(Scalar)

① reduction=‘None’ (對batch中的每個樣本保存其自己的loss)
在這裏插入圖片描述
② reduction=‘mean’ or ‘sum’ (求平均或者求和)
在這裏插入圖片描述

如果我們在計算機視覺任務中使用reduce的MSE (L2 Loss), 這通常意味着我們最後得到的結果會有或多或少的模糊:因爲你對每一項的loss都進行求和或者求平均了,那麼loss將很難反映出圖像/視頻中的每個部分對結果的影響。

而我們如果在計算機視覺任務中使用L1 Loss,通常會得到更銳利的結果。

  • nn.L1Loss()
    This measures the mean absolute error (MAE) betwen each element in the input xx and target yy (or the actual output and desired output).
    L1Loss衡量的是輸入x和目標y(或者實際輸出和理想輸出)的平均絕對值誤差(mean absolute error, MAE)。

xnyn |x_n - y_n|

同MSELoss類似,L1Loss也有unreduce和reduce2種,其方式與MSELoss無差別。

在實際使用中,L1 loss相比L2 loss對離羣點(outliers)和噪聲(noise)有着更強的魯棒性(L1 loss is more robust against outliers and noise compared to L2 loss)。這是因爲L2 loss對離羣點和噪聲計算平方,所以使得損失函數對於這些離羣點和噪聲更加的敏感。

但是,L1 loss的問題是其在一些地方不可微分,這使得一些部分的導數爲0,所以爲了避免L1 loss的hard margin問題,Smoot和L1Loss被提出,用於緩解梯度問題。

  • nn.SmoothL1Loss()

這個函數根據目標輸出和給定輸出的相差情況(<1, >=1)來分別使用不同的損失函數計算公式:

zi={0.5(xiyi)2,ifxiyi<1xiyi0.5,otherwisez_i = \begin{cases} 0.5(x_i - y_i)^2, if |x_i - y_i| <1\\ |x_i - y_i| -0.5, otherwise\\ \end{cases}
在這裏插入圖片描述
該損失函數在FAIR的大神Ross Girshick的目標檢測經典網絡: Fast R-CNN中大放異彩,這種光滑的L1 Loss也被稱作Huber Loss。

相對MSELoss(L2 Loss), Smooth L1 Loss對於離羣點和噪聲沒有那麼敏感。這個損失函數經常用於一些計算機視覺中一些需要避免/有效防止離羣點的應用。

當然,Smooth L1 Loss也有一些問題:它對損失函數進行了縮放, 縮放係數爲0.5.

  • nn.NLLLoss()

NLLLoss被用於訓練N分類任務,其含義是負對數似然損失函數(negative log likelihood loss)。

wynxn,yn-w_{y_n}*x_{n, y_n}
需要注意的是,在數學上,NLLLoss的輸入應該是log似然估計,但是PyTorch並沒有強制用戶這樣做。

同樣的,NLLLoss也分爲reduce和unreduce,其形似分別如下:

① unreduce
在這裏插入圖片描述
② reduce
在這裏插入圖片描述
注意,wn,ynw_{n, y_{n}}表示第n個樣本對應於yny_n類的權值,這是1個標量。

NLLLoss有一個optional的參數weight, 這個參數是1個1D Tensor,其長度與類別數一致。傳入weight的方式對處理不平衡的訓練集有很大的好處。

  • nn.CrossEntropyLoss()

CrossEntropyLoss是將nn.LogSoftmaxnn.NLLLoss合二爲一的損失函數。這種結合使得正確類的得分變得儘可能的高。

將二者合併爲一個新的損失函數的原因是爲了梯度計算的數值穩定性(numerical stability of gradient computation). 因爲當數據過softmax後,其靠近0或者1的值的梯度就幾乎不存在了。而Softmax後靠近0的值,在LogSoftmax裏接近負無窮;Softmax後靠近1的值,在LogSoftmax裏接近0. 這會造成數值問題。

但是當這兩個函數結合在一起時,我們可以得到飽和的梯度,所以我們在最後能夠得到一個合理的梯度。

每個類的輸入應該是unnormalized。

損失函數可以定義爲:
在這裏插入圖片描述
如果指定了weight參數,其形式爲:
在這裏插入圖片描述
注意,這裏不再分reduce和unreduce了,損失函數的計算是reduce的(reduction==‘mean’).

交叉熵的物理含義與KL散度(Kullback-Leibler Divergence)有關, KL散度常常被用於衡量2個分佈的相似性。

這裏,我們有目標分佈(one-hot) qq和神經網絡預測分佈pp, 那麼數學上, H(p,q)=ip(xi)log(q(xi))H(p, q) = -\sum_{i} p(x_i)log(q(x_i)) 其解析表達式爲:
H(p,q)=H(p)+DKL(pq)H(p, q) = H(p) + D_{KL}(p || q)

這裏,H(p,q)H(p, q)就是2個分佈的交叉熵,H(p)=ip(xi)log(p(xi))H(p)= -\sum_{i} p(x_i)log(p(x_i))是熵(Entropy),而DKL(pq)=ip(xi)logp(xi)q(xi)D_{KL}(p || q) = \sum_{i} p(x_i) log \frac{p(x_i)}{q(x_i)}就是KL散度。

  • nn.AdaptiveLogSoftmaxWithLoss()

這個是對有非常多的類(比如上百萬個類)的Softmax的高效實現。它被用於提升計算的效率。詳細的細節請參考FAIR的Edouard Grave, Armand Joulin等人於2016年寫的論文Efficient softmax approximation for GPUs

  • Binary Cross Entropy (BCE) Lossnn.BCELoss()

二分類的交叉熵,是交叉熵的特殊情況。BCE經常被用於衡量重建誤差: 比如auto-encoder。需要注意的是,因爲這裏我們認爲xxyy都是概率,所以BCE用到數據需要規則化到[0, 1]之間。
在這裏插入圖片描述

  • Kullback-Leibler Divergence Loss nn.KLDivLoss()

KLDivLoss對one-hot label的情況比較常用。它與BCELoss一樣,也把xxyy視爲概率分佈。它的缺點是沒有與Softmax或LogSoftmax合併,因此會存在數值穩定性問題。
在這裏插入圖片描述

  • BCE Loss with Logitsnn.BCEWithLogitsLoss()

可以看出,相比BCE Loss,我們對log裏的xx加上了一個激活函數σ\sigma = Sigmoid. 其目的是確保輸入到BCE 裏面的數據都被歸一化到0和1之間。
在這裏插入圖片描述

  • Margin Ranking Loss nn.MarginRankingLoss()

在這裏插入圖片描述
Margin loss是1類非常重要的損失函數。如果你有2個輸入,那麼Margin loss的目的是讓其中的1個輸入至少比另1個輸入大margin (margin是個標量)。

如上面的式子, yy只取 1,1{-1, 1}. 讓我們想象x1x_1x2x_2是兩個類別的分數。你的目的是想讓正確類別的得分比錯誤類別的得分至少高出margin。

與Hinge Loss類似,如果y(x1x2)y*(x_1 - x_2)大於margin,那麼根據Margin Loss的定義,loss的值爲0. 而如果小於margin,那麼隨着y(x1x2)y*(x_1 - x_2)的減小,Margin Loss線性增加。

以分類任務爲例,x1x_1應該是正確答案的得分而x2x_2是得分最高的錯誤答案,y=1y=1.

  • Triplet Margin Loss nn.TripletMarginLoss()
    在這裏插入圖片描述
    Triplet margin loss是用於度量樣本之間的相似性的指標。
    舉個例子,你把同屬1類的2張不同圖片喂入神經網絡中(如同屬花類的月季,海棠)來得到2個feature vector。你想讓同一類的feature vector儘可能的接近。

類似地,當你將不同類的圖片喂入神經網絡,得到的feature vector,你想讓這2個feature vector的距離越遠越好。

而Triplet Margin Loss的目的就是讓 “類內距離最小,類間距離最大”

Triplet Margin Loss公式中的aa表示anchor, pp表示positive, 表示與anchor同類的樣本;nn表示negtive,表示與anchor不同類的樣本。

TripleLet Loss的應用我知道的是FaceNet,用於人臉識別的網絡,大概是16年的樣子發出來的。
在這裏插入圖片描述
Triplet Margin Loss最初被用於谷歌的image search系統。其原理很簡單:

At that time, you would type a query into Google and it would encode that query into a vector. It would then compare that vector to a bunch of vectors from images that were previously indexed. Google would then
retrieve the images that were the closest to your vector.

  • Soft Margin Loss nn.SoftMarginLoss()
    在這裏插入圖片描述
    Soft Margin Loss創建了優化2分類邏輯損失的標準(在輸入Tensor xx 和 目標Tensor yy之間),yy的取值同Margin,也是-1和1。

其特點是:

① Margin Loss的softmax版本. 損失函數的目的是讓exp(y[i]x[i])exp(−y[i]∗x[i])x[i]x[i]y[i]y[i]對應上的時候(同屬1類)的情況下loss更小。因爲指數函數的性質:
在這裏插入圖片描述
② Soft Margin Loss的目的與Margin Loss一樣,即讓類內距離變近,類間距離變遠。但不同於Hard Margin,Soft Margin Loss在損失函數中加入了連續性,指數衰減的特徵,使得損失函數變得更加光滑,因此其對應的梯度範圍也比Hard Margin的Loss更大。理論上會使得模型收斂更加容易。

  • Multi-Class Hinge Loss nn.MultiLabelMarginLoss()

在這裏插入圖片描述
多分類Hinge Loss也是基於margin的loss,它允許輸入擁有不同數量的target。

x[y[j]]x[y[j]]表示正確的類得分,x[i]x[i]表示錯誤的類的得分,損失函數的設計目的是讓2者相差越大越好(即損失函數會越來越小)。

  • Hinge Embedding Loss nn.HingeEmbeddingLoss()

Hinge Embedding Loss被用於在半監督學習(semi-supervised learning)中度量輸入的相似性。

它將相似的輸入拉近(pull together),將不相似的輸入拉遠(pull away). 標籤yy表明得分是否需要向某個特定方向發展(The yy variable indicates whether the pair of scores need to go in a certain direction)。

  • Cosine Embedding Loss nn.CosineEmbeddingLoss()

Cosine Embedding Loss的目的是用cosine distance來衡量輸入的相似性。在學習非線性embeddings或半監督學習中被廣泛使用。

① 首先,我們用1減去2個向量的夾角的餘弦來表示規則化的歐式距離(normalized Euclidean distance)。

② 這樣做的好處是,無論何時你有兩個向量你想讓它們的距離儘可能大,很容易讓網絡通過讓向量很長來實現這一點。而這不是最優的。你不希望使向量變大/長,而是應該通過讓向量向正確的方向旋轉,這樣就可以對向量進行標準化,並計算出標準化的歐幾里得距離。

③ 理想情況下,Cosine Embedding Loss可以使得向量Vector儘可能的對齊。而Cosine Embedding Loss也可能會使得餘弦值小於特定的margin(margin通常是一個small positive value)。

④ 以地球爲例,在赤道附近的區域要遠大於高緯度地區的區域。我們對地球上的點進行歸一化,你想保證的是語義上相近的樣本依然相近,而語義上不相近的樣本相互正交。注意,你不想讓不相近的樣本相反,這是因爲只有2個完全相反點存在(極點)。而因爲赤道上有很大的取值範圍,所以你要讓Margin爲正這樣你就能利用所有這些面積。

  • Connectionist Temporal Classification (CTC) Loss nn.CTCLoss()

CTC Loss在音頻處理中得到非常廣泛的使用,其目的是度量連續的時間序列和目標序列的差異。

① CTC Loss對輸入的可能排列和target的概率求和,輸出1個loss值,這個值對任何輸入節點都是可微的。

② 這種輸入和目標align的方式被稱爲"mang-to-one", 這限制了target sequence的長度,使得target sequence的長度必須小於等於input length。

③ 當網絡的輸出是對應於類別的分數的向量序列時,它非常有用。

應用案例: 語音識別

  • 目標:每10毫秒預測一個單詞的發音。
  • 每個單詞都由一連串的聲音表示。
  • 根據說話人的語速,不同長度的聲音可能會映射到同一個單詞上。
  • 找到輸入sequence和輸出sequence的最佳映射關係。一個比較好的方法是使用動態規劃來找到最優代價路徑。

在這裏插入圖片描述
語音識別的CTC Loss
在這裏插入圖片描述
Many-to-one 映射過程示意圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章