65.9K
CodeProject 正在变化。 阅读更多。
Home

逻辑分类器过拟合和正则化

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2014年10月3日

CPOL

14分钟阅读

viewsIcon

39240

downloadIcon

82

在本文中,我们将探讨逻辑分类器以及正则化如何影响分类器的性能。


在本文中,我们将探讨逻辑回归分类器以及正则化如何影响分类器的性能。

训练机器学习算法涉及优化技术。然而,除了在训练和验证数据集上提供良好的准确性之外,还需要机器学习模型具有良好的泛化能力。机器学习算法应该在未见过的新样本上也能表现良好。模型通过优化在某个训练数据集上的性能来训练,但其性能取决于其在新数据集上的表现能力。

当机器学习算法在训练数据集上具有高准确性但在泛化方面准确性较低时,通常会使用“过拟合”一词。

过拟合问题

过拟合通常发生在模型过于复杂时。过度拟合的模型通常泛化能力较差,因为它可能由于数据中的微小波动(由于噪声和其他在训练过程中未建模的参数)而产生错误。

仅仅因为模型与训练数据吻合,并不意味着它在新样本上表现良好,也不一定是一个好模型。在过拟合的情况下,模型只是试图学习训练集的特有规律,而在与训练集不同的新样本上表现不佳。

总的来说,过拟合通常与复杂性有关。在多类逻辑分类器用于MNIST数字分类时,有7850个自由参数需要优化。这是一个很大的参数量。

训练、验证和测试数据集

通常,我们可以通过定期在新未见过的测试数据集上测试模型来了解模型是否发生过拟合。因此,在训练过程中,我们使用3种类型的数据集:训练数据集,主要用于学习;验证数据集,它是训练数据集的一部分,但不用于学习;以及测试数据集,它包含大量代表所有可能未见过样本的输入数据的变化。

验证数据集是我们用于测试模型以检查过拟合和泛化性能的新数据集。学习算法尚未见过验证数据集中的样本。验证数据集用于测试模型参数的各种选择。因此,验证数据集(再次被视为训练数据集的一部分)用于定期评估模型参数。根据模型的性能,我们决定是否发生了过拟合,学习过程是否饱和,以及可能自适应地调整模型。

验证数据集与测试数据集的区别在于,验证数据集不像测试数据集那样具有挑战性。它包含未见过的新样本,但可能不包含大量变化或所有可能的极端情况或困难样本。

测试数据主要用于检查模型是否真正如预期那样应对大量数据变化。这就是为什么测试数据集应该包含数据变化大、困难和极端情况的样本,而这些样本不包含在训练数据中。如果我们直接使用测试数据进行验证,我们可能会使分类器偏向于过拟合或根据测试数据选择参数,这为了泛化性而言是不希望的。

验证曲线

如果我们发现验证准确性或训练准确性在增加,而测试数据的准确性在下降,我们可以假定这是由于过拟合。直观地说,过拟合发生在模型或算法过于贴合数据时。

在某些情况下,我们可能会观察到训练数据的准确性正在降低,而测试数据的准确性保持不变。这可能也意味着过拟合。因为模型试图通过更新模型来更好地拟合训练数据,但更新模型并未影响其在测试数据集上的性能。

避免过拟合

在本文中,我们将探讨逻辑回归分类器以及如何处理过拟合的情况。

增加数据集大小

解决过拟合的一种方法是增加训练数据的大小。以使用相似的训练过程和参数,在5000个和50000个样本上训练的MNIST数据集为例。
以下是在训练、验证和测试数据集上观察到的错误:

在第250次迭代时,错误是:
训练准确率为12.34%
测试准确率为12.0%
验证准确率为11.29%


我们可以观察到,在学习过程的初期,训练错误和验证错误稳步下降。然而,在第100次迭代之后,我们可以看到训练错误改进的速度比验证错误快。

验证错误基本保持不变。在第120次迭代时,我们再次看到验证曲线有所改善,但训练数据集上的错误率仍然更高。在第140次迭代之后,验证曲线基本上是一条直线,表明没有学习,尽管训练错误持续减少。这可能是过拟合的迹象。

现在,让我们用完整的50000个样本集进行相同的测试。当然,当我们包含更大的训练集时,绝对误差会更好,因为分类器可以学习处理更大的数据变化。但重要的是观察错误的改变速率,而不是绝对错误。

我们可以看到在第250次迭代时,错误是:
训练准确率为11.34%
测试准确率为10.0%
验证准确率为10.29%


这与之前的训练过程几乎相同。这意味着使用5000个样本数据集训练250次迭代,与使用更大的数据集具有相似的性能。这可能让我们得出结论,学习算法已有效地从数据中学习。然而,重要的是观察到错误曲线没有饱和。在当前示例中,错误曲线在第300次迭代时的下降速率比之前的要快。因此,如果我们让训练继续下去,错误率会在饱和之前进一步下降。特别是,我们将在测试和验证数据集上获得更低的错误。

因此,增加训练样本量避免了在训练过程的第300次迭代时的过拟合,并将带来更好的泛化性能。

早停

另一种解决过拟合的方法是执行早停。

早停规则可以指导在学习器开始过拟合之前可以运行多少次迭代。早停规则已在许多不同的机器学习方法中使用,具有不同程度的理论基础。

基于交叉验证的早停通过监控模型在验证集上的性能来解决过拟合。验证集上的错误被用作泛化错误的代理,以确定何时开始过拟合。

在不同的实现中,存在许多用于确定何时真正发生过拟合的临时规则,但很少有规则具有理论基础。


其中一个规则可能是,如果我们看到训练数据上的错误在减少,而验证数据集上的错误保持不变或开始减少,这可能表明我们需要停止训练过程,或者它可能导致过拟合。

早停常用的标准之一是验证错误的改变速率。如果验证错误在连续迭代中没有显著变化,我们就减少执行基于梯度学习的迭代次数。

如前所述,验证集是一组我们从不用于梯度下降的样本,但它也不是测试集的一部分。验证样本被认为是未来测试样本的代表。如果模型在验证集上的性能没有足够改善,甚至随着进一步优化而下降,那么可以使用一些启发式方法来停止进一步的优化。

在本文中,我们根据在 deeplearning.net教程 中的随机梯度学习框架中使用的几何增长的耐心量来指定一种策略。我们将在未来的文章中讨论随机梯度下降算法。基于梯度的学习算法执行学习算法N次。

在数学中,几何级数(也称为几何序列)是一系列数字,其中第一项之后的每一项都是通过将前一项乘以一个固定的非零数(称为公比)得到的。

使用的启发式方法是验证错误的几何级数。让我们考虑公比为0.9。如果最佳验证误差为0.5,下一个误差小于0.9 * 0.5 = 0.45,那么我们认为发生了显著的误差减少。

如果误差显著减少,我们就将算法应运行的迭代次数乘以一个几何因子;如果误差没有显著增加,我们就将要运行的迭代次数除以一个几何因子。如果已达到最大迭代次数,则表示学习过程已完成,并保留最佳学习迭代的参数。

使用此标准,对于具有5000个样本的训练样本,学习在第134次迭代时停止,此时:

训练准确率为12.82%
测试准确率为11.4%
验证准确率为12.09%


我们可以看到,即使在第250次迭代时,我们也没有获得性能的显著改进。

训练准确率为12.34%
测试准确率为12.0%
验证准确率为11.29%


因此,早停有助于防止过拟合。

验证启发式方法的代码如下:

       if error3 < self.best_validation_loss:
         self.best_validation_loss=error3;
         if error3 < self.best_validation_loss *self.improvement_threshold:
                self.patience = max(self.patience, self.iter * self.patience_increase)
             self.best_validation_loss = error3
             self.best_iter = self.iter
        else:
          self.patience = min(self.patience,self.iter+self.iter/self.patience_increase)
error3是上述代码中的当前验证错误。self.improvement_threshold是误差改进因子,通常取值在0.9-1之间。self.patience_increase是几何迭代因子,通常取值大于2。每次未满足验证启发式条件时,迭代次数将按此因子减少。
 

正则化

一种解决过拟合的方法是通过正则化。正则化技术可以看作是对模型参数施加某种先验分布。从数学上看,正则化过程意味着执行约束优化。

L2正则化意味着对权重施加高斯先验,而L1先验意味着对权重施加拉普拉斯先验。

有几种正则化技术。然而,在本文中,我们将探讨 $L_{p}$ 正则化及其对逻辑分类过程的影响。
$L_{p}$ 正则化涉及向成本函数添加一个额外的项,该项会惩罚某些参数配置。
如果原始损失函数定义为:
$$L(\theta,\mathcal{D}) = - \sum_{i=1}^N log P(Y=y_i | X=x_i,\theta) \quad$$
则正则化后的损失函数为:
$$E(\theta,\mathcal{D}) = L(\theta,\mathcal{D}) + \lambda R(\theta) \quad$$

在一般情况下,对于 $L_{p}$ 正则化:

$$R'(\theta)= \lambda || \theta||_{p}^p \quad = \lambda \left(\sum_{j=0}^{|\theta|}{|\theta_j|^p}\right) \quad$$
 
其中 $||\theta||_{p}^p$ 是 $\theta$ 的 $L_p$ 范数,$\lambda$ 是一个控制正则化参数相对重要性的参数。通常使用 L1 或 L2 范数。

直观地说,添加正则化项会惩罚参数的大值,从而减少网络建模的非线性量。添加正则化项的效果是简化模型并在存在过拟合的情况下提高性能。因此,在正则化项存在的情况下最小化损失函数将为我们提供能够拟合训练数据的最简单模型。

在之前的文章 “MultiClass Logistic Regression in Python” 中,分类器的最佳参数是通过最小化成本函数来确定的。我们计算了成本函数相对于参数的梯度。

由于在成本函数中添加了正则化项,成本函数的梯度将包含对应于 L2 范数梯度的附加项。

正则化项的第一个影响是成本函数。由于正则化项,成本函数将具有先验似然。
 

    def negative_log_likelihood(self,params):
        # args contains the training data
        x,y=self.args;
                 
        self.update_params(params);
        sigmoid_activation = pyvision.softmax(self.W,self.b,x);
        index=[range(0,np.shape(sigmoid_activation)[0]),y];
        p=sigmoid_activation[index]
        l=-np.mean(np.log(p));
        
        if self.Regularization==2:
            l=l+0.5*self.eta*np.sum(self.W**2);
        if self.Regularization==1:
            l=l+self.eta*np.sum(np.abs(self.W));
        
        
        return l;
下一个变化是梯度计算。
    """ function to compute the gradient of parameters for a single data sample """
    def compute_gradients(self,out,y,x):
        out=(np.reshape(out,(np.shape(out)[0],1)));                
        out[y]=out[y]-1;   
        W=out*x.T;
        if self.Regularization==2:
           W=W+self.eta*self.W;
        if self.Regularization==1:
            W=W+self.eta*np.sign(W);
        res=np.vstack((W.T,out.flatten()))
        return res;
其中 (i) 表示正在计算其导数的类。

基于L2正则化的优化很简单,因为添加的附加成本函数是连续且可微的。对于L1正则化,我们使用基本的次梯度法来计算导数。

首先,我们来看L2正则化过程。

L2正则化

正则化受正则化常数的影响。通常,通过尝试不同值来运行训练来经验性地确定常数。
.
较大的常数值会导致错误曲线很快趋于平缓,模型通常会表现出较低的准确性。然而,较小的值会导致执行大量迭代,并可能导致过拟合。

从下面的L2正则化曲线可以看出:
正则化参数=0.9                                        

   正则化参数=0.1

我们可以看到,当参数值为0.9时,学习在约40次迭代时达到18%的误差饱和;而当参数值为0.1时,学习在120次迭代时饱和,误差为15%。因此,正则化过程通常通过控制权重参数来防止学习算法对数据中的异常值做出响应。

因此,我们可以观察到固有的权衡。正则化阻止模型对数据变化做出响应,这反过来导致模型在准确学习所有可能的数据变化方面准确性较低。这就是偏差-方差权衡的情况。

偏差-方差权衡

偏差代表模型如何表示训练数据,方差代表模型如何响应数据变化。

如果不同的训练集导致非常不同的分类器,则方差很大。如果训练集对分类决策的影响很小,则方差很小。方差衡量了学习到的分类器的预测不一致性和本质上的变化。

高方差模型对噪声敏感,训练数据中的微小变化可能导致模型参数发生显著变化。

高偏差模型会产生简单的模型,这些模型不会过拟合,但可能欠拟合数据,无法捕捉数据中的变化。低偏差模型是复杂的,使它们能够准确地表示训练数据。

高方差模型会随着数据变化而出现大幅波动,它们很好地表示训练数据,但经常过拟合数据。低方差模型对数据变化不敏感,它们可以在存在噪声的情况下提供良好的泛化性能。

理想情况下,人们希望选择一个能够捕捉训练数据中的规律并能很好地泛化到未见过的数据的模型。然而,这并不总是可能的。通常存在偏差-方差权衡,许多机器学习算法试图控制这种权衡以获得良好的性能。

学习误差通常可以表示为偏差和方差之和。在最小化过程中,降低偏差通常会导致方差升高,反之亦然。权衡通常以选择具有高偏差和低方差的模型,或具有低偏差和高方差的模型的形式出现。复杂模型具有低偏差和高方差,而简单模型具有高偏差和低方差。理想情况下,我们希望模型具有低偏差和低方差。

正则化参数使我们能够控制偏差-方差权衡。较大的正则化参数值会降低方差。因为正则化在数据异常值的情况下提供了鲁棒性。参数的低值将导致正则化对学习没有影响。
因此,正则化为我们提供了降低方差的选择。基础学习算法负责提供高偏差。带有正则化的分类器可以提供一个良好且鲁棒的模型。

L1和L2正则化
我们可以观察到,与L2正则化相比,在相同迭代次数和相同正则化常数下,使用L1正则化可以获得更低的错误率。然而,即使学习算法收敛速度更快,错误率仍然高于不进行正则化的情况。

L2正则化                                                                L1正则化


总之,我们可以看到各种对抗过拟合的方法,以及它如何影响分类器的性能,以及正则化如何为我们提供控制模型方差的工具。

代码

具有正则化的逻辑回归分类器的代码可以在GitHub存储库中找到:
https://github.com/pi19404/OpenVision/tree/master/ImgML/PyVision
文件**LogsiticRegression.py**实现了带正则化的LogisticRegression分类器。
**Optimizer.py**实现了小批量随机梯度算法。
运行代码需要整个pyVision目录。运行LogisitcRegression.py文件将执行训练过程。
可以从以下位置下载:
© . All rights reserved.