模型过拟合与欠拟合的核心原理及其与数据集分割的关系

picture.image

什么是过拟合、欠拟

在机器学习和统计学中,过拟合(Overfitting)和欠拟合(Underfitting)是指模型在训练数据和测试数据上的表现情况

过拟合(Overfitting)

过拟合是指模型在训练数据上表现非常好,但在测试数据或新数据上表现不佳的情况,也就是说,模型过于复杂,能够记住训练数据中的所有细节和噪声,但这些细节和噪声并不具有普遍性,因此,模型无法很好地推广到新数据上

过拟合的原因:

  • 模型过于复杂,例如使用了过多的参数
  • 训练数据包含噪声或异常值,模型“学会”了这些无用的信息
  • 训练数据量不足,使得模型容易记住每个训练样本

如何检测过拟合:

  • 训练误差很低,但验证误差很高
  • 训练误差随着时间减小,但验证误差在达到某个最小值后开始增加

如何防止过拟合:

  • 简化模型,例如减少模型的参数或使用正则化技术
  • 增加训练数据量
  • 使用交叉验证来评估模型
  • 使用早停法(Early Stopping)在验证误差开始上升时停止训练

欠拟合(Underfitting)

欠拟合是指模型在训练数据和测试数据上的表现都很差的情况,也就是说,模型过于简单,无法捕捉数据中的复杂模式,因此,模型既不能在训练数据上表现好,也不能在新数据上表现好

欠拟合的原因:

  • 模型过于简单,例如使用了过少的参数或选择了不合适的模型
  • 特征选择不当,未能充分利用输入数据中的信息
  • 训练数据过少或数据质量不高

如何检测欠拟合:

  • 训练误差和验证误差都很高
  • 增加训练时间或复杂度后,误差并没有显著减少

如何解决欠拟合:

  • 增加模型复杂度,例如增加模型的参数或选择更复杂的模型
  • 添加更多特征或尝试不同的特征工程方法
  • 提高训练数据的质量或增加训练数据量

总结

  • 过拟合:模型太复杂,在训练数据上表现很好,但在新数据上表现不佳
  • 欠拟合:模型太简单,无法捕捉数据中的模式,在训练数据和新数据上都表现不佳

理想情况下,我们希望模型在训练数据和测试数据上都能有较好的表现,这就需要在模型复杂度和泛化能力之间找到一个平衡点

案例:多项式回归中的过拟合和欠拟合

我们将生成一些数据点,并尝试用不同复杂度的多项式回归模型来拟合这些数据,然后,我们将观察在不同复杂度下,模型的拟合情况


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

          
# 生成模拟数据
          
np.random.seed(0)
          
X = np.sort(np.random.rand(100, 1) * 10, axis=0)
          
y = np.sin(X).ravel() + np.random.randn(100) * 0.5
          

          
# 绘制实际数据点
          
plt.figure(figsize=(12, 6))
          
plt.scatter(X, y, color='black', label='Data')
          

          
# 欠拟合:使用线性回归 (1阶多项式)
          
poly1 = PolynomialFeatures(degree=1)
          
X_poly1 = poly1.fit_transform(X)
          
model1 = LinearRegression().fit(X_poly1, y)
          
y_pred1 = model1.predict(X_poly1)
          
plt.plot(X, y_pred1, color='blue', label='Underfitting (Degree 1)')
          

          
# 适中拟合:使用 4阶多项式
          
poly4 = PolynomialFeatures(degree=4)
          
X_poly4 = poly4.fit_transform(X)
          
model4 = LinearRegression().fit(X_poly4, y)
          
y_pred4 = model4.predict(X_poly4)
          
plt.plot(X, y_pred4, color='green', label='Good Fit (Degree 4)')
          

          
# 过拟合:使用 15阶多项式
          
poly15 = PolynomialFeatures(degree=15)
          
X_poly15 = poly15.fit_transform(X)
          
model15 = LinearRegression().fit(X_poly15, y)
          
y_pred15 = model15.predict(X_poly15)
          
plt.plot(X, y_pred15, color='red', label='Overfitting (Degree 15)')
          

          
# 添加图例
          
plt.legend()
          
plt.title('Polynomial Regression: Underfitting vs Overfitting')
          
plt.xlabel('X')
          
plt.ylabel('y')
          
plt.show()
          

          
# 打印模型的均方误差 (MSE)
          
print("Degree 1 MSE:", mean_squared_error(y, y_pred1))
          
print("Degree 4 MSE:", mean_squared_error(y, y_pred4))
          
print("Degree 15 MSE:", mean_squared_error(y, y_pred15))
      

picture.image

代码解释:

  • 数据生成:我们生成了一些随机的 X 数据点,并使用 sin(X) 加上一些噪声来生成目标变量 y
  • 欠拟合:我们使用了一阶(线性)多项式来拟合数据,由于模型太简单,它不能很好地捕捉数据的模式
  • 适中拟合:我们使用四阶多项式来拟合数据,这个模型能够较好地描述数据的模式
  • 过拟合:我们使用十五阶多项式来拟合数据。由于模型太复杂,它在训练数据上表现很好,但可能在新数据上表现不佳

结果:

运行这段代码后,您将看到一张图,展示了三个不同模型的拟合曲线,蓝色线代表欠拟合,绿色线代表适中拟合,红色线代表过拟合。您还将看到各个模型的均方误差(MSE),可以用来量化每个模型的表现

通过这个简单的例子,可以清楚地看到欠拟合和过拟合的效果,以及如何通过选择适当的模型复杂度来避免这些问题

数据集分割与过拟合、欠拟合的关系

在机器学习任务中,分割数据集是一个非常重要的步骤,通常分为训练集(Training Set)、验证集(Validation Set)和测试集(Test Set),下面我将详细解释为什么要分割数据集,以及它与过拟合和欠拟合之间的关系

为什么要分割数据集?

训练集(Training Set):

  • 用于训练模型,即模型从中“学习”参数
  • 模型通过不断调整参数来最小化训练集上的损失

验证集(Validation Set):

  • 用于调参和模型选择,验证集并不是模型用来训练的,而是用来评估模型的性能,帮助选择最优的超参数(如正则化强度、树的深度等)
  • 通过验证集,我们可以监控模型是否过拟合,如果验证集上的性能开始下降,而训练集上的性能继续上升,这通常意味着模型开始过拟合

测试集(Test Set):

  • 用于最终评估模型的泛化能力,测试集是完全独立于训练过程的,只在模型完全训练好后使用一次
  • 测试集的目的是评估模型在未见过的数据上的表现,反映模型的实际应用能力

分割数据集和过拟合、欠拟合的关系

过拟合和分割数据集的关系:

  • 过拟合 是模型在训练集上表现非常好,但在验证集或测试集上表现较差的现象, 这意味着模型学会了训练集中的噪声或特异性模式,而不是数据的普遍模式
  • 通过分割数据集并使用验证集,可以在训练过程中检测到过拟合的趋势, 当验证集上的性能开始下降时,可以考虑使用正则化、减少模型复杂度或使用早停法来防止过拟合
  • 测试集 在模型训练和选择过程中不参与,确保最终评估模型性能时没有过拟合的风险

欠拟合和分割数据集的关系:

  • 欠拟合 是指模型在训练集和验证集上都表现不佳的情况,这通常意味着模型过于简单,无法捕捉数据中的复杂模式
  • 验证集 可以帮助我们发现欠拟合的问题, 如果模型在验证集上表现不佳且训练误差也很高,则可能需要增加模型复杂度或改进特征工程来提高性能

总结

分割数据集的主要目的是评估和提升模型的泛化能力,避免过拟合和欠拟合:

  • 避免过拟合: 验证集提供了一种手段来检测和防止模型过度拟合训练数据, 测试集确保最终评估的公正性
  • 检测欠拟合: 通过观察训练集和验证集的误差,我们可以判断模型是否欠拟合,并采取相应的措施

这种数据集分割方法(尤其是训练集与验证集的划分)有助于在模型复杂度和泛化能力之间取得平衡,从而构建出在真实世界中表现良好的模型

验证集强调

并不是所有的机器学习任务都需要显式地分割验证集,在某些情况下,只分割训练集和测试集是足够的,具体使用哪种方法取决于任务的性质、数据量以及模型的复杂性

什么时候不需要单独的验证集?

数据量有限的情况:

  • 交叉验证(Cross-Validation): 当数据量有限时,为了充分利用数据,常常使用交叉验证而不是单独的验证集, 比如,常见的k折交叉验证会将数据集分为k个部分,每次使用k-1个部分进行训练,剩下的一个部分进行验证, 这样就可以在不浪费数据的情况下,对模型进行有效的评估和选择
  • 在 这种情况下,交叉验证的结果可以用来替代单独验证集的评估效果,因此只需要保留训练集和测试集

简单模型或标准任务:

  • 对于一些较为简单的模型(如线性回归)或在标准化任务(如MNIST手写数字识别)中,模型选择和调参的空间有限,可能不需要一个单独的验证集
  • 此时,可 以通过交叉验证的方式调参,或根据经验和已有文献直接选择模型及参数,并用训练集训练模型,然后在测试集上进行最终评估

已知模型结构或参数:

  • 如果你对要使用的模型及其参数已经非常了解,或基于经验可以直接确定最佳的模型和参数设置,则可以省去验证集的步骤, 这在一些特定领域的应用或深度学习中的预训练模型使用中较为常见
  • 在这种情况下,数据集通常分为训 练集和测试集,训练完模型后直接在测试集上评 估性能

什么时候需要验证集?

复杂模型或超参数调整:

  • 当你在训练复杂的模型(如深度神经网络)时,超参数的选择对最终模型性能影响很大, 此时,验证集是必不可少的,因为它能够帮助你在训练过程中找到最优的超参数设置,并监控模型的过拟合情况

模型选择:

  • 如果你不确定哪种模型最适合当前任务,或者你需要在多个模型之间进行比较选择,验证集的存在是非常重要的, 它可以帮助你在训练过程中评估不同模型的性能并做出选择

防止过拟合:

  • 在模型训练过程中,通过观察验证集的表现,可以及时发现并防止过拟合, 验证集的误差往往能更真实地反映模型在新数据上的表现

总结

是否需要分割验证集取决于任务的具体需求:

  • 只 分割训练集和测试集: 适用于简单任务、数据量有限且使用交叉验证的情况,或者当模型及参数已确定时
  • 分割训练集、验证集和测试集: 适用于复杂模型、超参数调整或模型选择时,以确保模型的泛化能力和防止过拟合

在实际应用中,很多时候需要根据具体情况灵活选择数据集的分割策略

往期推荐

利用XGBoost模型进行多分类任务下的SHAP解释附代码讲解及GUI展示

利用SHAP解释二分类模型的四种机器学习GUI工具

SVM多分类分析:SHAP解释各类别下各特征对模型的影响力

快速选择最佳模型:轻松上手LightGBM、XGBoost、CatBoost和NGBoost!

基于CatBoost回归预测模型的多种可解释性图表绘制

顶刊APP部署复现——基于XGBoost模型的心脏病风险预测与解释:Streamlit应用程序开发

优化XGBoost回归模型:网格搜索与K折交叉验证实现

picture.image

picture.image

picture.image

微信号|deep_ML

欢迎添加作者微信进入Python、ChatGPT群

进群请备注Python或AI进入相关群
无需科学上网、同步官网所有功能、使用无限制

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

0
0
0
0
评论
未登录
暂无评论