1. 程式人生 > >L1 loss, L2 loss以及Smooth L1 Loss的對比

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損失函式,對離群點、異常值不敏感,梯度變化相對更小,訓練時不容易跑飛。