[轉] Bias-Variance Tradeoff

from: https://liam.page/2017/03/25/bias-variance-tradeoff/

準確是兩個概念。準是 bias 小,確是 variance 小。準確是相對概念,因爲 bias-variance tradeoff。
——Liam Huang

在機器學習領域,人們總是希望使自己的模型儘可能準確地描述數據背後的真實規律。通俗所言的「準確」,其實就是誤差小。在領域中,排除人爲失誤,人們一般會遇到三種誤差來源:隨機誤差、偏差和方差。偏差和方差又與「欠擬合」及「過擬合」緊緊聯繫在一起。由於隨機誤差是不可消除的,所以此篇我們討論在偏差和方差之間的權衡(Bias-Variance Tradeoff)。

定義

數學上定義

首先需要說明的是隨機誤差。隨機誤差是數據本身的噪音帶來的,這種誤差是不可避免的。一般認爲隨機誤差服從高斯分佈,記作 ϵ(0,σϵ)ϵ∼N(0,σϵ)。因此,若有變量 yy 作爲預測值,以及 XX 作爲自變量(協變量),那麼我們將數據背後的真實規律 ff 記作

 

y=f(X)+ϵ.y=f(X)+ϵ.

 

偏差和方差則需要在統計上做對應的定義。

  • 偏差(bias)描述的是通過學習擬合出來的結果之期望,與真實規律之間的差距,記作 Bias(X)=E[f̂ (X)]f(X)Bias(X)=E[f^(X)]−f(X)。
  • 方差(variance)即是統計學中的定義,描述的是通過學習擬合出來的結果自身的不穩定性,記作 Var(X)=E[(f̂ (X)E[f̂ (X)])2]Var(X)=E[(f^(X)−E[f^(X)])2]。

以均方誤差爲例,有如下推論

 

Err(X)=E[(yf̂ (X))2]=E[(f(X)+ϵf̂ (X))2]=(E[f̂ (X)]f(X))2+E[(f̂ (X)E[f̂ (X)])2]+σ2ϵ=Bias2+Variance+Random Error.(1)(1)Err(X)=E[(y−f^(X))2]=E[(f(X)+ϵ−f^(X))2]=(E[f^(X)]−f(X))2+E[(f^(X)−E[f^(X)])2]+σϵ2=Bias2+Variance+Random Error.

 

直觀的圖示

下圖將機器學習任務描述爲一個「打靶」的活動:根據相同算法、不同數據集訓練出的模型,對同一個樣本進行預測;每個模型作出的預測相當於是一次打靶。


http://scott.fortmann-roe.com/docs/BiasVariance.html

左上角的示例是理想狀況:偏差和方差都非常小。如果有無窮的訓練數據,以及完美的模型算法,我們是有辦法達成這樣的情況的。然而,現實中的工程問題,通常數據量是有限的,而模型也是不完美的。因此,這只是一個理想狀況。

右上角的示例表示偏差小而方差大。靶紙上的落點都集中分佈在紅心周圍,它們的期望落在紅心之內,因此偏差較小。另外一方面,落點雖然集中在紅心周圍,但是比較分散,這是方差大的表現。

左下角的示例表示偏差大二方差小。顯而易見,靶紙上的落點非常集中,說明方差小。但是落點集中的位置距離紅心很遠,這是偏差大的表現。

右下角的示例則是最糟糕的情況,偏差和方差都非常大。這是我們最不希望看到的結果。

舉個栗子

現在我們做一個模擬實驗,用以說明至此介紹的內容。

首先,我們生成了兩組 array,分別作爲訓練集和驗證集。這裏,x 與 y 是接近線性相關的,而在 y 上加入了隨機噪聲,用以模擬真實問題中的情況。

複製
1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
np.random.seed(42) # the answer to life, the universe and everything
real = lambda x:x + x ** 0.1

x_train = np.linspace(0, 15, 100)
y_train = map(real, x_train)
y_noise = 2 * np.random.normal(size = x_train.size)
y_train = y_train + y_noise

x_valid = np.linspace(0, 15, 50)
y_valid = map(real, x_valid)
y_noise = 2 * np.random.normal(size = x_valid.size)
y_valid = y_valid + y_noise

現在,我們選用最小平方誤差作爲損失函數,嘗試用多項式函數去擬合這些數據。

複製
1
2
3
4
prop    = np.polyfit(x_train, y_train, 1)
prop_ = np.poly1d(prop)
overf = np.polyfit(x_train, y_train, 15)
overf_ = np.poly1d(overf)

這裏,對於 prop,我們採用了一階的多項式函數(線性模型)去擬合數據;對於 overf,我們採用了 15 階的多項式函數(多項式模型)去擬合數據。如此,我們可以把擬合效果繪製成圖。

複製
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import matplotlib.pyplot as plt

_ = plt.figure(figsize = (14, 6))

plt.subplot(1, 2, 1)
prop_e = np.mean((y_train - np.polyval(prop, x_train)) ** 2)
overf_e = np.mean((y_train - np.polyval(overf, x_train)) ** 2)
xp = np.linspace(-2, 17, 200)
plt.plot(x_train, y_train, '.')
plt.plot(xp, prop_(xp), '-', label = 'proper, err: %.3f' % (prop_e))
plt.plot(xp, overf_(xp), '--', label = 'overfit, err: %.3f' % (overf_e))
plt.ylim(-5, 20)
plt.legend()
plt.title('train set')

plt.subplot(1, 2, 2)
prop_e = np.mean((y_valid - np.polyval(prop, x_valid)) ** 2)
overf_e = np.mean((y_valid - np.polyval(overf, x_valid)) ** 2)
xp = np.linspace(-2, 17, 200)
plt.plot(x_valid, y_valid, '.')
plt.plot(xp, prop_(xp), '-', label = 'proper, err: %.3f' % (prop_e))
plt.plot(xp, overf_(xp), '--', label = 'overfit, err: %.3f' % (overf_e))
plt.ylim(-5, 20)
plt.legend()
plt.title('validation set')

多項式擬合結果

以訓練集上的結果來說,線性模型的誤差要明顯高於多項式模型。站在人類觀察者的角度來說,這似乎是顯而易見的:數據是圍繞一個近似線性的函數附近抖動的,那麼用簡單的線性模型,自然就無法準確地擬合數據;但是,高階的多項式函數可以進行各種「扭曲」,以便將訓練集的數據擬合得更好。

這種情況,我們說線性模型在訓練集上欠擬合(underfitting),並且它的偏差(bias)要高於多項式模型的偏差。

但這並不意味着線性模型在這個問題裏,要弱於多項式模型。我們看到,在驗證集上,線性模型的誤差要小於多項式模型的誤差。並且,線性模型在訓練集和驗證集上的誤差相對接近,而多項式模型在兩個數據集上的誤差,差距就很大了。

這種情況,我們說多項式模型在訓練集上過擬合(overfitting),並且它的方差(variance)要高於線性模型的偏差。此外,因爲線性模型在兩個集合上的誤差較爲接近,因此我們說線性模型在訓練過程中未見的數據上,泛化能力更好。因爲,在真實情況下,我們都需要使用有限的訓練集去擬合模型,而後工作在無限的真實樣本中,而這些真實樣本對於模型訓練過程都是不可見的。所以,模型的泛化能力,是非常重要的指標。

考慮到兩個模型在驗證集上的表現,在這個任務上,我們說線性模型表現得較好。

權衡之術

克服 OCD

對於很多人來說,不可避免地會有這樣的強迫症:希望訓練誤差降至 0。

我們說,人想要過得快樂,首先要接納自己,與自己和解。做機器學習相關的任務也是一樣,首先要理解和接受機器學習的基本規律,克服自己的強迫症。

首先,對於誤差,在公式 11 中,我們得知誤差中至少有「隨機誤差」是無論如何不可避免的。因此,哪怕有一個模型在訓練集上的表現非常優秀,它的誤差是 0,這也不能說明這個模型完美無缺。因爲,訓練集本身存在的誤差,將會被帶入到模型之中;也就是說,這個模型天然地就和真實情況存在誤差,於是它不是完美的。

其次,由於訓練樣本無法完美地反應真實情況(樣本容量有限、抽樣不均勻),以及由於模型本身的學習能力存在上限,也意味着我們的模型不可能是完美的。

因此,我們需要克服強迫症,不去追求訓練誤差爲 0;轉而去追求在給定數據集和模型算法的前提下的,逼近最優結果。

最佳平衡點的數學表述

在實際應用中,我們做模型選擇的一般方法是:

  • 選定一個算法;
  • 調整算法的超參數;
  • 以某種指標選擇最合適的超參數組合。

也就是說,在整個過程中,我們固定訓練樣本,改變模型的描述能力(模型複雜度)。不難理解,隨着模型複雜度的增加,其描述能力也就會增加;此時,模型在驗證集上的表現,偏差會傾向於減小而方差會傾向於增大。而在相反方向,隨着模型複雜度的降低,其描述能力也就會降低;此時,模型在驗證集上的表現,偏差會傾向於增大而方差會傾向於減小。

考慮到,模型誤差是偏差與方差的加和,因此我們可以繪製出這樣的圖像。

偏差與誤差的變化趨勢
http://scott.fortmann-roe.com/docs/BiasVariance.html

圖中的最優位置,實際上是 total error 曲線的拐點。我們知道,連續函數的拐點意味着此處一階導數的值爲 0。考慮到 total error 是偏差與方差的加和,所以我們有,在拐點處:

 

dBiasdComplexity=dVariancedComplexity(2)(2)dBiasdComplexity=−dVariancedComplexity

 

公式 22 給出了尋找最優平衡點的數學描述。若模型複雜度大於平衡點,則模型的方差會偏高,模型傾向於過擬合;若模型複雜度小於平衡點,則模型的偏差會偏高,模型傾向於過擬合。

過擬合與欠擬合的外在表現

儘管有了上述數學表述,但是在現實環境中,有時候我們很難計算模型的偏差與方差。因此,我們需要通過外在表現,判斷模型的擬合狀態:是欠擬合還是過擬合。

同樣地,在有限的訓練數據集中,不斷增加模型的複雜度,意味着模型會盡可能多地降低在訓練集上的誤差。因此,在訓練集上,不斷增加模型的複雜度,訓練集上的誤差會一直下降。

因此,我們可以繪製出這樣的圖像。

訓練集和驗證集上的誤差變化
http://www.learnopencv.com/bias-variance-tradeoff-in-machine-learning/

因此,

  • 當模型處於欠擬合狀態時,訓練集和驗證集上的誤差都很高;
  • 當模型處於過擬合狀態時,訓練集上的誤差低,而驗證集上的誤差會非常高。

處理欠擬合與過擬合

有了這些分析,我們就能比較容易地判斷模型所處的擬合狀態。接下來,我們就可以參考 Andrew Ng 博士提供的處理模型欠擬合/過擬合的一般方法了。

機器學習調試的一般流程

欠擬合

當模型處於欠擬合狀態時,根本的辦法是增加模型複雜度。我們一般有以下一些辦法:

  • 增加模型的迭代次數;
  • 更換描述能力更強的模型;
  • 生成更多特徵供訓練使用;
  • 降低正則化水平。

過擬合

當模型處於過擬合狀態時,根本的辦法是降低模型複雜度。我們則有以下一些武器:

  • 擴增訓練集;
  • 減少訓練使用的特徵的數量;
  • 提高正則化水平。
俗話說,投資效率是最好的投資。 如果您感覺我的文章質量不錯,讀後收穫很大,預計能爲您提高 10% 的工作效率,不妨小額捐助我一下,讓我有動力繼續寫出更多好文章。
打賞