这是8-4中提到的模型复杂度曲线。用于说明过拟合和欠拟合。
还有另一种曲线,也可以可视化地表达过拟合与欠拟合的情况,即学习曲线。
学习曲线
随着训练样本的逐渐增多,算法训练出的模型的表现能力。
欠拟合、拟合、过拟合和学习曲线图对比
仍使用8-4中的数据
绘制学习曲线的函数如下:
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
def plot_learning_curve(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(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( LinearRegression(), X_train, X_test, y_train, y_test)
在训练数据集上,误差逐渐升高。
刚开始,误差累积较快,到后面误差累积变慢。
在测试数据集上,刚开始误差很大,逐渐减小,减小到一定程度后达到相对稳定。
最终,训练误差与测试误差趋于大体相同。测试误差略高于训练误差。
2阶多项式回归,拟合
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
def PolynomialRegression(degree):
return Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
plot_learning_curve( PolynomialRegression(degree=2), X_train, X_test, y_train, y_test)
整体趋势与使用线性回归的图像是一致的。
区别在于,线性回归模型中训练误差和测试误差稳定在1.7左右
而2阶多项式回归模型中训练误差和测试误差稳定在1.0左右
这说明使用2阶多项式回归的结果是比较好的。
20阶多项式回归,过拟合
plot_learning_curve( PolynomialRegression(degree=20), X_train, X_test, y_train, y_test)
整体趋势仍然是train逐渐上升,test逐渐下降,最终趋于稳定。
在区别是,在train和test都比较稳定时,它们之间的差距是比较大。
这就说明模型虽然在训练数据集上拟合得非常好,但是在测试数据集上误差仍然很大。
这种情况通常就是过拟合。
总结
欠拟合情况和最佳情况相比,欠拟合情况train、test曲线趋于稳定的位置比最佳情况的要高一些。这是因为模型选择得不对,所以即使在训练数据集上误差也很大。 对于过拟合情况,train曲线和最佳情况差不多,但test曲线比较高,并且train与test之间的差距比较大。