回歸損失函數1:L1 loss, L2 loss以及Smooth L1 Loss的對比


總結對比下\(L_1\) 損失函數,\(L_2\) 損失函數以及\(\text{Smooth} L_1\) 損失函數的優缺點。

均方誤差MSE (\(L_2\) Loss)

均方誤差(Mean Square Error,MSE)是模型預測值\(f(x)\) 與真實樣本值\(y\) 之間差值平方的平均值,其公式如下

\[MSE = \frac{\sum_{i=1}^n(f_{x_i} - y_i)^2}{n} \]

其中,\(y_i\)\(f(x_i)\)分別表示第\(i\)個樣本的真實值及其對應的預測值,\(n\)為樣本的個數。

忽略下標\(i\) ,設\(n=1\),以\(f(x) - y\)為橫軸,MSE的值為縱軸,得到函數的圖形如下:

MSE的函數曲線光滑、連續,處處可導,便於使用梯度下降算法,是一種常用的損失函數。 而且,隨着誤差的減小,梯度也在減小,這有利於收斂,即使使用固定的學習速率,也能較快的收斂到最小值。

\(y\)\(f(x)\)也就是真實值和預測值的差值大於1時,會放大誤差;而當差值小於1時,則會縮小誤差,這是平方運算決定的。MSE對於較大的誤差(\(>1\))給予較大的懲罰,較小的誤差(\(<1\))給予較小的懲罰。也就是說,對離群點比較敏感,受其影響較大。

如果樣本中存在離群點,MSE會給離群點更高的權重,這就會犧牲其他正常點數據的預測效果,最終降低整體的模型性能。 如下圖:

可見,使用 MSE 損失函數,受離群點的影響較大,雖然樣本中只有 5 個離群點,但是擬合的直線還是比較偏向於離群點。

平均絕對誤差(\(L_1\) Loss)

平均絕對誤差(Mean Absolute Error,MAE) 是指模型預測值\(f(x)\)和真實值\(y\)之間距離的平均值,其公式如下:

\[MAE = \frac{\sum_{n=1}^n\mid f(x_i) - y_i\mid}{n} \]

忽略下標\(i\) ,設\(n=1\),以\(f(x) - y\)為橫軸,MAE的值為縱軸,得到函數的圖形如下:

MAE曲線連續,但是在\(y-f(x)=0\)處不可導。而且 MAE 大部分情況下梯度都是相等的,這意味着即使對於小的損失值,其梯度也是大的。這不利於函數的收斂和模型的學習。但是,無論對於什么樣的輸入值,都有着穩定的梯度,不會導致梯度爆炸問題,具有較為穩健性的解。

相比於MSE,MAE有個優點就是,對於離群點不那么敏感。因為MAE計算的是誤差\(y-f(x)\)的絕對值,對於任意大小的差值,其懲罰都是固定的。

針對上面帶有離群點的數據,MAE的效果要好於MSE。

顯然,使用 MAE 損失函數,受離群點的影響較小,擬合直線能夠較好地表征正常數據的分布情況。

MSE和MAE的選擇

  • 從梯度的求解以及收斂上,MSE是由於MAE的。MSE處處可導,而且梯度值也是動態變化的,能夠快速的收斂;而MAE在0點處不可導,且其梯度保持不變。對於很小的損失值其梯度也很大,在深度學習中,就需要使用變化的學習率,在損失值很小時降低學習率。

  • 對離群(異常)值得處理上,MAE要明顯好於MSE。

如果離群點(異常值)需要被檢測出來,則可以選擇MSE作為損失函數;如果離群點只是當做受損的數據處理,則可以選擇MAE作為損失函數。

總之,MAE作為損失函數更穩定,並且對離群值不敏感,但是其導數不連續,求解效率低。另外,在深度學習中,收斂較慢。MSE導數求解速度高,但是其對離群值敏感,不過可以將離群值的導數設為0(導數值大於某個閾值)來避免這種情況。

在某些情況下,上述兩種損失函數都不能滿足需求。例如,若數據中90%的樣本對應的目標值為150,剩下10%在0到30之間。那么使用MAE作為損失函數的模型可能會忽視10%的異常點,而對所有樣本的預測值都為150。這是因為模型會按中位數來預測。而使用MSE的模型則會給出很多介於0到30的預測值,因為模型會向異常點偏移。

這種情況下,MSE和MAE都是不可取的,簡單的辦法是對目標變量進行變換,或者使用別的損失函數,例如:Huber,Log-Cosh以及分位數損失等。

Smooth \(L_1\) Loss

在Faster R-CNN以及SSD中對邊框的回歸使用的損失函數都是Smooth \(L_1\) 作為損失函數,

\[\text{Smooth}{L_1}(x) =\left \{ \begin{array}{c} 0.5x^2 & if \mid x \mid <1 \\ \mid x \mid - 0.5 & otherwise \end{array} \right. \]

其中,\(x = f(x_i) - y_i\) 為真實值和預測值的差值。

Smooth \(L_1\) 能從兩個方面限制梯度:

  1. 當預測框與 ground truth 差別過大時,梯度值不至於過大;
  2. 當預測框與 ground truth 差別很小時,梯度值足夠小。

對比\(L_1\) Loss 和 \(L_2\) Loss

其中\(x\)為預測框與groud truth之間的差異:

\[\begin{align} L_2(x) &= x^2 \\ L_1(x) &= x \\ smooth_{L_1}(x) &=\left \{ \begin{array}{c} 0.5x^2 & if \mid x \mid <1 \\ \mid x \mid - 0.5 & otherwise \end{array} \right. \end{align} \]

上面損失函數對\(x\)的導數為:

\[\begin{align} \frac{\partial L_2(x)}{\partial x} &= 2x \\ \frac{\partial L_1(x)}{\partial x} &= \left \{ \begin{array}{c} 1 & \text{if } x \geq 0 \\ -1 & \text{otherwise} \end{array} \right. \\ \frac{\partial smooth_{L_1}(x)}{\partial x} &=\left \{ \begin{array}{c} x & if \mid x \mid <1 \\ \pm1 & otherwise \end{array} \right. \end{align} \]

上面導數可以看出:

  • 根據公式-4,當\(x\)增大時,\(L_2\)的損失也增大。 這就導致在訓練初期,預測值與 groud truth 差異過於大時,損失函數對預測值的梯度十分大,訓練不穩定。

  • 根據公式-5,\(L_1\)\(x\)的導數為常數,在訓練的后期,預測值與ground truth差異很小時,\(L_1\)的導數的絕對值仍然為1,而 learning rate 如果不變,損失函數將在穩定值附近波動,難以繼續收斂以達到更高精度。

  • 根據公式-6,\(\text{Smotth } L_1\)\(x\)較小時,對\(x\)的梯度也會變小。 而當\(x\)較大時,對\(x\)的梯度的上限為1,也不會太大以至於破壞網絡參數。\(Smooth L_1\)完美的避開了\(L_1\)\(L_2\)作為損失函數的缺陷。

\(L_1\) Loss ,\(L_2\) Loss以及\(Smooth L_1\) 放在一起的函數曲線對比

從上面可以看出,該函數實際上就是一個分段函數,在[-1,1]之間實際上就是L2損失,這樣解決了L1的不光滑問題,在[-1,1]區間外,實際上就是L1損失,這樣就解決了離群點梯度爆炸的問題

實現 (PyTorch)

def _smooth_l1_loss(input, target, reduction='none'):
    # type: (Tensor, Tensor) -> Tensor
    t = torch.abs(input - target)
    ret = torch.where(t < 1, 0.5 * t ** 2, t - 0.5)
    if reduction != 'none':
        ret = torch.mean(ret) if reduction == 'mean' else torch.sum(ret)
    return ret      

也可以添加個參數beta 這樣就可以控制,什么范圍的誤差使用MSE,什么范圍內的誤差使用MAE了。

def smooth_l1_loss(input, target, beta=1. / 9, reduction = 'none'):
    """
    very similar to the smooth_l1_loss from pytorch, but with
    the extra beta parameter
    """
    n = torch.abs(input - target)
    cond = n < beta
    ret = torch.where(cond, 0.5 * n ** 2 / beta, n - 0.5 * beta)
    if reduction != 'none':
        ret = torch.mean(ret) if reduction == 'mean' else torch.sum(ret)
    return ret

總結

對於大多數CNN網絡,我們一般是使用L2-loss而不是L1-loss,因為L2-loss的收斂速度要比L1-loss要快得多。

對於邊框預測回歸問題,通常也可以選擇平方損失函數(L2損失),但L2范數的缺點是當存在離群點(outliers)的時候,這些點會占loss的主要組成部分。比如說真實值為1,預測10次,有一次預測值為1000,其余次的預測值為1左右,顯然loss值主要由1000決定。所以FastRCNN采用稍微緩和一點絕對損失函數(smooth L1損失),它是隨着誤差線性增長,而不是平方增長。

  Smooth L1 和 L1 Loss 函數的區別在於,L1 Loss 在0點處導數不唯一,可能影響收斂。Smooth L1的解決辦法是在 0 點附近使用平方函數使得它更加平滑。

Smooth L1的優點

  • 相比於L1損失函數,可以收斂得更快。
  • 相比於L2損失函數,對離群點、異常值不敏感,梯度變化相對更小,訓練時不容易跑飛。


免責聲明!

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



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