# 模型偏差和方差
> 原文:[https://www.bookbookmark.ds100.org/ch/15/bias_modeling.html](https://www.bookbookmark.ds100.org/ch/15/bias_modeling.html)
```
# HIDDEN
# Clear previously defined variables
%reset -f
# Set directory for data loading to work properly
import os
os.chdir(os.path.expanduser('~/notebooks/15'))
```
```
# HIDDEN
import warnings
# Ignore numpy dtype warnings. These warnings are caused by an interaction
# between numpy and Cython and can be safely ignored.
# Reference: https://stackoverflow.com/a/40846742
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
%matplotlib inline
import ipywidgets as widgets
from ipywidgets import interact, interactive, fixed, interact_manual
import nbinteract as nbi
sns.set()
sns.set_context('talk')
np.set_printoptions(threshold=20, precision=2, suppress=True)
pd.options.display.max_rows = 7
pd.options.display.max_columns = 8
pd.set_option('precision', 2)
# This option stops scientific notation for pandas
# pd.set_option('display.float_format', '{:.2f}'.format)
```
```
# HIDDEN
def df_interact(df, nrows=7, ncols=7):
'''
Outputs sliders that show rows and columns of df
'''
def peek(row=0, col=0):
return df.iloc[row:row + nrows, col:col + ncols]
if len(df.columns) <= ncols:
interact(peek, row=(0, len(df) - nrows, nrows), col=fixed(0))
else:
interact(peek,
row=(0, len(df) - nrows, nrows),
col=(0, len(df.columns) - ncols))
print('({} rows, {} columns) total'.format(df.shape[0], df.shape[1]))
```
我們之前已經看到,我們選擇的模型有兩個基本的錯誤來源。
我們的模型可能過于簡單——例如,線性模型無法正確地擬合由二次過程生成的數據。這種類型的錯誤是由模型**偏差**引起的。
我們的模型也可能適合數據中的隨機噪聲,即使我們使用二次模型擬合二次過程,模型也可能預測不同于實際過程產生的結果。這種類型的錯誤是由模型**方差**引起的。
## 偏差方差分解
我們可以通過分解模型風險的公式,使上面的陳述更加精確。回想一下,$f \theta 型號的**風險**是所有可能的訓練數據集$x$、$y$和所有輸入輸出點$z$、$\gamma$在總體上的預期損失:
$$ \begin{aligned} R(f_\hat{\theta}) = \mathbb{E}[ \ell(\gamma, f_\hat{\theta} (z)) ] \end{aligned} $$
我們將生成真實人口數據的過程表示為$f_yta(x)$。輸出點$\gamma$由我們的填充過程加上數據收集中的一些隨機噪聲生成:$\gamma_i=f_ \theta(z_i)+\epsilon$。隨機噪聲$\epsilon$是平均值為零的隨機變量:$\mathbb e[\epsilon]=0$。
如果我們使用平方誤差作為損失函數,則上述表達式將變為:
$$ \begin{aligned} R(f_\hat{\theta}) = \mathbb{E}[ (\gamma - f_\hat{\theta} (z))^2 ] \end{aligned} $$
通過一些代數運算,我們可以證明上述表達式等價于:
$$ \begin{aligned} R(f_\hat{\theta}) = (\mathbb{E}[f_\hat{\theta}(z)] - f_\theta(z))^2 + \text{Var}(f_\hat{\theta}(z)) + \text{Var}(\epsilon) \end{aligned} $$
此表達式中的第一個術語$(\mathbb e[f \theta(z)]-f \theta(z))^2$是模型偏差的數學表達式。(從技術上講,這個術語表示偏差平方,$\text 偏差^2$)如果從長遠來看,我們選擇$f \theta(z)$模型預測人口過程產生的相同結果,$f \theta(z)$則偏差等于零。如果我們選擇的模型對總體過程的預測很差,那么即使我們將整個總體作為數據集,這種偏差也是很高的。
此表達式中的第二個術語,$\text var(f \that \theta(z))$表示模型方差。當模型的預測在不同的數據集上訓練時變化不大時,方差很小。當模型在來自總體的不同數據集上訓練時,當模型的預測發生很大變化時,方差很大。
此表達式中的第三個也是最后一個術語,$\text var(\epsilon)$表示數據生成和收集過程中不可減少的錯誤或噪聲。當數據生成和收集過程很精確或變化很小時,這個術語就很小。當數據包含大量噪聲時,此術語很大。
## 偏差方差分解的推導
為了開始分解,我們從均方誤差開始:
$$\mathbb{E}[(\gamma - f_{\hat{\theta}}(z))^2]$$
并展開平方,應用期望線性:
$$ =\mathbb{E}[\gamma^2 -2\gamma f_{\hat{\theta}} +f_\hat{\theta}(z)^2]$$
$=\mathbb e[\gamma^2]-\mathbb e[2\gamma f \hat \theta(z)]+\mathbb[f \hat \theta(z)^2]$$
由于\ \\\123\\123 \123 123 ;(Z)美元。然后,我們用$F_uyta(z)+\epsilon$替換$\gamma$:
$$ =\mathbb{E}[(f_\theta(z) + \epsilon)^2] - \mathbb{E}[2(f_\theta(z) + \epsilon)] \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)^2]$$
再簡單化一些:(注意,$\mathbb e[f \theta(z)]=f \theta(z)$因為$f \theta(z)$是一個確定性函數,給定一個特定的查詢點$z$。)
$$ =\mathbb{E}[f_\theta(z)^2 + 2f_\theta(z) \epsilon + \epsilon^2] - (2f_\theta(z) + \mathbb{E}[2\epsilon]) \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)^2]$$
再次應用期望線性:
$$= f_\theta(z)^2 + 2f_\theta(z)\mathbb{E}[\epsilon] + \mathbb{E}[\epsilon^2] - (2f_\theta(z) + 2\mathbb{E}[\epsilon]) \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)^2]$$
注意到$\big(\mathbb e[\epsilon]=0\big)=>;\big(\mathbb[\epsilon^2]=\text var(\epsilon)\big)$因為$\text var(\epsilon)=\mathbb
$$ = f_\theta(z)^2 + \text{Var}(\epsilon) - 2f_\theta(z) \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)^2]$$
然后我們可以將方程改寫為:
$$ = f_\theta(z)^2 + \text{Var}(\epsilon) - 2f_\theta(z) \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)^2] - \mathbb{E}[f_{\hat{\theta}}(z)]^2 + \mathbb{E}[f_{\hat{\theta}}(z)]^2$$
因為$\mathbb e[f \hat \theta(z)^2]-\mathbb[f \hat \theta(z)]2=var(f \hat \theta(z))$:
$$ = f_\theta(z)^2 - 2f_\theta(z) \mathbb{E}[f_{\hat{\theta}}(z)] + \mathbb{E}[f_{\hat{\theta}}(z)]^2 + Var(f_{\hat{\theta}}(z)) + \text{Var}(\epsilon)$$$$ = (f_\theta(z) - \mathbb{E}[f_{\hat{\theta}}(z)])^2 + Var(f_{\hat{\theta}}(z)) + \text{Var}(\epsilon) $$$$= \text{bias}^2 + \text{model variance} + \text{noise}$$
為了選擇一個性能良好的模型,我們尋求最小化風險。為了最小化風險,我們嘗試最小化偏差方差分解的偏差、方差和噪聲項。例如,降低噪聲項通常需要改進數據采集過程,以購買更精確的傳感器。然而,為了減少偏差和方差,我們必須調整模型的復雜性。過于簡單的模型具有較高的偏差;過于復雜的模型具有較高的方差。這就是 _ 偏差方差權衡 _ 的本質,這是我們在選擇預測模型時面臨的一個基本問題。
## 示例:線性回歸和正弦波
假設我們正在對下面所示的振蕩函數生成的數據進行建模。
```
# HIDDEN
from collections import namedtuple
from sklearn.linear_model import LinearRegression
np.random.seed(42)
Line = namedtuple('Line', ['x_start', 'x_end', 'y_start', 'y_end'])
def f(x): return np.sin(x) + 0.3 * x
def noise(n):
return np.random.normal(scale=0.1, size=n)
def draw(n):
points = np.random.choice(np.arange(0, 20, 0.2), size=n)
return points, f(points) + noise(n)
def fit_line(x, y, x_start=0, x_end=20):
clf = LinearRegression().fit(x.reshape(-1, 1), y)
return Line(x_start, x_end, clf.predict(x_start)[0], clf.predict(x_end)[0])
population_x = np.arange(0, 20, 0.2)
population_y = f(population_x)
avg_line = fit_line(population_x, population_y)
datasets = [draw(100) for _ in range(20)]
random_lines = [fit_line(x, y) for x, y in datasets]
```
```
# HIDDEN
plt.plot(population_x, population_y)
plt.title('True underlying data generation process');
```

如果我們從人群中隨機抽取一個數據集,我們可能會得到以下結果:
```
# HIDDEN
xs, ys = draw(100)
plt.scatter(xs, ys, s=10)
plt.title('One set of observed data');
```

假設我們從總體中提取許多數據集,并將一個簡單的線性模型擬合到每個數據集。下面,我們用藍色繪制人口數據生成方案,用綠色繪制模型預測。
```
# HIDDEN
plt.figure(figsize=(8, 5))
plt.plot(population_x, population_y)
for x_start, x_end, y_start, y_end in random_lines:
plt.plot([x_start, x_end], [y_start, y_end], linewidth=1, c='g')
plt.title('Population vs. linear model predictions');
```

上面的圖表清楚地表明,一個線性模型會對這個群體產生預測誤差。我們可以將預測誤差分解為偏差、方差和不可約噪聲。我們通過顯示長期平均線性模型將預測不同于人口過程的結果來說明我們模型的偏差:
```
plt.figure(figsize=(8, 5))
xs = np.arange(0, 20, 0.2)
plt.plot(population_x, population_y, label='Population')
plt.plot([avg_line.x_start, avg_line.x_end],
[avg_line.y_start, avg_line.y_end],
linewidth=2, c='r',
label='Long-run average linear model')
plt.title('Bias of linear model')
plt.legend();
```

我們模型的方差是圍繞長期平均模型的模型預測的方差:
```
plt.figure(figsize=(8, 5))
for x_start, x_end, y_start, y_end in random_lines:
plt.plot([x_start, x_end], [y_start, y_end], linewidth=1, c='g', alpha=0.8)
plt.plot([avg_line.x_start, avg_line.x_end],
[avg_line.y_start, avg_line.y_end],
linewidth=4, c='r')
plt.title('Variance of linear model');
```

最后,我們通過顯示觀測點與底層總體過程的偏差來說明不可約誤差。
```
# HIDDEN
plt.plot(population_x, population_y)
xs, ys = draw(100)
plt.scatter(xs, ys, s=10)
plt.title('Irreducible error');
```

## 實踐偏差方差
在理想的情況下,我們將最小化我們的模型對總體中所有輸入輸出點的預期預測誤差。然而,在實踐中,我們不知道總體數據的生成過程,因此無法精確地確定模型的偏差、方差或不可約誤差。相反,我們使用我們的觀測數據集作為人口的近似值。
然而,正如我們所看到的,實現一個低的訓練錯誤并不一定意味著我們的模型也將有一個低的測試錯誤。通過擬合一條經過每次訓練觀測的曲線,可以很容易地得到一個偏差極低、訓練誤差小的模型。然而,該模型具有很高的方差,這通常會導致很高的測試誤差。相反,預測常數的模型具有低方差但高偏差。從根本上說,這是因為訓練誤差反映了我們模型的偏差,而不是方差;測試誤差反映了兩者。為了使測試誤差最小化,我們的模型需要同時實現低偏差和低方差。為此,我們需要一種不使用測試集來模擬測試錯誤的方法。這通常是通過交叉驗證完成的。
## 抽頭[?](#Takeaways)
偏差-方差權衡使我們能夠更準確地描述我們迄今為止所看到的建模現象。
下溢通常是由過多的偏差引起的;過度擬合通常是由過多的模型方差引起的。
收集更多的數據可以減少差異。例如,線性回歸的模型方差下降了$1/N$的因子,其中$N$是數據點的數量。因此,將數據集大小加倍將使模型方差減半,并且收集許多數據點將導致方差接近 0。最近的一個趨勢是選擇一個具有低偏差和高內在方差的模型(例如神經網絡),并收集許多數據點,使模型方差足夠低,能夠做出準確的預測。雖然在實踐中有效,但是為這些模型收集足夠的數據往往需要大量的時間和金錢。
如果模型能夠精確地適應人口過程,收集更多的數據可以減少偏差。如果模型本身無法對總體進行建模(如上例所示),即使是無限的數據也無法消除模型偏差。
向數據中添加一個有用的特性,例如,當底層進程是二次的時候,添加一個二次特性,可以減少偏差。添加一個無用的特性很少會增加偏差。
添加一個功能,無論是否有用,通常都會增加模型差異,因為每個新功能都會向模型添加一個參數。一般來說,具有許多參數的模型有許多可能的參數組合,因此比具有很少參數的模型具有更高的方差。為了提高模型的預測精度,新特征應該比增加方差更能減少偏差。
刪除功能通常會增加偏差,并可能導致下溢。例如,一個簡單的線性模型比添加了二次特征的同一個模型具有更高的模型偏差。如果數據是由二次現象生成的,那么簡單的線性模型將在數據下方。
在下面的圖表中,X 軸測量模型復雜性,Y 軸測量大小。請注意,隨著模型復雜性的增加,模型偏差將嚴格減少,模型方差將嚴格增加。當我們選擇更復雜的模型時,測試誤差首先減小,然后隨著模型方差的增加而增加,而大于模型偏差的減少。

如圖所示,一個高復雜度的模型可以實現較低的訓練誤差,但由于其模型方差較大,不能推廣到測試集。另一方面,復雜度較低的模型方差較低,但由于模型偏差較大,無法推廣。為了選擇一個有用的模型,我們必須在模型偏差和方差之間取得平衡。
當我們添加更多的數據時,我們將繪圖上的曲線向右和向下移動,減少偏差和方差:

## 摘要[?](#Summary)
偏差-方差權衡揭示了建模中的一個基本問題。為了使模型風險最小化,我們結合了特征工程、模型選擇和交叉驗證來平衡偏差和方差。
- 一、數據科學的生命周期
- 二、數據生成
- 三、處理表格數據
- 四、數據清理
- 五、探索性數據分析
- 六、數據可視化
- Web 技術
- 超文本傳輸協議
- 處理文本
- python 字符串方法
- 正則表達式
- regex 和 python
- 關系數據庫和 SQL
- 關系模型
- SQL
- SQL 連接
- 建模與估計
- 模型
- 損失函數
- 絕對損失和 Huber 損失
- 梯度下降與數值優化
- 使用程序最小化損失
- 梯度下降
- 凸性
- 隨機梯度下降法
- 概率與泛化
- 隨機變量
- 期望和方差
- 風險
- 線性模型
- 預測小費金額
- 用梯度下降擬合線性模型
- 多元線性回歸
- 最小二乘-幾何透視
- 線性回歸案例研究
- 特征工程
- 沃爾瑪數據集
- 預測冰淇淋評級
- 偏方差權衡
- 風險和損失最小化
- 模型偏差和方差
- 交叉驗證
- 正規化
- 正則化直覺
- L2 正則化:嶺回歸
- L1 正則化:LASSO 回歸
- 分類
- 概率回歸
- Logistic 模型
- Logistic 模型的損失函數
- 使用邏輯回歸
- 經驗概率分布的近似
- 擬合 Logistic 模型
- 評估 Logistic 模型
- 多類分類
- 統計推斷
- 假設檢驗和置信區間
- 置換檢驗
- 線性回歸的自舉(真系數的推斷)
- 學生化自舉
- P-HACKING
- 向量空間回顧
- 參考表
- Pandas
- Seaborn
- Matplotlib
- Scikit Learn