多项式次数选择完整演示

news/2025/11/28 21:27:33/文章来源:https://www.cnblogs.com/wangya216/p/19284191

多项式次数选择完整演示(Python)

本文将通过 人工生成数据→数据划分→多次数模型训练→验证集筛选最优次数→测试集评估 的全流程,演示多项式回归中如何通过验证集选择最优次数,所有代码逐行解释,兼顾理论与实践。

核心逻辑

多项式回归的核心是通过增加高次项(如 (x^2, x^3))拟合复杂数据,但次数过高会导致过拟合(训练集表现好、测试集表现差),次数过低会导致欠拟合(训练/测试集表现都差)。因此需要:

  1. 划分训练集(拟合模型)、验证集(筛选最优次数)、测试集(最终评估)
  2. 训练不同次数的多项式模型
  3. 用验证集的性能(如均方误差MSE)选择最优次数
  4. 用最优次数模型在测试集上验证泛化能力

完整代码(含逐行解释)

第一步:导入依赖库

# 1. 数值计算库(处理数组、数学运算)
import numpy as np
# 2. 绘图库(可视化数据和模型)
import matplotlib.pyplot as plt
# 3.  sklearn工具:数据划分、多项式特征构造、线性回归、 metrics评估
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

第二步:人工生成带噪声的非线性数据(模拟真实场景)

我们生成一个二次函数+随机噪声的数据(真实模型是二次多项式),用于后续验证选择逻辑:

# 1. 生成100个均匀分布的x值(范围[-3, 3]),reshape(-1,1)转为2D数组(sklearn要求输入为2D)
np.random.seed(42)  # 设置随机种子,保证结果可复现
x = np.linspace(-3, 3, 100).reshape(-1, 1)# 2. 真实模型:y = 2x² + 3x + 1 + 噪声(噪声服从正态分布N(0,1))
y_true = 2 * x**2 + 3 * x + 1
y = y_true + np.random.normal(0, 1, size=x.shape)  # 加入噪声,模拟真实数据的不确定性# 3. 可视化原始数据(可选,帮助理解数据分布)
plt.figure(figsize=(8, 4))
plt.scatter(x, y, color='blue', s=20, label='带噪声的原始数据')
plt.plot(x, y_true, color='red', linewidth=2, label='真实模型(二次多项式)')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.title('原始数据与真实模型')
plt.show()

输出:蓝色散点是带噪声的数据,红色曲线是真实的二次模型。

第三步:划分训练集、验证集、测试集(关键步骤)

  • 训练集(60%):用于拟合不同次数的多项式模型
  • 验证集(20%):用于筛选最优多项式次数(排除过拟合/欠拟合模型)
  • 测试集(20%):仅用于最终评估最优模型的泛化能力(不参与任何选择过程)
# 1. 第一步:先划分「训练集+验证集」(80%)和「测试集」(20%)
# test_size=0.2:测试集占比20%;random_state=42:固定随机划分方式
x_train_val, x_test, y_train_val, y_test = train_test_split(x, y, test_size=0.2, random_state=42
)# 2. 第二步:从「训练集+验证集」中再划分「训练集」(60%总数据)和「验证集」(20%总数据)
x_train, x_val, y_train, y_val = train_test_split(x_train_val, y_train_val, test_size=0.25, random_state=42  # 0.25是80%中的20%,即总数据的20%
)# 查看数据量(验证划分是否正确)
print(f"训练集数量:{len(x_train)}, 验证集数量:{len(x_val)}, 测试集数量:{len(x_test)}")

输出训练集数量:60, 验证集数量:20, 测试集数量:20(符合6:2:2划分)

第四步:训练不同次数的多项式模型,用验证集筛选最优次数

我们尝试1次到10次的多项式(覆盖欠拟合、合适、过拟合场景),核心逻辑:

  • 对每个次数,构造多项式特征(如x→[x, x², x³])
  • 用训练集拟合模型
  • 计算训练集和验证集的MSE(均方误差,越小表示拟合越好)
  • 选择「验证集MSE最小」的次数作为最优次数
# 1. 定义要尝试的多项式次数范围(1次到10次)
degrees = range(1, 11)  # 1,2,...,10# 2. 存储每个次数的训练集MSE和验证集MSE
train_mse_list = []
val_mse_list = []# 3. 遍历每个次数,训练模型并计算MSE
for degree in degrees:# ----------------------# 步骤1:构造多项式特征(核心!将x转为高次项组合)# ----------------------# PolynomialFeatures(degree=d):生成d次多项式特征,include_bias=False表示不自动加常数项(线性回归会自动加)poly = PolynomialFeatures(degree=degree, include_bias=False)# 对训练集、验证集、测试集分别构造特征(注意:测试集仅用于最终评估,此处先构造)x_train_poly = poly.fit_transform(x_train)  # 训练集:拟合+转换x_val_poly = poly.transform(x_val)          # 验证集:仅转换(用训练集的拟合结果,避免数据泄露)x_test_poly = poly.transform(x_test)        # 测试集:仅转换(同上)# ----------------------# 步骤2:训练线性回归模型(多项式回归本质是线性回归拟合高次特征)# ----------------------lr = LinearRegression()  # 线性回归模型(无正则化,方便观察过拟合)lr.fit(x_train_poly, y_train)  # 用训练集的多项式特征拟合模型# ----------------------# 步骤3:预测并计算MSE# ----------------------# 训练集预测与MSE(评估模型在训练数据上的拟合程度)y_train_pred = lr.predict(x_train_poly)train_mse = mean_squared_error(y_train, y_train_pred)  # MSE = 平均(真实值-预测值)²# 验证集预测与MSE(评估模型的泛化能力,用于筛选次数)y_val_pred = lr.predict(x_val_poly)val_mse = mean_squared_error(y_val, y_val_pred)# ----------------------# 步骤4:存储MSE结果# ----------------------train_mse_list.append(train_mse)val_mse_list.append(val_mse)# 打印当前次数的MSE(直观观察)print(f"多项式次数:{degree:2d} | 训练集MSE:{train_mse:.4f} | 验证集MSE:{val_mse:.4f}")

输出示例(关键观察点):

多项式次数: 1 | 训练集MSE:14.0412 | 验证集MSE:13.9845  # 欠拟合(1次多项式拟合不了二次数据)
多项式次数: 2 | 训练集MSE:1.0159 | 验证集MSE:0.8658   # 合适(接近真实模型,MSE小)
多项式次数: 3 | 训练集MSE:1.0064 | 验证集MSE:0.8907   # 开始过拟合(训练MSE下降,验证MSE上升)
...
多项式次数:10 | 训练集MSE:0.7756 | 验证集MSE:2.2345   # 严重过拟合(训练MSE最小,但验证MSE大幅上升)

第五步:可视化MSE曲线,确定最优次数

通过绘图可以更直观地观察「训练集MSE下降,验证集MSE先降后升」的趋势,最优次数对应验证集MSE的最低点:

plt.figure(figsize=(8, 4))
plt.plot(degrees, train_mse_list, 'o-', color='blue', label='训练集MSE')
plt.plot(degrees, val_mse_list, 's-', color='red', label='验证集MSE')
plt.xlabel('多项式次数')
plt.ylabel('均方误差(MSE)')
plt.title('不同次数的训练集MSE与验证集MSE')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(degrees)  # x轴显示所有尝试的次数# 标记最优次数(验证集MSE最小的次数)
best_degree = degrees[np.argmin(val_mse_list)]  # np.argmin返回最小值的索引
plt.scatter(best_degree, min(val_mse_list), color='green', s=100, zorder=5)
plt.annotate(f'最优次数:{best_degree}', xy=(best_degree, min(val_mse_list)),xytext=(best_degree+0.5, min(val_mse_list)+0.2),arrowprops=dict(arrowstyle='->', color='green'))
plt.show()print(f"\n通过验证集筛选出的最优多项式次数:{best_degree}")

输出:绿色点标记的是最优次数(本文中应为2次,与真实模型一致)。

第六步:用最优次数模型在测试集上做最终评估

测试集是「从未参与训练和选择」的数据,用于评估最优模型的泛化能力(即真实场景中的表现):

# 1. 用最优次数构造多项式特征,重新训练模型(用完整的训练集+验证集?或仅训练集?)
# 注:此处有两种方案,推荐方案2(更充分利用数据):
# 方案1:仅用原始训练集训练(保持划分一致性)
# 方案2:用「训练集+验证集」训练(因为验证集已完成选择,可合并为更大的训练集提升性能)# 本文采用方案2(更实用):
poly_best = PolynomialFeatures(degree=best_degree, include_bias=False)
x_train_val_poly = poly_best.fit_transform(x_train_val)  # 用训练集+验证集拟合特征
x_test_poly = poly_best.transform(x_test)                # 测试集仅转换# 2. 训练最优模型
lr_best = LinearRegression()
lr_best.fit(x_train_val_poly, y_train_val)# 3. 测试集预测与评估
y_test_pred = lr_best.predict(x_test_poly)
test_mse = mean_squared_error(y_test, y_test_pred)
test_rmse = np.sqrt(test_mse)  # 均方根误差(RMSE,单位与y一致,更易解释)print(f"\n最优模型({best_degree}次多项式)在测试集上的表现:")
print(f"测试集MSE:{test_mse:.4f}")
print(f"测试集RMSE:{test_rmse:.4f}")# 4. 可视化最优模型的预测效果
plt.figure(figsize=(8, 4))
plt.scatter(x, y, color='blue', s=20, label='原始数据')
plt.plot(x, y_true, color='red', linewidth=2, label='真实模型')# 生成密集的x点,绘制最优模型的拟合曲线(更平滑)
x_plot = np.linspace(-3, 3, 200).reshape(-1, 1)
x_plot_poly = poly_best.transform(x_plot)
y_plot_pred = lr_best.predict(x_plot_poly)
plt.plot(x_plot, y_plot_pred, color='green', linewidth=2, label=f'最优模型({best_degree}次多项式)')plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.title(f'最优模型拟合效果(测试集RMSE:{test_rmse:.4f})')
plt.show()

输出:绿色曲线是最优模型,测试集RMSE接近噪声水平(1.0左右),说明模型泛化能力良好。

关键结论与注意事项

  1. 验证集的核心作用:筛选超参数(此处是多项式次数),避免用测试集选择模型(会导致测试集性能失真,无法反映真实泛化能力)。
  2. 过拟合与欠拟合判断
    • 欠拟合:训练集和验证集MSE都很大(如1次多项式)。
    • 过拟合:训练集MSE很小,但验证集MSE显著上升(如8次以上多项式)。
  3. 数据划分原则
    • 训练集:占比60%-80%,用于拟合模型。
    • 验证集:占比10%-20%,用于选择超参数。
    • 测试集:占比10%-20%,仅用于最终评估。
  4. 多项式特征构造:必须用训练集的fit_transform,验证集和测试集仅用transform(避免数据泄露,即验证集/测试集的特征统计信息影响模型)。

扩展方向

  • 若数据量较小,可采用交叉验证(如5折交叉验证)替代单独的验证集,更充分利用数据。
  • 可加入正则化(如Ridge、Lasso回归)抑制过拟合,此时需要用验证集同时选择「多项式次数」和「正则化强度」。
  • 真实场景中,可通过网格搜索(GridSearchCV)自动遍历超参数,无需手动循环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/980102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 线程池深度解析:原理、策略与生产环境调优指南

在现代 Java 应用中,线程池已成为并发处理的核心基础设施。无论是 Web 服务、定时任务、RPC 框架还是大数据处理,线程池都扮演着至关重要的角色。正确理解线程池的工作机制与调优方法,将直接影响系统的吞吐、延迟与…

Tita CRM一体化平台:破解销售管理五大痛点,实现业绩可持续增长

在数字化转型浪潮中,销售管理正成为企业高质量发展的关键瓶颈。目标执行不到位、客户资源流失、团队协同低效、项目交付延期、绩效考核失真——这些痛点的背后,是企业销售管理体系的系统性缺失。Tita CRM以”销售+交…

NOIP 算法合集

Ⅰ​.数据结构 1.树状数组 时间复杂度:\(O(n\log n)\) 优点:常数小 缺点:可以维护的内容不如线段树 应用:小常数维护前缀和或单点值 int tr[200005]; void add(int x,int y){while(x<=n)tr[x]+=y,x+=(-x)&x…

会赢吗

会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢吗会赢…

直接通过electron创建项目

直接通过electron创建项目一、创建原始electron实例demo1 1、创建项目目录demo1 2、通过命令初始化项目配置文件package.json 命令:npm init -y 项目目录下生成packabe.json文件 {"name": "demo1"…

东方博宜OJ 1246:请输出n行的9*9乘法表 ← 嵌套循环

​【题目来源】https://oj.czos.cn/p/1246【题目描述】请从键盘读入一个整数 n,代表有 n 行,输出 n 行的 9*9 乘法表。比如,假设 n=5,则输出如下: 1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=165*…

使用cnpm(中国镜像源的npm客户端)来安装electron

使用cnpm(中国镜像源的npm客户端)来安装electron要使用cnpm(中国镜像源的npm客户端)来安装electron,你需要先确保已经安装了cnpm。如果你还没有安装cnpm,你可以通过npm来安装它。以下是具体步骤:1. 安装 cnpm 首…

2025年11月电动叉车销售企业避坑指南:市场主流品牌横向对比

在制造业转型升级和绿色物流政策推动下,电动叉车市场需求持续增长。根据中国工程机械工业协会数据,2025年前三季度电动叉车销量同比增长18%,占叉车总销量比例突破65%。许多企业管理者在选购电动叉车时面临诸多考量,…

2025年11月中国电动叉车销售公司推荐榜单:主流品牌综合对比分析

作为物流仓储、制造业企业管理者或采购负责人,您在2025年面临日益严格的环保政策与降本增效的双重压力时,选择可靠的电动叉车供应商成为关键决策。根据中国工程机械工业协会数据显示,2024年中国电动叉车销量占比已突…

详细介绍:Qt样式深度解析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

文档抽取科技:利用自然语言处理技术自动识别和提取合同、判决书等法律文书中的关键信息,并将其转化为结构化数据

文档抽取科技:利用自然语言处理技术自动识别和提取合同、判决书等法律文书中的关键信息,并将其转化为结构化数据pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; d…

替代模型简化复杂物理仿真任务

本文介绍了利用替代模型技术加速多物理场仿真的创新方法。通过机器学习将复杂物理模型压缩为轻量级版本,实现实时仿真计算,应用于电动汽车电池包模拟和食品储存优化等领域,计算速度提升高达10万倍。工程仿真瘦身实现…

U636459 网格

网格走路问题的多维版本。 我们说过,如果网格是二维的,复杂度可以做到 \(\sqrt {nm}\),这是因为通过根号分治有 DP 和容斥的两种解法,这里都需要运用到。 将所有坏点排序之后 DP 即可。

NOIP day -1 笔记

考前打云斗的模拟赛练一下手,比赛链接 T1 二分答案+差分,每次二分都模拟出一个差分数组来找到要求最严格的值,总时间复杂度为 \(O(n\log(a+k))\)AC Code #include<bits/stdc++.h> #define int long long #def…

2025-11-28 用后端java的架构来类比 NestJS 的各个部分(deepseek)

Java和NestJS在设计理念和架构模式上有很深的渊源。NestJS 本身很大程度上受到了 Spring Boot 和 Angular 的启发。核心概念类比NestJS 部件 Java/Spring 类比 核心职责Module (模块) @Configuration 配置类 / Java 包…

2025-11-28 用前端react的架构来类比 NestJS 的各个部分(deepseek)

好的,这个类比非常棒!用前端 React 的架构来理解 NestJS,可以让你快速建立起对 NestJS 各个核心部件的直观感受。 我们来做这样一个类比:一个 NestJS 应用就像一个复杂的 React 组件树,而它的模块、控制器、服务等…

java真分页查询两个库的数据,合并成一个结果集分页查询

/*** 合并两个库的数据,真分页* @param pageNum 页码(从1开始)* @param pageSize 页大小* @param age 查询条件(示例)* @return 分页结果*/public IPage<UserDTO> mergeUserPage(Integer pageNum, Integer …

【Microsoft Learn】Microsoft Azure 服务 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

U636458 蛇

记录一个 DP 表示匹配信息。 然后枚举开头位置,路径形态只有那么几种,枚举一下即可。 可 pku 那个题差不太多。

Spring AI 代码分析(十)--Spring Boot集成

Spring Boot 集成分析 请关注微信公众号:阿呆-bot 1. 工程结构概览 Spring AI 通过 Spring Boot Starter 和 Auto Configuration 机制,实现了零配置的 AI 应用开发。开发者只需要添加依赖和配置属性,就能使用各种 A…