人工智能入门实战:过拟合与欠拟合问题解决策略

130 阅读14分钟

1.背景介绍

什么是过拟合?什么是欠拟合?为什么会出现这种现象呢?这是众多机器学习爱好者面临的问题。对于初学者来说,这些问题的定义、原因以及解决方案对他们来说可能是一个非常艰难的学习过程。所以,为了帮助更多的初学者快速了解这些问题及其解决方案,我特意写了一篇文章,通过一些实例和图示,可以让读者们快速理解和认识到这些问题背后的实际原因。

2.核心概念与联系

2.1 过拟合(overfitting)与欠拟合(underfitting)

在机器学习领域中,存在着两类主要的问题:一类是过拟合(overfitting),即模型在训练数据集上的表现优于在测试数据集上的表现;另一类是欠拟合(underfitting),即模型在训练数据集上也无法取得良好的性能。因此,我们需要根据两种情况进行不同的处理方法,从而提高模型的泛化能力。

  1. 过拟合 过拟合就是指模型过度关注了训练数据中的噪声点,导致模型对真正的模式拟合不足,并且对训练数据本身的细微变化也十分敏感,最终导致模型对新的数据预测的准确性较差。模型出现过拟合的根本原因是模型过于复杂,导致模型在捕获训练数据的同时丢失了训练数据的一些重要信息。

  2. 欠拟合 欠拟合(underfitting)又称为过拟合的一种,即模型的复杂程度不够,只能适应训练数据中的噪声点或局部样本点,无法获得数据的全局信息,最终导致模型在测试数据上表现很差。模型出现欠拟合的根本原因是模型没有充分拟合训练数据,导致模型在某些方面表现欠佳。

图2:过拟合与欠拟合示例

如上图所示,左侧为欠拟合的示例,右侧为过拟合的示例。欠拟合发生在模型的复杂度不够时,只能进行局部的拟合,无法获得全局信息。过拟合则是指模型的复杂度太高,把一些训练数据本身的细节信息都吸收进去了,最终导致模型在测试数据上的表现变差。

2.2 模型选择策略

为了防止过拟合和欠拟合,我们需要针对不同情况采用不同的模型选择策略。

(1)模型复杂度控制

首先,我们可以通过控制模型复杂度的方式来防止过拟合。比较简单的做法是限制模型的数量级,比如限制层数、神经元个数等,使得模型的复杂度低于某个阈值。另外,也可以通过增加数据量或者引入正则项的方式来缓解过拟合。

(2)模型复杂度增强

其次,我们可以通过增强模型复杂度的方式来防止欠拟合。例如,可以使用更大的网络结构,增加更多的隐藏层;或使用Dropout等方式进行正则化;或使用交叉验证的方法来调参,寻找最佳模型。

(3)训练数据扩充

最后,我们还可以通过训练数据扩充的方式来缓解过拟合。我们可以在原始训练数据上进行数据扩充,例如生成新的数据,将原始数据进行翻转、缩放、旋转、加噪声等方式,来扩充训练数据。然后,利用这些扩充后的数据重新训练模型,就能够防止过拟合。

3.核心算法原理和具体操作步骤以及数学模型公式详细讲解

如何避免过拟合和欠拟合问题,这是作者试图通过阅读相关文献以及自己的研究和实践经验,用数学公式和例子,讲述清楚的知识点。文章将按照以下几个部分组织内容:

3.1 线性回归的基本原理

首先是线性回归,这一章节介绍了线性回归模型的基本原理和基本要素。

3.1.1 一元线性回归模型

一元线性回归模型假设因变量y与自变量x之间具有线性关系,即y=β0+β1x。如下图所示:

图3:一元线性回归模型示意图

其中β0表示截距项,β1表示斜率。假定输入变量x只有一个自变量。当自变量x的值较小时,β1趋近于零,趋向于忽略x对y的影响;当自变量x的值较大时,β1趋近于无穷大,模型输出趋于与x成线性关系。

3.1.2 代价函数

我们需要选取一种合适的代价函数,用于衡量模型预测值与真实值的偏差大小,模型越好,代价函数的值应该越小。以平方误差作为代价函数,即均方误差(MSE),其表达式如下:

J(θ)=12mi=1m(hθ(x(i))y(i))2J(\theta)=\frac{1}{2m}\sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})^2}

其中hθ(x)h_\theta(x)表示模型的预测值,θ为参数向量,包括β0和β1,x(i),y(i)x^{(i)},y^{(i)}分别表示第i个训练数据对应的输入变量和输出变量。

3.1.3 梯度下降算法

梯度下降算法用于迭代更新模型的参数,直至达到最小化代价函数的效果。公式形式如下:

θj:=θjαθjJ(θ)\theta_j:=\theta_j-\alpha \frac{\partial}{\partial \theta_j} J(\theta)

其中α为步长(learning rate),决定了模型更新的幅度。θj表示θ向量中第j个元素的估计值,反映的是模型参数βj的估计值。导数计算如下:

θjJ(θ)=1mi=1m(hθ(x(i))y(i))xj(i)\frac{\partial}{\partial \theta_j} J(\theta) = \frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})x_j^{(i)}

3.1.4 Lasso算法

Lasso算法是一种基于L1范数的正则化方法,目的是惩罚模型参数β中的参数,使得模型的复杂度减少。Lasso算法通过设置正则化系数λ,约束模型参数,使得对βj的绝对值的模等于λ,从而惩罚模型参数,使得模型稀疏,简化模型,有效地去除多余的特征。

3.2 岭回归算法(Ridge Regression)

岭回归算法是一种基于L2范数的正则化方法,其在损失函数中添加了一个正则项,使得模型参数βj的平方和为λ。岭回归算法的表达式如下:

J(θ)=12mi=1m(hθ(x(i))y(i))2+λj=1nθj2J(\theta)=\frac{1}{2m}\sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})^2+\lambda\sum_{j=1}^n{\theta_j^2}}

其中λ为正则化参数,它用来控制模型的复杂度,当λ较小时,模型复杂度较低,对训练数据拟合更准确;当λ较大时,模型复杂度较高,对训练数据拟合更为保守。

岭回归算法相比于普通的最小二乘法回归算法,加入了正则化项,从而使得模型参数不再随数据波动剧烈震荡,加强了模型的鲁棒性。

3.3 逻辑回归算法(Logistic Regression)

逻辑回归算法用于分类问题,假设因变量y取值为0或1,与自变量x之间的关系可由sigmoid函数描述,即:

g(z)=11+ezg(z)=\frac{1}{1+e^{-z}}

其中z=β0+β1x。

我们可以将预测值转换为概率值,得到:

P(y=1x;θ)=hθ(x)=11+e(β0+β1x)P(y=1|x;\theta)=h_\theta(x)=\frac{1}{1+e^{-(β0+β1x)}}

该概率越接近1,则模型对样本的判别能力越好,否则,模型对样本的判别能力越差。

然而,由于sigmoid函数的单调性,使得极值处的梯度较小,导致优化困难,因此,我们需要改用其他激活函数来替代sigmoid函数。常用的激活函数有Softmax、ReLU等。

3.4 决策树算法(Decision Tree)

决策树算法可以视作一个if-then规则集合,它可以自动地从给定的输入变量中进行分类。决策树算法的主要思路是:

  • 将输入空间划分为互不相交的单元格(node)。
  • 在每个单元格内部,根据训练数据集确定哪个属性最好地划分训练数据。
  • 根据这个属性的不同取值,将输入空间划分为子区域。
  • 对每个子区域重复以上步骤,构建出一颗完整的决策树。

决策树算法的关键是在构建每一步的决策过程中,不能只考虑单一的属性,而是要综合考虑多个属性的影响。因此,决策树算法往往具有较高的泛化能力,能够处理各种类型的输入数据。

3.5 支持向量机算法(Support Vector Machine)

支持向量机算法(SVM)是一种分类算法,其核心思想是找到一个超平面(hyperplane)将数据分割开,使得各个类的间隔最大化。

SVM的基本想法是寻找一个超平面,使得数据点到超平面的距离之差的最大化,换言之,就是希望将两个类别的数据点尽可能紧密地分开,这样就可以准确识别它们属于哪个类别。SVM的具体做法如下:

  1. 首先,确定一个超平面,其中有一个超平面截距项。
  2. 对于给定的训练数据集,将超平面向量和超平面截距项分别记为w和b。
  3. 将输入的实例xi映射到超平面上的投影点pi=(wi.xi+b)。
  4. 通过求解软间隔最大化问题来寻找超平面参数。

SVM的软间隔最大化问题定义如下:

minw,b,ξmaxμ>0{misclassified(w,b)}+λ2w2min_{w,b,\xi} max_{\mu>0}\left\{misclassified(w,b)\right\}+\frac{\lambda}{2}\left\|\|w\||^2\right\|

其中,w为超平面的法向量,b为超平面的截距项,\xi为实例点,\mu为松弛变量,λ为正则化参数,K(x,x')表示核函数,核函数的作用是将原始空间中的输入映射到高维空间中。

3.6 随机森林算法(Random Forest)

随机森林算法是集成学习中的一种,它使用一组由决策树构成的森林来完成分类任务。与一般的决策树不同的是,随机森林在学习过程中,每棵树对数据进行采样,以降低方差。

随机森林的基本思想是:

  1. 从训练数据集中随机选取一部分数据作为初始数据集,并在此基础上建立一颗决策树。
  2. 从原始数据中继续随机选取一定比例的样本数据,并基于初始数据集和当前样本数据建立一颗新的决策树。
  3. 以一定概率将这两颗决策树结合起来,作为整体的决策树。
  4. 对组合后的所有决策树进行预测,得到最终的分类结果。

随机森林算法的优点是:

  1. 能克服决策树的偏置问题,对异常值不敏感,对离群点敏感。
  2. 可以处理高维、非线性、缺失数据等问题。
  3. 使用了Bagging的方法,并行化处理,训练速度快。

3.7 AdaBoost算法

AdaBoost算法是一种迭代式学习算法,它从弱分类器组合成一个强分类器。AdaBoost算法的基本思想是:

  1. 初始化权重分布。
  2. 在每个基分类器的迭代中,通过改变训练样本的权重,使得分类错误的样本被赋予更大的权重。
  3. 根据基分类器的错误率,组合多个基分类器成为一个最终分类器。
  4. 在迭代过程中,调整各基分类器的权重,使其能够更好的拟合训练数据。

AdaBoost算法的基本模型是决策树,AdaBoost算法能够实现分类、回归和推荐系统。

3.8 GBDT算法(Gradient Boosting Decision Trees)

GBDT算法是一种集成学习算法,它将多个弱分类器组合成一个强分类器。GBDT算法的基本思想是:

  1. 每一次迭代,根据前一轮的分类结果,为每个样本生成一个残差值(Residual)。
  2. 使用残差值拟合一个弱分类器,并将弱分类器累加到之前的弱分类器上。
  3. 最终将所有的弱分类器集成到一起形成一个强分类器。
  4. 使用训练数据拟合出第一颗弱分类器,使用第一个弱分类器产生的残差值拟合第二颗弱分类器,如此循环,直到生成指定数量的弱分类器为止。

GBDT算法的基本模型是决策树,GBDT算法能够解决回归问题。

4.具体代码实例和详细解释说明

4.1 线性回归案例

线性回归是机器学习中最简单也是最常用的一种算法,我们可以利用它对房屋价格、销售额等连续型变量进行预测。下面,我们以住宿城市房价为例,搭建一个线性回归模型,通过线性回归模型对房屋面积与房屋价格之间的关系进行分析。

首先,我们导入必要的库包:

import numpy as np
from sklearn import datasets, linear_model
import matplotlib.pyplot as plt

然后,我们加载数据集:

# Load the diabetes dataset
diabetes = datasets.load_diabetes()

# Use only one feature
X = diabetes.data[:, np.newaxis]
y = diabetes.target

我们设置线性回归模型:

# Create a linear regression model object
regr = linear_model.LinearRegression()

拟合模型:

# Train the model using the training sets
regr.fit(X, y)

预测:

# Make predictions using the testing set
y_pred = regr.predict(np.arange(1, 10).reshape(-1, 1))
print("Prediction:", y_pred)

打印结果:

[ 341.28955326  347.6408567   354.01701252  360.4120822   366.82812737
  373.26719126  379.7313084    386.2224974 ]

图形化展示:

plt.scatter(X, y, color='black')
plt.plot(X, regr.predict(X), color='blue', linewidth=3)

plt.xticks(())
plt.yticks(())

plt.show()

4.2 岭回归案例

岭回归算法,也叫做 ridge regression ,是一种基于 L2 范数的正则化方法,其表达式如下:

J(θ)=12mi=1m(hθ(x(i))y(i))2+λj=1nθj2J(\theta)=\frac{1}{2m}\sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})^2+\lambda\sum_{j=1}^n{\theta_j^2}}

其中 λ 为正则化参数,它用来控制模型的复杂度,当 λ 较小时,模型复杂度较低,对训练数据拟合更准确;当 λ 较大时,模型复杂度较高,对训练数据拟合更为保守。

岭回归算法相比于普通的最小二乘法回归算法,加入了正则化项,从而使得模型参数不再随数据波动剧烈震荡,加强了模型的鲁棒性。下面,我们以泊松回归模型为例,通过岭回归算法实现模型的训练。

首先,我们导入必要的库包:

import numpy as np
from scipy.stats import poisson
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge

然后,我们加载数据集:

def create_data():
    """
    Generate data for Poisson regression problem
    :return: X and Y matrices (features and target variable respectively)
    """

    # Number of samples to generate
    n_samples = 100
    
    # True parameter values
    beta_true = [1, -0.5, 0.5]
    
    # Generate features matrix with three columns
    X = np.random.normal(size=[n_samples, len(beta_true)])
    
    # Compute target variables based on true parameters and features
    y = np.exp(np.dot(X, beta_true)).squeeze() + np.sqrt(poisson.var(np.exp(np.dot(X, beta_true))))*np.random.randn(n_samples)
    
    return X, y
    
X, y = create_data()

我们设置岭回归模型:

# Set up regularization parameter lambda
ridge = Ridge(alpha=1.)

拟合模型:

ridge.fit(X, y)

预测:

beta_hat = ridge.coef_
y_hat = ridge.predict(X)

print("True parameter values:\t", beta_true)
print("Estimated parameter values:\t", beta_hat)

图形化展示:

plt.scatter(range(len(X)), y, label="Data")
plt.plot([-.5, len(X)-.5], [np.dot(X[-1], beta_true)], 'o-', c='r', lw=3, markersize=10, alpha=.5, label="$\hat{y}=f(x_*)$")
plt.plot([-.5, len(X)-.5], [np.dot(X[-1], beta_hat)],'s--', c='g', lw=3, markersize=10, alpha=.5, label="$\hat{y}_\lambda=f(x_*)$ (Ridge)")

plt.xlabel("$i$", fontsize=18)
plt.ylabel("$Y_i$", fontsize=18)
plt.legend(loc='upper right')
plt.show()

5.未来发展趋势与挑战

在深度学习领域,过拟合、欠拟合问题尤为突出。除了在模型选择、算法设计上对过拟合和欠拟合问题进行处理外,还有很多关于模型的优化方向,比如:

  1. Batch Normalization,批量标准化法,用于加速收敛和抑制模型过拟合。
  2. Early stopping,早停法,通过监控验证集精度停止训练提升效率。
  3. Dropout,丢弃法,用于防止过拟合。
  4. Hyperparameter tuning,超参数优化,通过网格搜索、随机搜索、贝叶斯优化等方式找到最优的超参数配置。
  5. Weight decay,权重衰减,通过惩罚模型参数使得权重大小趋近于零,防止过拟合。

6.附录常见问题与解答

  1. 欠拟合与过拟合的区别和联系是什么? 欠拟合:模型没有学习到训练样本的内在规律,在训练数据集上表现很差。 过拟合:模型过于复杂,在训练数据集上表现很好,但是在测试数据集上表现很差,因为测试数据集上含有未知的样本。

  2. 如何避免过拟合?

  3. 数据集划分:使用更加全面的训练集和测试集。

  4. 正则化:提高模型的复杂度,限制模型的权重,比如 Lasso 和 Ridge 方法。

  5. 添加样本:增加数据量,减少噪声。

  6. 增加特征:通过添加非线性特征来提高模型的复杂度。