来源:原始 Jupyter Notebook。内容已转换为网页阅读格式;下载原文件

在前一节的例子中,我们只有一个自变量,也就是只有一个特征 (X)(X),但是通过数学变换,我们可以扩展到多个特征 (X,X2,...,Xn)(X, X^2, ..., X^n),并得到多项式回归。模型的结果如下图所示:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

# 创建图形,并将图形划分成 2*2 四格
plt.figure(figsize=(15,8))
ax1 = plt.subplot(2,2,1)
ax2 = plt.subplot(2,2,2)
ax3 = plt.subplot(2,2,3)
ax4 = plt.subplot(2,2,4)

def draw_polynomial(X, Y, degree):
    polynomial = PolynomialFeatures(degree = degree)
    X_t = polynomial.fit_transform(X)
    model = LinearRegression()
    model.fit(X_t, Y)
    x = np.linspace(30, 60, 100).reshape(-1, 1)
    x_t = polynomial.fit_transform(x.reshape(x.shape[0], 1))
    y = model.predict(x_t)
    plt.xlim(30, 60)
    plt.ylim(100, 600)
    plt.plot(x, y)

X = np.array([39.93, 42.05, 43.18, 44.68, 49.87, 53.57]).reshape(-1, 1)
Y = np.array([199,   290,   298,   310,   399,   420]).reshape(-1, 1)

# 一次回归
plt.sca(ax1)
plt.scatter(X, Y)
plt.text(31,540,r'$y=a_0+a_1x$',fontsize=12)
draw_polynomial(X, Y, 1)

# 二次回归
plt.sca(ax2)
plt.scatter(X, Y)
plt.text(31,540,r'$y=a_0+a_1x+a_2x^2$',fontsize=12)
draw_polynomial(X, Y, 2)

# 三次回归
plt.sca(ax3)
plt.scatter(X, Y)
plt.text(31,540,r'$y=a_0+a_1x+a_2x^2+a_3x^3$',fontsize=12)
draw_polynomial(X, Y, 3)

# 十次回归
plt.sca(ax4)
plt.scatter(X, Y)
plt.text(31,540,r'$y=a_0+a_1x+...+a_{10}x^{10}$',fontsize=12)
draw_polynomial(X, Y, 10)

plt.show()

运行结果

Notebook 运行结果

从图中的拟合程度来看,似乎是特征越多,模型越复杂,拟合效果越好。很显然这是不可取的,在前面讲到过拟合时我们提到,用非常复杂的模型可以把训练误差降的很低,甚至为0,而我们其实是希望模型在新样本上表现的很好,也就是泛化误差要小,当我们把模型训练的太复杂时,模型的泛化能力反而会下降。

这里我们犯了一个很严重的错误,既将样本数据当作训练数据,又把这些数据拿来评估模型的好坏,这有点像是在自娱自乐。为了解决这个问题,我们通常将数据集划分成两部分:训练集(training set)和测试集(testing set)。机器学习是关于算法的算法,根据输入的数据,生成 模型(model),这个模型可以接收新的输入数据,从而对未知的情况作出预测。生成模型的过程称为 学习(learning)或 训练(training),训练所使用的数据集合称为 训练集。生成模型之后,我们要对模型进行 测试(testing),测试所使用的数据集合称为 测试集

我们将数据划分成训练集和测试集之后,模型在训练集上的误差称为 训练误差(testing error),模型在测试集上的误差称为 测试误差(testing error),然后以测试误差作为泛化误差的一个近似,再根据模型的评估方法,找到测试误差最小的一个模型。

那么这里就引申出两个问题:如何将数据划分成训练集和测试集?如何在测试集上评估模型的好坏?