機器學(xué)習(xí)實戰(zhàn)之訓(xùn)練模型-多項式回歸(一)–泛化和學(xué)習(xí)曲線

本文介紹了多項式回歸的過擬合和欠擬合、泛化能力和學(xué)習(xí)曲線,通過對比測試集和驗證集的MSE的學(xué)習(xí)曲線,判斷擬合是過擬合還是欠擬合,尋找到最合適的模型。

高階多項式回歸對訓(xùn)練數(shù)據(jù)的擬合,可能會比簡單線性回歸要好。當(dāng)然太過高階(如階數(shù)200)的多項式回歸模型可能會嚴重的過度擬合訓(xùn)練數(shù)據(jù),而線性模型則擬合不足。
我們用一個例子來看看。

1.模塊引用

首先我們引入本文需要用到的所有模塊

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler

2.生成我們的測試數(shù)據(jù)

生成我們的測試數(shù)據(jù),并在坐標系中畫出來。

X = 10 * np.random.rand(100,1) - 5
X = np.sort(X,axis=0) ##為了方便作圖,X和y的每一個組合的順序沒有關(guān)系的
y = 0.5* X ** 2 + 2 * X + 2 + np.random.randn(100,1)
plt.scatter(X,y,c='green', alpha=0.6)
image

3.欠擬合

如果我們用線性模型進行擬合,明顯擬合不足。

lin_reg = LinearRegression()
lin_reg.fit(X, y)
y_predict = lin_reg.predict(X)
plt.scatter(X,y, c='green', alpha=0.6)
plt.plot(X, y_predict, color='blue',alpha=0.6)
plt.show()
image

4.過擬合

如果我們用非常高的階數(shù)進行擬合,擬合會非常好。但如果有新的數(shù)據(jù)進來,預(yù)測會非常差。

poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=200)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])

poly_reg.fit(X, y)
y_predict = poly_reg.predict(X)
plt.scatter(X,y, c='green', alpha=0.5)

plt.plot(X, y_predict, color='r',alpha=0.6)

plt.show()
image

上面的情況欠擬合和過擬合我們?nèi)绾伪苊獾模可鲜龅睦邮窃谖覀冎郎傻臄?shù)據(jù)的二次函數(shù)的情況下做的,實際情況我們一般不知道數(shù)據(jù)的模式,如何確定模型的復(fù)雜度呢?如何才能判斷模型是否過擬合或者欠擬合呢?

這篇文章《Python大規(guī)模建模的特征值選擇和性能評估方法詳解? 》我們使用了交叉驗證來評估模型的泛化能力,如果模型在訓(xùn)練集上表現(xiàn)良好,而在交叉驗證上的泛化表現(xiàn)很差,那么模型就是過度擬合。如果在二者上的表現(xiàn)都不佳,那就是擬合不足,這是判斷模型太簡單還是太復(fù)雜的一種方法。

5.泛化能力

我們把數(shù)據(jù)分成兩部分,一部分用于訓(xùn)練,尋找到一個適合的擬合模型,另一部分用于驗證,用于判定擬合是過擬合還是欠擬合。

先將數(shù)據(jù)劃分為80%的訓(xùn)練集和20%的驗證集。

X_train,X_val,y_train,y_val = train_test_split(X,y,test_size=0.2) #80%和20%劃分X和y

我們用線性回歸進行擬合

lin_reg = LinearRegression()
X_train,X_val,y_train,y_val = train_test_split(X,y,test_size=0.2) #80%和20%劃分X和y
lin_reg.fit(X_train, y_train) #用訓(xùn)練集進行擬合訓(xùn)練
y_predict = lin_reg.predict(X_val) #用驗證集的X來預(yù)測y
mean_squared_error(y_predict,y_val) #用預(yù)測得到的y和驗證集的y計算均方誤差

用訓(xùn)練集進行擬合訓(xùn)練,用驗證集的X來預(yù)測y,用預(yù)測得到的y和驗證集的y計算均方誤差,結(jié)果如下:

MSE=19.22

接下來我們用100階的多項式回歸進行擬合。

poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=100)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])

poly_reg.fit(X_train, y_train)
y_predict = poly_reg.predict(X_val)
mean_squared_error(y_predict,y_val)

結(jié)果如下:

MSE=39273456364906.516

上述兩個擬合雖然差別很大,但MSE都比較大,不能滿足我們的應(yīng)用需要。
我們看看2階多項式回歸(因為我們的數(shù)據(jù)就是用二階生成的)

poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=2)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])

poly_reg.fit(X_train, y_train)
y_predict = poly_reg.predict(X_val)
mean_squared_error(y_predict,y_val)

結(jié)果:MSE=1.1038,擬合得非常好。

6.學(xué)習(xí)曲線

我們看看不同的訓(xùn)練集的大小來進行訓(xùn)練,得到的結(jié)果用驗證集來計算均方誤差,看看均方誤差的趨勢是怎么樣的,這就是學(xué)習(xí)曲線。

首先我們定義一個函數(shù)。

train_errors,val_errors = [],[]
def plot_learning_curves(model,X,y):
 X_train,X_val,y_train,y_val = train_test_split(X,y,test_size=0.2)
 for m in range(1,X_train.size):#循環(huán)1-79
    model.fit(X_train[:m],y_train[:m])
    y_train_predict = model.predict(X_train[:m])
    y_val_predict = model.predict(X_val)
    train_errors.append(mean_squared_error(y_train_predict,y_train[:m]))
    val_errors.append(mean_squared_error(y_val_predict,y_val))
plt.plot(range(1,X_train.size),np.sqrt(train_errors),label='train',c='green')
plt.plot(range(1,X_train.size),np.sqrt(val_errors),label='val',c='red')

上面的函數(shù)是把數(shù)據(jù)分為80%的訓(xùn)練集和20%的驗證集(我們生成的數(shù)據(jù)是100個,兩個集合分別為80個和20個。

從驗證集中提取1個、2個、3個…80個記錄進行訓(xùn)練,得到的模型用訓(xùn)練集(和樣本一樣的記錄個數(shù))和驗證集分別進行計算MSE,把不同的樣本數(shù)量和MSE進行畫圖對比。

接下來我們用線性回歸進行模擬。

train_errors,val_errors = [],[]
lin_reg = LinearRegression()
plot_learning_curves(lin_reg,X,y)

得到下面的圖,紅色為驗證集的MSE,綠色為訓(xùn)練集的MSE。

image

當(dāng)訓(xùn)練樣本只有一個的時候,用訓(xùn)練集MSE解釋,模型完美擬合,但用驗證集的MSE解釋,完全不能接受的MSE大小,達到15左右。

隨著新的樣本進入訓(xùn)練,訓(xùn)練集的MSE開始上升,但訓(xùn)練樣本多了后,MSE穩(wěn)定在一定的水平。驗證集的MSE開始下降,穩(wěn)定到一定的水平。
這類型的曲線是典型的擬合不足

我們用100階多項式回歸進行擬合看看效果。

train_errors,val_errors = [],[]
poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=100)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])

plot_learning_curves(poly_reg,X,y)

結(jié)果如下:

image

注意縱坐標單位非常大看不出來效果,導(dǎo)致0和10000的點基本重合。我們查看驗證集的MSE看看。

image

出現(xiàn)非常大的數(shù),我們無法和訓(xùn)練集的個位數(shù)的MSE在同一張圖上表示。我們僅僅對驗證集的MSE進行對數(shù)計算,減少它的值,以方便在同一張圖表示。

pd_train_errors = pd.DataFrame(np.sqrt(train_errors))
pd_val_errors = np.log10(pd.DataFrame(np.sqrt(val_errors)))

plt.plot(range(1,80),pd_train_errors,linewidth=1,label='train',c='green', alpha=0.6)
plt.plot(range(1,80),pd_val_errors,linewidth=2,label='val',c='red', alpha=0.6)
![Alt text](./1564938218823.png)
image

可以很清楚的看出來,這個模型用訓(xùn)練集來計算MSE基本上在0-1之間,擬合非常好,但在驗證集的擬合就非常差了,MSE取了10為底數(shù)的對數(shù)后的值也達到了5-10之間。這種情況就是過擬合了。

我們看看階數(shù)為2的多項式回歸的情況

train_errors,val_errors = [],[]
poly_reg = Pipeline([
("poly", PolynomialFeatures(degree=2)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
plot_learning_curves(poly_reg,X,y)
image

不管是訓(xùn)練集合還是測試集的MSE都是非常小的(注意縱坐標單位)。當(dāng)然啦,我們的數(shù)據(jù)就是2階模擬出來的數(shù)據(jù)。

總結(jié)

本文介紹了多項式回歸的過擬合和欠擬合及其泛化能力和學(xué)習(xí)曲線,可以通過對比測試集和驗證集的MSE的學(xué)習(xí)曲線,判斷擬合是否是過擬合還是欠擬合,尋找到最合適的模型。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容