🐋正则化
2021-11-15
| 2023-8-6
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
和普通的机器学习算法一样,DNN也会遇到过拟合的问题,需要考虑泛化
 

模型复杂性

notion image
notion image

代码

用以下三阶多项式来生成训练和测试数据的标签:
notion image
notion image
 
 
notion image
notion image
 
 
notion image
notion image
 
 
 
训练数据集中的样本越少,就越有可能(且更严重地)遇到过拟合。随着训练数据量的增加,泛化误差通常会减小。⼀般来说,更多的数据不会有什么坏处。对于固定的任务和数据分布,模型复杂性和数据集⼤小之间通常存在关系。给出更多的数据,可能会尝试拟合⼀个更复杂的模型。能够拟合更复杂的模型可能是有益的。如果没有⾜够的数据,简单的模型可能更有⽤。对于许多任务,深度学习只有在有数千个训练样本时才优于线性模型。
 
 
 
 

DNN的L1&L2正则化(权重衰退)

L1正则化和L2正则化原理类似,这里重点讲述DNN的L2正则化。
DNN的L2正则化通常的做法是只针对与线性系数矩阵 ,而不针对偏倚系数
假如每个样本的损失函数是均方差损失函数,则所有的 个样本的损失函数为:
则加上了L2正则化后的损失函数是:
其中, 即我们的正则化超参数,实际使用时需要调参。而为所有权重矩阵的所有列向量
如果使用上式的损失函数,进行反向传播算法时,流程和没有正则化的反向传播算法完全一样,区别仅仅在于进行梯度下降法时, 的更新公式。
回想未加L2正则 的梯度下降更新公式为:
则加入L2正则化以后,迭代更新公式变成:
注意到上式中的梯度计算中 忽略了,因为 是常数,而除以 也是常数,所以等同于用了新常数 来代替 。进而简化表达式,但是不影响损失算法。
类似的L2正则化方法可以用于交叉熵损失函数或者其他的DNN损失函数。

代码

生成一些数据,生成公式如下:
为了使过拟合的效果更加明显,我们可以将问题的维数增加到, 并使用一个只包含20个样本的小训练集

从零开始实现

notion image
notion image
notion image
notion image
 

简洁实现

由于权重衰减在神经网络优化中很常用,深度学习框架为了便于使用权重衰减,便将权重衰减集成到优化算法中,以便与任何损失函数结合使用。此外,这种集成还有计算上的好处,允许在不增加任何额外的计算开销的情况下向算法中添加权重衰减。由于更新的权重衰减部分仅依赖于每个参数的当前值,因此优化器必须⾄少接触每个参数⼀次。
下⾯的代码,在实例化优化器时直接通过weight_decay指定weight decay超参数。默认情况下,PyTorch同时衰减权重和偏移。这里只为权重设置了weight_decay,所以bias参数b不会衰减。
 
 

DNN通过集成学习的思路正则化

除了常见的L1&L2正则化,DNN还可以通过集成学习的思路正则化。集成学习有Boosting和Bagging两种思路。而DNN可以用Bagging的思路来正则化。常用的机器学习Bagging算法中,随机森林是最流行的。它通过随机采样构建若干个相互独立的弱决策树学习器,最后采用加权平均法或者投票法决定集成的输出。在DNN中,一样使用Bagging的思路。不过和随机森林不同的是,我们这里不是若干个决策树,而是若干个DNN的网络。
首先我们要对原始的m个训练样本进行有放回随机采样,构建 个样本的数据集,然后分别用这N组数据集去训练我们的DNN。即采用我们的前向传播算法和反向传播算法得到 个DNN模型的 参数组合,最后对N个DNN模型的输出用加权平均法或者投票法决定最终输出。
不过用集成学习Bagging的方法有一个问题,就是我们的DNN模型本来就比较复杂,参数很多。现在又变成了 个DNN模型,这样参数又增加了N倍,从而导致训练这样的网络要花更加多的时间和空间。因此一般 的个数不能太多,比如5-10个就可以了。
 
 
 

DNN通过dropout 正则化

和Bagging类似但是又不同的正则化方法:Dropout
所谓的Dropout指的是在用前向传播算法和反向传播算法训练DNN模型时,一批数据迭代时,随机的从全连接DNN网络中去掉一部分隐藏层的神经元。
比如我们本来的DNN模型对应的结构是这样的:
notion image
在对训练集中的一批数据进行训练时,我们随机去掉一部分隐藏层的神经元,并用去掉隐藏层的神经元的网络来拟合我们的一批训练数据。如下图,去掉了一半的隐藏层神经元:
notion image
然后用这个去掉隐藏层的神经元的网络来进行一轮迭代,更新所有的 。这就是所谓的dropout。
当然,dropout并不意味着这些神经元永远的消失了。在下一批数据迭代前,会把DNN模型恢复成最初的全连接模型,然后再用随机的方法去掉部分隐藏层的神经元,接着去迭代更新。当然,这次用随机的方法去掉部分隐藏层后的残缺DNN网络和上次的残缺DNN网络并不相同。
 
总结下dropout的方法: 每轮梯度下降迭代时,它需要将训练数据分成若干批,然后分批进行迭代,每批数据迭代时,需要将原始的DNN模型随机去掉部分隐藏层的神经元,用残缺的DNN模型来迭代更新 。每批数据迭代更新完毕后,要将残缺的DNN模型恢复成原始的DNN模型。
从上面的描述可以看出dropout和Bagging的正则化思路还是很不相同的。dropout模型中的 是一套,共享的。所有的残缺DNN迭代时,更新的是同一组 ;而Bagging正则化时每个DNN模型有自己独有的一套 参数,相互之间是独立的。当然他们每次使用基于原始数据集得到的分批的数据集来训练模型,这点是类似的。
使用基于dropout的正则化比基于bagging的正则化简单,这显而易见,当然天下没有免费的午餐,由于dropout会将原始数据分批迭代,因此原始数据集最好较大,否则模型可能会欠拟合。

代码

从零开始实现

notion image
notion image
 
 

简洁实现

对于深度学习框架的高级API,我们只需在每个全连接层之后添加一个Dropout层, 将暂退概率作为唯一的参数传递给它的构造函数。 在训练时,Dropout层将根据指定的暂退概率随机丢弃上一层的输出(相当于下一层的输入)。 在测试时,Dropout层仅传递数据。
 
 
 

DNN通过增强数据集正则化

增强模型泛化能力最好的办法是有更多更多的训练数据,但是在实际应用中,更多的训练数据往往很难得到。有时候我们不得不去自己想办法能无中生有,来增加训练数据集,进而得到让模型泛化能力更强的目的。
对于我们传统的机器学习分类回归方法,增强数据集还是很难的。你无中生有出一组特征输入,却很难知道对应的特征输出是什么。但是对于DNN擅长的领域,比如图像识别,语音识别等则是有办法的。以图像识别领域为例,对于原始的数据集中的图像,我们可以将原始图像稍微的平移或者旋转一点点,则得到了一个新的图像。虽然这是一个新的图像,即样本的特征是新的,但是我们知道对应的特征输出和之前未平移旋转的图像是一样的。
举个例子,下面这个图像,我们的特征输出是5。
notion image
我们将原始的图像旋转15度,得到了一副新的图像如下:
notion image
我们现在得到了一个新的训练样本,输入特征和之前的训练样本不同,但是特征输出是一样的,我们可以确定这是5.
用类似的思路,我们可以对原始的数据集进行增强,进而得到增强DNN模型的泛化能力的目的。
  • PyTorch
  • 多层感知机的实现K折交叉验证
    目录