一、基礎理解
- 學習曲線作用:
- 查看模型的學習效果;
- 通過學習曲線可以清晰的看出模型對數據的過擬合和欠擬合;
- 學習曲線:隨着訓練樣本的逐漸增多,算法訓練出的模型的表現能力;
- 表現能力:也就是模型的預測准確率,使用均方誤差表示;學習率上體現了模型相對於訓練集和測試集兩類數據的均方誤差。
-
具體的操作:
- len(X_train) 個訓練樣本,訓練出 len(X_train) 個模型,第一次使用一個樣本訓練出第一個模型,第二次使用兩個樣本訓練出第二個模型,... ,第 len(X_train) 次使用 len(X_train) 個樣本訓練出最后一個模型;
- 每個模型對於訓練這個模型所使用的部分訓練數據集的預測值:y_train_predict = 模型.predict(X_train[ : i ]);
- 每個模型對於訓練這個模型所使用的部分訓練數據集的均方誤差:mean_squared_error(y_train[ : i ], y_train_predict);
- 每個模型對於整個測試數據集的預測值:y_test_predict = 模型.predict(X_test)
- 每個模型對於整個測試數據集的預測的均方誤差:mean_squared_error(y_test, y_test_predict);
- 繪制每次訓練模型所用的樣本數量與該模型對應的部分訓練數據集的均方誤差的平方根的關系曲線:plt.plot([i for i in range(1, len(X_train)+1)],np.sqrt(train_score), label="train")
- 繪制每次訓練模型所用的樣本數量與該模型對應的測試數據集的預測的均方誤差的關系曲線:plt.plot([i for i in range(1, len(X_train)+1)],np.sqrt(test_score), label="test")
二、實例
1)模擬數據集
-
數據集
import numpy as np import matplotlib.pyplot as plt np.random.seed(666) 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.model_selection import train_test_split # random_state=10:隨機種子; X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=10)
2)使用線性回歸擬合數據集並繪制學習曲線
-
擬合
from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error # 存儲每一次訓練的模型的均方誤差 train_score = [] test_score = [] # for 循環:進行 75 次模型訓練,每次訓練出 1 個模型,第一次給 1 個數據,第二次給 2 個數據,... ,最后一次給 75 個數據 for i in range(1, 76): lin_reg = LinearRegression() lin_reg.fit(X_train[:i], y_train[:i]) # LinearRegression().fit(X_train[:i], y_train[:i]) # 查看模型的預測情況:兩種,模型基於訓練數據集預測的情況(可以理解為模型擬合訓練數據集的情況),模型基於測試數據集預測的情況 # 此處使用 lin_reg.predict(X_train[:i]),為訓練模型的全部數據集 y_train_predict = lin_reg.predict(X_train[:i]) train_score.append(mean_squared_error(y_train[:i], y_train_predict)) y_test_predict = lin_reg.predict(X_test) test_score.append(mean_squared_error(y_test, y_test_predict))
-
繪制
# np.sqrt(train_score):將列表 train_score 中的數開平方 plt.plot([i for i in range(1, 76)], np.sqrt(train_score), label='train') plt.plot([i for i in range(1, 76)], np.sqrt(test_score), label='test') # plt.legend():顯示圖例(如圖形的 label); plt.legend() plt.show()
-
分析:隨着數據集的增大,所訓練出的模型
- 相對於訓練數據集的均方誤差在逐漸增大:因為隨着數據集的增大,樣本點的增多,模型越難擬合住所有的數據,相應的均方誤差會逐漸的累積,越來越大,但隨着訓練數據集的增大,均方差的逐漸累積量越來越小,模型相應的會越來越穩定;
- 相對於測試數據集的測試誤差逐漸減小,當數據量增大到一定程度,測試誤差趨於相對穩定;
- 最終的訓練誤差和測試誤差幾乎接近,相當於一個級別,不過測試誤差比訓練誤差相對較大一點,因為訓練數據集訓練出的模型對訓練數據集擬合的程度較好,相對的模型對應訓練數據集的均方誤差相對較小;
3)將繪制學習曲線的方法封裝成一個函數
-
具體代碼
def plot_learning_curve(algo, X_train, X_test, y_train, y_test): """繪制學習曲線:只需要傳入算法(或實例對象)、X_train、X_test、y_train、y_test""" """當使用該函數時傳入算法,該算法的變量要進行實例化,如:PolynomialRegression(degree=2),變量 degree 要進行實例化""" 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(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, len(X_train)+1)], np.sqrt(train_score), label="train") plt.plot([i for i in range(1, len(X_train)+1)], np.sqrt(test_score), label="test") plt.legend() plt.axis([0, len(X_train)+1, 0, 4]) plt.show()
- 當使用該函數時傳入算法,該算法的變量要進行實例化,如:
plot_learning_curve(PolynomialRegression(degree=2), X_train, X_test, y_train, y_test)
- 可以直接傳承實例化后的變量,如:lin_reg = LinearRegression(),
plot_learning_curve(lin_reg, X_train, X_test, y_train, y_test)
-
使用 plot_squared_error() 函數,繪制線性回歸模型的學習曲線
plot_learning_curve(LinearRegression(), X_train, X_test, y_train, y_test)
-
使用 plot_squared_error() 函數,繪制線性回歸模型的學習曲線
from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error def PolynomialRegression(degree): return Pipeline([ ('poly', PolynomialFeatures(degree=degree)), ('std_scaler', StandardScaler()), ('lin_reg', LinearRegression()) ])
- degree = 2
poly2_reg = PolynomialRegression(degree=2) plot_learning_curve(poly2_reg, X_train, X_test, y_train, y_test)
- degree = 20
plot_learning_curve(PolynomialRegression(degree=20), X_train, X_test, y_train, y_test)
-
分析(一):對比 degree=2 和線性回歸學習曲線
-
- 對於欠擬合情況,和最佳的情況相比較,相對的 train 和 test 兩根曲線趨於穩定的位置,比最佳的兩個曲線趨於穩定的位置較高:說明,無論對於訓練數據集還是測試數據集,相應的誤差都比較大,這是因為本身模型選的不正確,即使在訓練數據集上,誤差也比較大;
-
分析(二):對比 degree=2 和 degree=20 兩個學習曲線
-
- 對於過擬合情況,在訓練數據集上,相應的誤差和最佳時的誤差差不多,甚至當 degree 取值更大時,過擬合的誤差比最佳時的誤差小;
- 對於過擬合情況,測試數據集的誤差相比較大,並且從圖上看出,測試數據集的誤差曲線距離訓練數據集的誤差曲線較遠:說明,此時模型的泛化能力不夠好,對於新的數據預測誤差較大;