百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

通透!过拟合和欠拟合 全面总结!(过拟合与欠拟合解决方案)

toyiye 2024-09-01 05:41 3 浏览 0 评论

在机器学习中,有一项很重要的概念,那就是:过拟合(Overfitting)和欠拟合(Underfitting)。

很长一段时间,和不少同学私信聊到过拟合和欠拟合的问题。尤其是对于初学者来说,这个有时候感觉很难把握。

过拟合和欠拟合,涉及到机器学习中常见的两种模型性能问题,分别表示模型在训练数据上表现得过于复杂或过于简单。

下面咱们先来简单聊聊关于过拟合和欠拟合的特征,以及防止性能问题的方法。

过拟合(Overfitting)

基本概念

简单来说,过拟合就是模型在训练集上学习得太好,以至于学到了训练数据中的噪声和细节,导致模型泛化能力差,即模型在新的、未见过的数据上表现不佳。

通常发生在模型复杂度较高时,此时模型可能会尝试去捕捉训练数据中的每个小的特征,包括那些不具代表性的特征,而这些特征可能仅仅是由于随机噪声而存在。

特征

这里总结过拟合4个最主要的特征~

  1. 训练集表现良好:模型在训练数据上的准确率非常高,几乎完美。
  2. 测试集表现差:相比之下,模型在测试集或验证集上的表现要差得多。
  3. 泛化能力弱:模型对于新的数据缺乏适应性,泛化能力差。
  4. 学习曲线表现:在学习曲线上,训练误差持续降低,而验证误差降低到一定程度后开始增加。

防止过拟合有效方法

防止过拟合的方法很多,要根据不同的情况进行不同的操作,以下总结了11种方法。

相比于之前文中的5种方式,多增加了5种,都可以作为大家使用的方式~

  1. 数据增强:通过对训练数据进行变换,比如旋转、缩放、翻转等,可以增加数据的多样性,帮助模型学习到更一般的特征。
  2. 减少模型复杂度:选择更简单的模型或减少模型中的参数数量(例如,减少神经网络中的层数或每层的节点数)可以降低过拟合的风险。
  3. 正则化(Regularization):添加正则项(如L1或L2正则化)到损失函数中可以惩罚模型的复杂度,限制模型权重的大小,从而减少过拟合。
  4. 提前停止(Early Stopping):在训练过程中,一旦验证误差开始增加,即停止进一步训练,可以防止模型过度拟合训练数据。
  5. 交叉验证(Cross-Validation):使用交叉验证可以更好地估计模型在未见数据上的表现,并选择表现最好的模型参数。
  6. Dropout:在训练神经网络时,随机丢弃(即暂时移除)网络中的一些节点,可以防止网络中的节点同时共同适应训练数据。
  7. 集成学习(Ensemble Methods):结合多个模型的预测,如随机森林或梯度提升机,通常可以减少过拟合并提高模型的泛化能力。
  8. 限制参数的搜索空间:在进行模型选择和超参数调优时,限制参数的搜索空间可以避免选择过于复杂的模型。
  9. 数据集分割:合理分割数据集为训练集、验证集和测试集,确保模型不是简单地记住了特定数据集的特征。
  10. 噪声注入:在训练数据中添加噪声可以减少模型对训练样本的依赖,并增加其泛化能力。
  11. 特征选择:减少输入特征的数量,舍弃那些不相关或冗余的特征,可以简化模型并减少过拟合的风险。

大家在实验中,这些方法的应用和结合,可以在一定程度上避免过拟合,从而提高模型对新数据的泛化和预测能力。

欠拟合(Underfitting)

基本概念

欠拟合指的就是在训练数据上没有获得足够的学习,以至于无法捕捉到数据的基本结构,既不能在训练集上表现良好,也不能在新的数据上做出准确的预测。

欠拟合通常是因为模型过于简单,没有足够的参数来学习数据的复杂性。

特征

这里也是总结了4点,大家可以大概看下:

  1. 训练集表现不佳:模型在训练数据上的准确率低,无法得到一个好的拟合。
  2. 测试集表现同样不佳:模型在测试集上的表现也很差,因为它连训练数据都没有学习好。
  3. 泛化能力差:因为模型对训练数据的学习不足,所以对新数据的泛化能力也很差。
  4. 学习曲线表现:在学习曲线上,训练误差和验证误差都很高,且两者可能相差不大。

防止欠拟合的方法

同样是11种最常用的方法~

  1. 增加模型复杂度:选择更复杂的模型或增加模型中的参数数量(例如增加神经网络中的层数或每层的节点数)以便捕捉数据中更复杂的模式。
  2. 特征工程(Feature Engineering):通过创建更多的特征,例如通过组合、转换或多项式扩展现有特征,可以帮助模型学习到数据中的更多有用信息。
  3. 减少正则化:如果模型过于简单,可能需要减少正则化项的权重或完全去掉正则化,以允许模型的复杂度增加。
  4. 更长的训练时间:有时模型仅仅是因为没有训练足够久,因此增加训练迭代次数或者训练时间有助于模型更好地学习数据。
  5. 减少数据预处理:如果数据预处理过程过于简化,可能会丢失重要信息。确保数据处理不会导致有价值信息的丢失。
  6. 调整超参数:通过调整学习算法的超参数(如学习率、树的深度等),可以帮助模型更好地学习数据。
  7. 更多的数据:如果可用,使用更多的训练数据可以帮助模型更好地泛化到新数据上。
  8. 集成不同模型:有时将不同的模型组合起来,比如使用模型融合或堆叠(stacking),可以帮助提升整体的模型性能。
  9. 使用非线性模型:如果数据本身具有非线性关系而使用了线性模型,换用非线性模型可能会带来更好的拟合。
  10. 获取更多特征信息:在可能的情况下,收集更多相关特征,增加模型的输入信息。
  11. 模型选择:有时需要重新考虑所选模型的适用性,尝试不同的模型以找到更好的匹配。

在实验中,大家可以用起来~

案例 - 过拟合

下面,咱们通过一个具体的案例来说明过拟合现象及其解决方法。使用多项式特征和线性回归模型来演示过拟合,并展示如何通过增加正则化来减轻过拟合。

实验设置

  • 任务:基于单一特征x,预测目标变量y。
  • 数据集:生成一个简单的数据集,包含噪声。
  • 模型:使用线性回归模型,先不带正则化(容易过拟合),后添加L2正则化(岭回归)对比效果。

实验说明

  1. 生成数据集。
  2. 使用高阶多项式特征对数据进行转换,使模型更复杂,易于出现过拟合。
  3. 训练两个模型:一个是普通的线性回归模型,另一个是加入L2正则化的线性回归模型(岭回归)。
  4. 可视化并比较模型在训练集上的拟合情况以及在测试集上的表现。

完整代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error

# 生成数据集
np.random.seed(0)
x = np.linspace(-3, 3, 100)
y = x**2 + np.random.randn(100) * 2 + 3
X = x[:, np.newaxis] # 转换为二维数组,用于模型训练

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建多项式特征
poly = PolynomialFeatures(degree=10, include_bias=False)
X_poly_train = poly.fit_transform(X_train)
X_poly_test = poly.transform(X_test)

# 模型训练:线性回归
model_lr = LinearRegression()
model_lr.fit(X_poly_train, y_train)

# 模型训练:岭回归
model_ridge = Ridge(alpha=100)
model_ridge.fit(X_poly_train, y_train)

# 预测和评估
x_range = np.linspace(X.min(), X.max(), 100).reshape(-1, 1)
x_range_poly = poly.transform(x_range)

y_pred_lr = model_lr.predict(x_range_poly)
y_pred_ridge = model_ridge.predict(x_range_poly)

print("Linear Regression MSE:", mean_squared_error(y_test, model_lr.predict(X_poly_test)))
print("Ridge Regression MSE:", mean_squared_error(y_test, model_ridge.predict(X_poly_test)))

# 绘制图形
plt.scatter(X_train, y_train, color='gray', marker='o', label='Training data')
plt.scatter(X_test, y_test, color='gold', marker='x', label='Test data')
plt.plot(x_range, y_pred_lr, label='Linear Regression', color='red', linewidth=2)
plt.plot(x_range, y_pred_ridge, label='Ridge Regression', color='blue', linewidth=2)
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('Overfitting Example and Solution')
plt.grid(True)
plt.show()

过拟合的情况

很显然,大家可以看到。在未添加正则化的线性回归模型中(红色曲线),会看到模型尝试非常精确地通过每个训练数据点,导致在测试集上的表现(黄色点)较差,这就是典型的过拟合现象。

解决过拟合后的情况

引入L2正则化的岭回归模型(蓝色曲线)能够有效降低模型复杂度,虽然它不再尝试穿过所有训练数据点,但在测试集上的MSE(均方误差)有显著降低,显示出了更好的泛化能力。

案例 - 欠拟合

这里,咱们再通过一个案例说明欠拟合的情况~

实验设置

  • 任务:基于单一特征x,预测目标变量y。
  • 数据集:生成一个具有非线性关系的数据集。
  • 模型:首先使用简单的线性回归模型(可能导致欠拟合),然后使用多项式回归来改善欠拟合。

实验说明

  1. 生成具有非线性关系的数据集。
  2. 使用线性回归模型训练,观察其在复杂数据上的表现。
  3. 通过引入多项式特征并再次使用线性回归,提高模型复杂度,以解决欠拟合问题。
  4. 可视化比较两种情况下模型的表现。

完整代码

import numpy as np
import matplotlib.pyplot as plt
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

# 生成数据集
np.random.seed(42)
x = np.random.rand(100) * 10 - 5  # 生成-5到5之间的随机数
y = x**3 + np.random.randn(100) * 20 + 10  # 非线性关系加上噪声
X = x.reshape(-1, 1)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# 线性回归模型(可能导致欠拟合)
model_linear = LinearRegression()
model_linear.fit(X_train, y_train)

# 多项式回归(解决欠拟合)
poly_features = PolynomialFeatures(degree=3)  # 选择三阶多项式特征
X_poly_train = poly_features.fit_transform(X_train)
X_poly_test = poly_features.transform(X_test)

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

# 预测与评估
x_range = np.linspace(X.min(), X.max(), 100).reshape(-1, 1)
y_pred_linear = model_linear.predict(x_range)
y_pred_poly = model_poly.predict(poly_features.transform(x_range))

print("Linear Regression MSE:", mean_squared_error(y_test, model_linear.predict(X_test)))
print("Polynomial Regression MSE:", mean_squared_error(y_test, model_poly.predict(X_poly_test)))

# 绘制结果
plt.scatter(X_train, y_train, color='gray', marker='o', label='Training data')
plt.scatter(X_test, y_test, color='gold', marker='x', label='Test data')
plt.plot(x_range, y_pred_linear, label='Linear Regression', color='red', linewidth=2)
plt.plot(x_range, y_pred_poly, label='Polynomial Regression', color='blue', linewidth=2)
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('Underfitting Example and Solution')
plt.grid(True)
plt.show()


欠拟合的情况

在使用简单的线性回归模型中(红色曲线),由于模型复杂度不足以捕捉底层数据的非线性关系,导致在训练集和测试集上的表现都不理想,这就是典型的欠拟合现象。

解决欠拟合后的情况

通过引入多项式特征并应用线性回归模型(蓝色曲线),我们显著提高了模型的复杂度,使得模型能够更好地逼近具有非线性关系的真实数据。结果显示,多项式回归的MSE明显低于简单线性回归模型,有效地解决了欠拟合问题。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码