在機器學習中,模型的欠擬合和過擬合是需要格外注意的問題,同時也是經(jīng)常發(fā)生的問題,其中過擬合最為常見.
欠擬合,即訓練出的算法模型不足以表達數(shù)據(jù)間的關系.
過擬合,即訓練出的算法模型過多地表達了數(shù)據(jù)間的關系,學習到的關系可能是一些噪聲.
關于欠擬合和過擬合還結合 偏差
方差
問題.可以參考另一篇筆記:
http://www.reibang.com/p/6b32a46cd0fc
模型訓練的目的在于對未知情況的預測,訓練者關注的應該是模型的泛化能力
,而非模型對于訓練數(shù)據(jù)的擬合效果(當然了,兩者是有密切的聯(lián)系的,不能割裂來看待).
那么如何測試模型的泛化能力?
針對這一問題,常用的trick就是將數(shù)據(jù)集拆分為訓練數(shù)據(jù)集和測試數(shù)據(jù)集.在訓練數(shù)據(jù)集上訓練模型,然后將模型運用到測試數(shù)據(jù)集上進行預測測試.同時,根據(jù)選定的性能指標對模型的性能進行評估.
根據(jù)模型在訓練 和 測試數(shù)據(jù)集上的表現(xiàn)可以繪制出模型的復雜度曲線 :模型復雜度曲線能夠表達模型的在訓練集和測試集上的準確度和泛化能力的關系.
學習曲線
需要注意的是,往往并不是所有模型都能準確地繪制出模型復雜度曲線.幸運的是,所有模型都能繪制出學習曲線, 學習曲線能夠清晰地描述模型的性能評價 泛化 和 過擬合情況.
以下兩張圖片中的學習曲線分別描述線性回歸模型最佳擬合和過擬合的情況:
在最佳擬合的情況下,模型在test_data和train_data上的曲線最終都收斂到1.0附近,test_data和train_data都有著良好的表現(xiàn),并且test_data上的收斂值值略大于train_data曲線上的收斂值,兩者十分貼近這說明泛化能力也是較好的.
在過擬合的情況下,模型在test_data和train_data上的曲線都最終收斂,但是兩條曲線的最終收斂值差值(曲線間隙)較大且test_data集合上收斂值偏大,這說明模型的泛化能力不夠好.同時,train_data上曲線的收斂速度與收斂效果比最佳擬合圖中的曲線更快更好,這說明模型本身是過擬合的.
關于學習曲線的繪制,這里給出實現(xiàn)代碼:
需要說明的幾點:
- 模型的性能評估,選用的標準是均方根誤差RMSE
- algo 處傳入不同的模型對象
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
def learn_curve_plot(algo,X_train,X_test,y_train,y_test):
train_score = []
test_score = []
for i in range(1,len(X_train)+1):
algo.fit(X_train[:i],y_train[:i])
y_train_predict = algo.predict(X_train[:i])
train_score.append(np.sqrt(mean_squared_error(y_train[:i],y_train_predict)))
y_test_predict = algo.predict(X_test)
test_score.append(np.sqrt(mean_squared_error(y_test,y_test_predict)))
plt.plot([i for i in range(1,len(X_train)+1)], np.array(train_score),label = 'train')
plt.plot([i for i in range(1,len(X_train)+1)], np.array(test_score),label = 'test')
plt.legend()
plt.axis([0,len(X_train)+1,0,4])
plt.show()