機器學習系列(二十三)——過擬合overfitting和欠擬合underfitting

過擬合和欠擬合

有了多項式迴歸的方式,我們就可以對非線性的數據做擬合了,不過,複雜度不夠的多項式迴歸會導致欠擬合問題,而過度地使用多項式迴歸又會導致過擬合問題。
接下來直觀地看一下什麼是過擬合和欠擬合,生成模擬數據集:

import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(-3,3,size=100)
X = x.reshape(-1,1)
y = 0.5 * x**2 +x +2 +np.random.normal(0,1,size=100)
plt.scatter(x,y)
plt.show()

用線性迴歸對該數據做訓練:

'''線性迴歸'''
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X,y)
lin_reg.score(X,y)  //out:0.49

用線性迴歸對該數據訓練後的R方值爲0.49,顯然線性關係不明顯,因此用線性迴歸是有很大誤差的。不過添加多項式特徵後,特徵畢竟變多了,用R方衡量來衡量不同特徵的模型不太直觀,改用均方誤差衡量:

from sklearn.metrics import mean_squared_error

y_predict = lin_reg.predict(X)
mean_squared_error(y,y_predict) 

線性迴歸的均方誤差爲3.03,再看一下二次多項式迴歸:

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

def PolynomialRegression(degree):
    '''傳入步驟對應的類組成多項式迴歸函數'''
    return Pipeline([
        ("poly",PolynomialFeatures(degree=degree)),
        ("std_scaler",StandardScaler()),
        ("lin_reg",LinearRegression())
    ])
poly2_reg = PolynomialRegression(degree=2)
poly2_reg.fit(X,y)
y2_predict = poly2_reg.predict(X)
mean_squared_error(y,y2_predict) 

二次多項式迴歸的均方誤差要減小很多,擬合的曲線如下圖:

那更高次的呢?我們來試一試10次和100次。10次的情況:

'''修改degree測試'''
poly10_reg = PolynomialRegression(degree=10)
poly10_reg.fit(X,y)
y10_predict = poly10_reg.predict(X)
mean_squared_error(y,y10_predict)

10次冪的均方誤差相比2次又小了。擬合曲線如下圖:

100次的情況:

'''修改degree測試'''
poly100_reg = PolynomialRegression(degree=100)
poly100_reg.fit(X,y)
y100_predict = poly100_reg.predict(X)
mean_squared_error(y,y100_predict)

可見均方誤差更小了,擬合曲線如下圖:

不過上面只是一個100次冪的曲線將所有樣本特徵點包括進去,實際上這條連續曲線是這樣的:

plt.scatter(x,y)
plt.plot(X_plot,y_plot,color='r')#有序排序後繪製曲線
plt.axis([-3,3,-4,10])
plt.show()

理論上我們提高多項式的次數可以任意精度擬合樣本點,從而樣本的均方誤差可以非常非常小,但是樣本誤差更小就真的能更好地表達數據走勢嗎?從圖像中看出顯然不能,這種現象是就是過擬合(overfitting),而只用一次線性迴歸擬合的情況則是欠擬合。
機器學習主要解決的問題是過擬合,雖然過擬合的模型能使樣本誤差總體很小,但是在新的樣本上表現卻很差,泛化能力弱。而我們需要的是泛化能力強的模型而不是在樣本上誤差更小的模型。這也正是測試數據集的意義,將樣本分爲訓練和測試數據集,只用訓練數據fit模型,而用測試數據測試模型。如果模型能在測試數據集同樣表現很好(有很小的誤差),說明模型效果不錯。可以測試,如果將樣本劃分爲訓練集和測試集,10次冪,100次冪的多項式迴歸雖然能使之在訓練集上的誤差更小,但是在測試集上誤差卻是越來越大的,這正是過擬合導致的。
線性模型

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=666)
lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
y_predict = lin_reg.predict(X_test)
mean_squared_error(y_test,y_predict)

二次模型

poly2_reg = PolynomialRegression(degree=2)
poly2_reg.fit(X_train,y_train)
y2_predict = poly2_reg.predict(X_test)
mean_squared_error(y_test,y2_predict)

10次模型和100次模型

從上述結果發現,在測試集上10次冪的誤差已大於2次冪的,而100次冪的誤差更是天文數字。綜上所述,欠擬合是算法所訓練的模型不能完整表述數據關係,而過擬合是算法訓練的模型過多地表達了數據間的關係(往往是把噪音當成了特徵,是噪音間的關係)。而我們需要尋找的是泛化能力最好的模型。


學習曲線

機器學習中有一個模型複雜度的概念,對於多項式迴歸,次冪越高則複雜度越高,對於knn算法來說,k值越小模型複雜度越高。相應地有模型複雜度曲線用於直觀地反映模型複雜度和模型準確率的關係

不過模型複雜度曲線的繪製困難,這在後面的決策樹再具體介紹。這裏我們先用一個學習曲線來直觀感受一下在多項式迴歸中,模型複雜度和訓練效果的關係。
線性模型

import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(-3,3,size=100)
X = x.reshape(-1,1)
y = 0.5 * x**2 +x +2 +np.random.normal(0,1,size=100)
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=10)#默認0.25
X_train.shape

封裝學習曲線繪製函數:

'''封裝學習曲線函數'''
def plot_learning_curve(algo,X_train,X_test,y_train,y_test):
    '''algo是模型'''
    train_score = []
    test_score = []
    l = len(X_train)+1
    for i in range(1,l):
        
        algo.fit(X_train[:i],y_train[:i])
        y_train_predict = algo.predict(X_train[:i])
        train_score.append(mean_squared_error(y_train[:i],y_train_predict))

        y_test_predict = algo.predict(X_test)
        test_score.append(mean_squared_error(y_test,y_test_predict))

    plt.plot([i for i in range(1,l)],np.sqrt(train_score),label='train')
    plt.plot([i for i in range(1,l)],np.sqrt(test_score),label='test')
    plt.legend()
    plt.axis([0,l,0,4])
    plt.show() 
plot_learning_curve(LinearRegression(),X_train,X_test,y_train,y_test)

繪製線性模型的學習曲線:

可以觀察到隨着訓練的進行(這裏是不斷增加訓練數據),訓練集上的誤差會慢慢積累,積累到一定程度穩定下來,測試集的誤差先升後慢慢降低到一定程度穩定下來。
二次模型

二次模型與線性模型趨勢一樣,不過穩定的位置較一次低而且在測試集上的曲線和訓練集上的曲線距離小,因爲2次確實是最優的模型。

20次冪模型

測試集曲線和訓練集曲線距離更大了,說明過擬合現象比較嚴重。我們要尋找的是有最好的泛化能力的模型。如何尋找最優的模型,使模型擁有優秀的泛化能力呢?這將在下篇介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章