当前位置: 首页 > article >正文

【理解机器学习中的过拟合与欠拟合】

在机器学习中,模型的表现很大程度上取决于我们如何平衡“过拟合”和“欠拟合”。本文通过理论介绍和代码演示,详细解析过拟合与欠拟合现象,并提出应对策略。主要内容如下:

什么是过拟合和欠拟合?
如何防止过拟合和欠拟合?
出现过拟合或欠拟合时怎么办?
使用代码和图像辅助理解。


一、什么是过拟合和欠拟合?

1.1过拟合(Overfitting)

定义:过拟合就是模型“学得太多了”,它不仅学会了数据中的规律,还把噪声和细节当成规律记住了。这就好比一个学生在考试前死记硬背了答案,但稍微换一道题就不会了。

过拟合的表现:

训练集表现非常好:训练数据上的准确率高,误差低。
测试集表现很差:新数据上的准确率低,误差大。
模型太复杂:比如使用了不必要的高阶多项式或过深的神经网络。

1.2 欠拟合(Underfitting)

欠拟合是什么?

欠拟合就是模型“学得太少了”。它只掌握了最基本的规律,无法捕获数据中的复杂模式。这就像一个学生只学到了皮毛,考试的时候连最简单的题都答不对。

欠拟合的表现:

训练集和测试集表现都很差:无论新数据还是老数据,模型都表现不好。
模型太简单:比如使用了线性模型拟合非线性数据,或者训练时间不足。

二、如何防止过拟合和欠拟合?

2.1 防止过拟合的方法

  1. 获取更多数据

更多的数据可以帮助模型更好地学习数据的真实分布,减少对训练数据细节的依赖。

  1. 正则化

正则化通过惩罚模型的复杂度,让模型不容易“过拟合”。

from sklearn.linear_model import Ridge  # L2正则化
model = Ridge(alpha=0.1)  # alpha控制正则化强度
  1. 降低模型复杂度

简化模型,比如减少神经网络层数或多项式的阶数。

  1. 早停法(Early Stopping)

在模型训练时,监控验证集的误差,如果误差开始上升,提前停止训练。

from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=5)
  1. 数据增强(Data Augmentation)

在图像分类任务中,通过旋转、裁剪、翻转等方法增加数据的多样性,提升模型的泛化能力。

2.2 防止欠拟合的方法

  1. 增加模型复杂度

增加模型的参数,比如更多的神经元或更深的网络层。

  1. 延长训练时间

欠拟合可能是因为训练时间不够长,模型没有学到足够的规律。

3。 优化特征工程

如果模型无法拟合数据,可能是因为输入的特征不够好。尝试创建更多、更有意义的特征。

  1. 降低正则化强度

正则化强度过大可能限制了模型的学习能力,适当减小正则化系数。

三、过拟合与欠拟合时怎么办?
当你发现模型出现问题时,可以通过以下策略调整:

现象解决方法
过拟合- 获取更多数据
- 使用正则化
- 降低模型复杂度
- 使用早停法
欠拟合- 增加模型复杂度
- 延长训练时间
- 改善特征质量
- 减小正则化强度

四、代码与图像演示:多项式拟合的例子

下面通过一个简单的例子,用多项式拟合来直观感受过拟合与欠拟合。

4.1 数据生成
我们生成一个非线性数据集,并可视化:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib

matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为 SimHei,显示中文
matplotlib.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 生成非线性数据
np.random.seed(42)  # 设置随机种子,保证结果可复现
X = np.random.rand(100, 1) * 6 - 3  # X范围[-3, 3]
y = 0.5 * X**3 - X**2 + 2 + np.random.randn(100, 1) * 2  # 非线性关系并添加噪声

# 可视化数据
plt.scatter(X, y, color='blue', alpha=0.7, label='数据')  # 绘制散点图
plt.xlabel("X")  # 设置X轴标签
plt.ylabel("y")  # 设置Y轴标签
plt.title("生成的非线性数据")  # 设置图表标题
plt.legend()  # 显示图例
plt.show()  # 显示图表

在这里插入图片描述
结果图:
生成的数据呈现一个明显的非线性分布。

4.2 模型训练与可视化

我们训练三种模型:
线性回归(1阶):欠拟合。
4阶多项式回归:最佳拟合。
10阶多项式回归:过拟合。

from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 多项式拟合
degrees = [1, 4, 20]
for degree in degrees:
    poly_features = PolynomialFeatures(degree=degree)  # 生成多项式特征
    X_poly_train = poly_features.fit_transform(X_train)
    X_poly_test = poly_features.transform(X_test)

    # 训练模型
    model = LinearRegression()
    model.fit(X_poly_train, y_train)

    # 预测
    y_train_pred = model.predict(X_poly_train)
    y_test_pred = model.predict(X_poly_test)

    # 计算误差
    train_error = mean_squared_error(y_train, y_train_pred)
    test_error = mean_squared_error(y_test, y_test_pred)

    # 绘制拟合曲线
    X_plot = np.linspace(-3, 3, 100).reshape(100, 1)
    X_poly_plot = poly_features.transform(X_plot)
    y_plot = model.predict(X_poly_plot)

    plt.scatter(X, y, color='blue', alpha=0.7, label='Data')
    plt.plot(X_plot, y_plot, color='red', label=f'Degree {degree}')
    plt.xlabel("X")
    plt.ylabel("y")
    plt.title(f"Degree {degree}\nTrain Error: {train_error:.2f} | Test Error: {test_error:.2f}")
    plt.legend()
    plt.show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结果图:

Degree 1(欠拟合):模型太简单,无法捕获数据的非线性规律。
Degree 4(最佳拟合):模型复杂度适中,能很好地拟合数据。
Degree 20(过拟合):模型过于复杂,训练误差低,但测试误差大。

4.3 误差趋势分析

绘制训练误差和测试误差随模型复杂度变化的曲线:

train_errors = []
test_errors = []

for degree in degrees:
    poly_features = PolynomialFeatures(degree=degree)
    X_poly_train = poly_features.fit_transform(X_train)
    X_poly_test = poly_features.transform(X_test)

    model = LinearRegression()
    model.fit(X_poly_train, y_train)

    y_train_pred = model.predict(X_poly_train)
    y_test_pred = model.predict(X_poly_test)

    train_errors.append(mean_squared_error(y_train, y_train_pred))
    test_errors.append(mean_squared_error(y_test, y_test_pred))

# 绘制误差曲线
plt.plot(degrees, train_errors, marker='o', label='Train Error')
plt.plot(degrees, test_errors, marker='o', label='Test Error')
plt.xlabel("Polynomial Degree")
plt.ylabel("Mean Squared Error")
plt.title("训练误差和测试误差随多项式阶数变化")
plt.legend()
plt.show()

在这里插入图片描述

结果分析:

训练误差随着复杂度增加而降低。
测试误差先下降后上升,呈现“U型趋势”。

五、总结

5.1 过拟合与欠拟合的核心区别

过拟合:模型对训练数据“学得太死”,测试数据表现很差。
欠拟合:模型对数据“学得太少”,训练和测试表现都不好。

5.2 防止方法

防止过拟合:使用正则化、数据增强、早停等方法。
防止欠拟合:增加模型复杂度、延长训练时间、优化特征。


希望这篇文章让你对过拟合与欠拟合有了更深入的理解!如果还有疑问,欢迎交流!


http://www.kler.cn/a/451744.html

相关文章:

  • python fastapi docs UI 失效解决方案
  • 【Select 语法全解密】.NET开源ORM框架 SqlSugar 系列
  • dns一般设置为多少
  • leetcode-80.删除有序数组的重复项II-day12
  • 模型优化之知识蒸馏
  • sfnt-pingpong -测试网络性能和延迟的工具
  • 前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
  • 关于科研中使用linux服务器的集锦
  • 指数函数与累积效应——数学模型
  • MLCC电容加直流偏压时,为什么容值会变低?
  • 虾皮开的很高,还有签字费。
  • VUE3——003、VUE 项目中的文件结构(index.html、main.ts、App.vue)
  • 细说STM32F407单片机轮询方式读写SPI FLASH W25Q16BV
  • ArrayList与LinkedList、Vector的区别
  • 力扣658. 找到 K 个最接近的元素
  • 【RAG实战】语言模型基础
  • WPS工具栏灰色怎么办
  • 工业“元宇宙化”:科技引领生产新潮流
  • 微软的AI转型故事
  • docker环境动态链接库找不到liblpsolve55.so
  • 网络安全 | 入门:理解基本概念和术语
  • LabVIEW应用在工业车间
  • 前端XMLHttpRequest get请求能不能在body中传参数?
  • IDEA 打开 maven 的 settings.xml 文件
  • C语言-结构体数组练习题
  • 游戏引擎学习第60天