第31课:多项式回归与非线性拟合
1. 学习目标
完成本课学习后,你将能够:
- 理解线性回归在处理非线性数据时的局限性。
- 掌握多项式回归的核心思想及其数学原理。
- 使用Scikit-learn库实现多项式回归,并进行模型拟合与预测。
- 评估多项式模型的拟合效果,并理解“过拟合”概念。
- 选择合适的多项式阶数,以平衡模型的偏差与方差。
2. 核心概念
为什么需要多项式回归?
在上一课“多元线性回归”中,我们假设自变量(特征)与因变量(目标)之间存在线性关系。然而,现实世界中的许多关系是非线性的。例如,一个物体的运动轨迹、生物生长曲线、广告投入与销量的边际效应等。如果用一条直线去拟合这些弯曲的数据,效果会非常差。
多项式回归的核心思想非常直观:我们不是用一条直线,而是用一条多项式曲线去拟合数据。它通过引入特征的高次项(如 (x^2, x^3, ...))来扩展线性模型的表达能力。
从数学上看,一个简单的多项式回归方程(以单个自变量 x 为例)是:
[ y = \beta_0 + \beta_1x + \beta_2x^2 + ... + \beta_nx^n + \epsilon ]
这里 n 被称为多项式的阶数。当 n=1 时,它就是我们熟悉的线性回归。
关键洞察:虽然模型关于系数 \(\beta\) 是线性的(这是“线性”回归名称的真正来源),但关于特征 x 却是非线性的。因此,我们可以在不改变线性回归求解框架(如最小二乘法)的前提下,处理非线性数据。
“升维”与“非线性拟合”
多项式回归可以看作是一种特征工程。它先将原始特征 x 转换为一组新的特征:[x, x², x³, ..., xⁿ],然后对这组新特征进行线性回归。
- 原始一维数据空间:数据点分布在一条曲线上。
- 升维后的多维空间:通过构造
x², x³...,我们把曲线“拉直”了。在高维空间中,数据与目标之间的关系可能变为线性。然后,一个在这个高维空间中的线性超平面,映射回原始一维空间,就形成了一条曲线。
3. 代码示例
我们将通过一个完整的例子来演示如何使用多项式回归拟合一条非线性曲线。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 1. 生成非线性数据
np.random.seed(42) # 设置随机种子以保证结果可复现
X = np.sort(5 * np.random.rand(100, 1), axis=0) # 生成0-5之间的100个点
y = np.sin(X).ravel() + np.random.randn(100) * 0.2 # 以正弦函数为基础,添加噪声
# 2. 准备多项式特征
degree = 3 # 我们尝试3次多项式
poly_features = PolynomialFeatures(degree=degree, include_bias=False) # 不包含截距项的常数特征(后面线性回归会自动加)
X_poly = poly_features.fit_transform(X) # X_poly现在有3列:[x, x^2, x^3]
# 打印原始特征和多项式特征的形状对比
print(f"原始特征X的形状: {X.shape}") # 输出: (100, 1)
print(f"多项式特征X_poly的形状: {X_poly.shape}") # 输出: (100, 3)
# 3. 训练模型
lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
y_pred = lin_reg.predict(X_poly)
# 4. 评估模型
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse:.4f}")
print(f"R² 分数: {r2:.4f}")
# 5. 可视化拟合结果
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color='blue', label='原始数据点', alpha=0.6)
# 为了绘制平滑的拟合曲线,生成一个密集的点序列
X_plot = np.linspace(0, 5, 300).reshape(-1, 1)
X_plot_poly = poly_features.transform(X_plot)
y_plot_pred = lin_reg.predict(X_plot_poly)
plt.plot(X_plot, y_plot_pred, color='red', linewidth=2, label=f'多项式回归 (degree={degree})')
plt.xlabel('X')
plt.ylabel('y')
plt.title('多项式回归拟合非线性数据')
plt.legend()
plt.grid(True)
plt.show()
# 6. 尝试不同阶数并比较(展示过拟合)
degrees = [1, 3, 10]
plt.figure(figsize=(15, 5))
for i, degree in enumerate(degrees):
poly_features = PolynomialFeatures(degree=degree, include_bias=False)
X_poly = poly_features.fit_transform(X)
lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
# 预测用于绘图
X_plot_poly = poly_features.transform(X_plot)
y_plot_pred = lin_reg.predict(X_plot_poly)
plt.subplot(1, 3, i+1)
plt.scatter(X, y, color='blue', alpha=0.6, label='数据')
plt.plot(X_plot, y_plot_pred, color='red', linewidth=2, label=f'Degree {degree}')
plt.title(f'Degree={degree}, R²={r2_score(y, lin_reg.predict(X_poly)):.2f}')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
代码解读:
- 我们先用正弦函数
sin(x)生成一些带噪声的非线性数据。 PolynomialFeatures是关键工具,它将原始特征X(1列) 转换成多项式特征X_poly(3列,对应x,x²,x³)。- 接着,我们用标准的
LinearRegression对这个升维后的特征矩阵进行拟合。 - 评估指标使用了MSE和R²。可视化是理解拟合效果最直观的方式。
- 最后一部分代码对比了不同阶数 (
degree) 的拟合效果。degree=1(直线)显然欠拟合;degree=3拟合得较好;而degree=10虽然完美穿过了所有训练点,但曲线非常扭曲,这是典型的过拟合,它在未知数据上表现会很差。
4. 实践练习
练习1:基础拟合
给定一组数据:X = [1, 2, 3, 4, 5, 6, 7, 8], y = [2, 8, 18, 32, 50, 72, 98, 128]。
请使用2次多项式 (degree=2) 进行拟合,并预测当 x=9 时的 y 值。你预测的值是多少?(提示:可以观察规律 y = 2*x^2)
练习2:模型选择
使用本课代码中生成数据的方法 (np.sin(X) + noise),尝试将多项式阶数 degree 分别设为 2, 5, 15。绘制三个模型的拟合曲线图,并分别计算它们在训练数据上的R²分数。你认为哪个阶数最合适?为什么?
练习3:综合应用
一家公司发现其广告投入 (x) 与产品销量 (y) 之间可能不是简单的线性关系。他们提供了12个月的数据。
X_ad = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).reshape(-1, 1)
y_sales = np.array([100, 150, 250, 350, 500, 700, 850, 1100, 1300, 1500, 1750, 2000])
- a) 分别使用线性回归 (
degree=1) 和二次多项式回归 (degree=2) 拟合数据。 - b) 计算两个模型的MSE。
- c) 预测下个月 (
x=13) 的销量分别是多少?你认为哪个模型的预测更可信?(可通过绘图观察拟合效果)
5. 常见错误
- 忽略数据升维步骤:尝试直接对
X使用高次项进行线性回归,而忘记用PolynomialFeatures进行特征转换。直接用X*X是错误的,因为它只改变数值大小,没有改变特征结构。 - 过度追求高阶多项式:认为阶数越高,拟合效果越好。实际上,过高的阶数会导致模型对训练数据中的噪声过度学习(过拟合),导致泛化能力极差。
- 忘记特征缩放:当多项式阶数较高时,特征值的尺度差异会变得非常巨大(例如
x=2vsx^10=1024)。这会使梯度下降法收敛缓慢,甚至影响数值稳定性。虽然本例使用的是正规方程求解,但在大数据集或迭代算法中,在构造多项式特征后,对数据进行标准化是一个好习惯。 - 误解“线性”模型:认为多项式回归不是线性模型。要记住,这里的“线性”是指参数(系数) 是线性的,而不是指数据关系是线性的。
6. 小结
- 多项式回归是处理特征与目标变量之间非线性关系的一种简单而强大的方法。
- 其本质是通过特征工程(
PolynomialFeatures)将原始特征升维为多项式特征,然后应用线性回归。这体现了机器学习中“线性模型+非线性特征”解决问题的经典思路。 - 模型的复杂度由阶数
n控制。选择合适的n至关重要:过低导致欠拟合,过高导致过拟合。 - 过拟合是多项式回归,乃至所有机器学习模型的核心挑战。模型在训练集上表现完美,但在新数据上表现糟糕。
- 可视化和计算评估指标(如R²、MSE)是判断模型拟合好坏的有力工具。
本课介绍的过拟合问题,将直接引出下一课的主题——正则化,它正是通过约束模型系数来防止过拟合的有效技术。