神经网络的提升方法(2)——正则化

过拟合
过拟合是一个普遍存在的问题,尤其是在神经网络领域,神经网络模型动辄都有上万个参数,现代的深度网络参数则更是上百万的参数,所以深度网络更容易出现过拟合现象。
过拟合现象主要体现在accuracy rate和cost两方面:
1.模型在测试集上的准确率趋于饱和而训练集上的cost仍处于下降趋势
2.训练集数据的cost趋于下降但测试集数据的cost却趋于饱和或上升
我们经常用test data来测试模型的质量和测试过拟合现象,但是其实也可以把数据集分成训练集(training data),测试数据(test data)以及验证数据(validation data)并且使用验证数据来代劳。跟测试数据的做法一样,我们使用验证数据对训练过程进行监督,只要验证数据准确率达到饱和了,训练就停止,这种方法叫做early stopping。
那么为什么要用验证数据而不是测试数据呢?这个问题似乎没办法解答。其实这是一个很普遍的做法,因为验证数据经常被用于模型选取超参数,而测试数据通常被用于测试训练了权值并且设定好超参数的模型。原文作者的说法是因为,如果测试数据测试了模型效果,并且又基于这个数据集去调整超参数,这样很容易会使得模型去特别测试数据从而降低泛化能力。因此,通常我们都使用验证数据集去测试超参数的影响而使用测试数据集去评判最终模型的结果,这种方法又称为hold out,因为验证数据集可以被视为从训练数据hold out出去的一部分专门用于调参的数据。

正则化
过拟合现象很普遍,根本原因还是数据量不足以支撑复杂度高的模型,因此最直接的解决过拟合问题的办法是增加训练数据量。但要获得带标签的数据成本是很高的。另一种直接的办法是降低模型复杂度,这看起来可行,但是复杂度高的模型往往有很大的潜力去解决更复杂的问题,或者比简单的模型有更好的效果,这一点,resNet似乎已经证明过了。所以,增加数据量和降低模型复杂度都不是很好的办法。
如果我们能在固定训练集大小和固定模型复杂度的情况下解决过拟合问题,那就真是太好了,幸运的是我们已经找到了这种办法,它就是正则化。首先要介绍的就是最常用的L2正则化或者叫权值衰减(weights decay),就是在原本的损失函数基础上加上一个惩罚项。

C0可以是任意的普通损失函数,w是模型里面的所有权值,而 λ是正则化参数,它必须大于0(当然也可以认为等于0就是纯粹经验风险损失的情况)。
正则化损失函数(通常也叫结构化损失)综合考虑了模型效果和模型复杂度,这两者的权衡由正则化参数λ来衡量,即如果λ很小,那么结构化损失更倾向考虑模型效果,相反,则更倾向于惩罚复杂的模型。结构化损失函数的目的是要使模型里面的权值变小从而达到避免过拟合现象发生。
那么,带有惩罚项的损失函数怎么训练呢?要解决这个问题,我们先要知道结构化损失函数关于权值和偏置值的偏导数∂C/∂w和∂C/∂b。

这个求导不难理解,∂C/∂w相当于在原来的基础上加上了个λ/n*w,而∂C/∂b则没有任何变化。那么,权值和偏置值的更新规则就分别是


这个更新规则跟非正则化的情况没啥特别——偏置值的更新是一样的,因为它的偏导数没有变化;而权值则是相当于乘上了一个1−ηλ/n,这也是为什么说正则化情况下权值会变小。
更新规则我们知道了,但是SGD中怎么处理呢?
考虑我们是通过一个大小为m的mini-batch,跟非正则化的情况一样,我们会对m个训练集的偏导数求平均,再乘上η作为Δw:

我们已经知道,正则化是减轻过拟合现象的一个好方法,但这并不是它唯一的好处。如果我们使用非正则损失函数,模型表现可能会卡在一个局部极小值里,并且我们可能会从不同的初始化权值获得截然不同的结果,但如果使用L2正则化,这样训练出来的结果往往有鲁棒性。
正则化对减轻过拟合现象的原因可能很不明显,但如果要简要的去说明,那么我们只能说:由于正则项的存在,使得模型的权值趋于衰减,由于权值普遍的衰减,甚至有部分的权值接近于0,这样就相当于模型的复杂度得到降低。
那么问题又来了,为什么模型复杂度低就会减轻过拟合现象呢?
举个很简单的例子,我们用一些如下图很简单数据去拟合一个模型。我们可以选择用一个简单的线性回归模型或一个9次多项式模型。我们虽然很难从拟合出来的结果去说明哪个模型更好——直观上,因为9次多项式几乎完美的拟合了所有数据点,但线性回归方程也有很不错的表现,不能完美拟合可能只是随机变动的噪音造成的。但是,9次多项式回归过于充分得考虑每个数据点的情况了,甚至乎它已经把局部噪音的特征都学习到了,以致它很难推广到别的数据集中。相对之下,简单得多的线性回归模型不仅已经很不错的拟合了数据集,还可以有对其他数据有很好的泛化能力。

让我们回到神经网络,如果我们用L2正则化去压缩权值,很小的权值就意味着输入数据的改变并不会对网络输出有很大的影响,这样的网络也很难会受局部噪音的影响,相反,较大的权值则会对很小的输入变化有较敏感的改变。因此,非正则化网络会通过较大的权值去学习更复杂的模型(相对较小权值模型来说)从而考虑了训练数据中的噪音成分,而正则化网络因其更小的权值,避免训练数据中噪音的影响,专注于数据现象的学习从而有更好的推广能力。
人们通常把倾向于简单模型的准则成为“奥卡姆剪刀”,但这在科学研究中并不成文,因为我们没有很好的逻辑去解释简单比复杂要好,而有时,复杂真的会比简单要好。·这一点,作者用了好几个故事去说明,这里就不介绍了。
既然我们也没办法知道到底模型是复杂好还是简单的好,那么正则化为什么通过降低模型复杂度就能获得更好的泛化能力呢?这点看起来是没有很好的道理,但很多学者正在致力于探究这个问题背后的原因。而我们其实只需要把它作为一种经验就好了,因为通常正则化的神经网络都会比非正则化的有更好的表现。
我们把权值的平方和用作为惩罚项,为什么不用偏置值呢?这是因为从经验上来说,偏置值的大小对模型表现没有很显著的影响,换句话说,即便把偏置值加入到惩罚项里面做正则化,最后模型的泛化能力也不会得到很明显的提升。所以,即便网络中采用了很大的偏置值,我们也不必担心网络会去学习到训练数据中的噪音。
除了L2正则化之外,其实还要很多种正则化方法,但接下来,我们只会专注于其中三种除L2以外的正则化方法:L1正则化、DropOut和人工增加训练数据大小。
L1正则化是一种与L2正则化很相似的方法,在正则化损失函数中唯一区别在于惩罚项是网络所有权值的绝对值之和而不是平方和。

直观上,它的目的跟L2正则化也是一致的:惩罚过大的权值,把网络权值尽量往小的修改。但是L2和L1毕竟是两种不同的正则化,它们的表现也是会有所不同的。
首先,L1正则化C对w的偏导数为:

注:abs(w)的导数为sign(w),即上式的sgn(w)——当w为正时,偏导数为1,w为负时则为-1
通过这个表达式,我们可以得到在梯度下降算法中权值更新规则:

对比一下L2正则化中的更新规则:

就很明显可以看出,两者还是有较为明显的区别,但直观上,两者共同点是都在压缩着权值。
然而,两者对权值的压缩是不一样的:L2正则化只是对权值以一定的比例打折,而L1正则化却是使权值通过减去一个常数去朝着0削减。而当|w|很大时,L2对权值减少的幅度要远大于L1,相反,当|w|很小时,L1对权值的衰减又远大于L2。通过L1正则化,网络最终的结果会变为只保留对模型结果很重要的权值,而其他不重要的权值变为0。
另外有一点值得注意,由于函数|w|在w=0的时候是一个尖角,因此∂C/∂w在此时不可导,所以,在SGD训练过程中,w一旦被缩减到0就不能继续缩减了。更精确一点说,当|w|在w=0时,其导数sign(w)=0,因此权值不会被更新。
Dropout相对于L1,L2而言,则是一种更为暴力的正则化方法。L1,L2根本方式都是在损失函数上增加一个惩罚项,使得模型在训练的过程中对高模型复杂度也进行惩罚,但Dropout是不通过损失而直接对网络本身进行修改。下面我们来用网络结构图说明Dropout的工作方式。
假设我们要训练一个这样的网络:

在训练的开始,我们随机的并临时的以某一个概率让部分神经元激活值直接设置为0:

我们就这样利用输入数据前向通过这个被修改的网络,再反馈误差信号,结果只有被保留下来的权值和偏置值会被更新。在每个mini-batch,我们都重设要dropout的神经元,并再用数据通过网络估计出梯度,再修改响应的权值、偏置值。
通过一个一个mini-batch的执行这样的网络训练,我们最后会得到一些基于dropout训练出来的权值和偏置值,而我们在使用全连接网络的时候,假如dropout概率为0.5,实质上我们激活了相当于两倍数量的神经元。由于训练过程中我们只需要用大约一半的神经元就能得到期望输出接近的结果,如果使用两倍神经元的话则输出值会大大偏离了我们的期望输出,因此需要对权值进行减半。当然这里只举了dropout概率为0.5的情况,其他概率的情况也大致如此。
Dropout看起来很奇怪,当然一开始接受也很难理解其中的道理。首先我们把dropout放在一边,假设我们用同一批数据去训练五个不同的网络,因为初始化的随机性,所以五个网络从开始到结束都会有所不同,最后我们会通过多数表决或者对输出的各个类的概率取平均的方法得到最终的结果。因为不同网络可能会有不同的过拟合问题,但把它们综合到一起考虑,这种问题可能会被弱化甚至消除。
那Dropout跟这个有什么关系呢?事实上,当我们每个mini-batch随机的丢弃一些神经元,我们就相当于在训练不一样的网络,dropout方法就相当于我们综合考虑大量网络的情况,所以我们可以通过dropout来减少过拟合的影响。
Dropout是一种很成功的神经网络提升技术,尤其是在庞大的、深度的神经网络训练任务中——因为过拟合问题特别严重。这种技术也被实证过是有效提升网络效果的,并且被广泛用于不用的场合以及不同的任务中。
最后,我们讨论一下人工扩展训练数据
其实我们都应该清楚,所谓的“模型复杂度高”都是相对于训练集而言的,其本身并没有一个标准。假如用只有150条样本的iris数据集作为模型训练,那么使用一个只有200个权值的网络也会过拟合,而这个网络假如能被应用到拥有5万条记录的MNIST数据集的话,则很大可能是过于简单了。
其实并不难想象,对于一个固定的网络而言,更大量的训练数据通常会获得更好的结果——因为更大量的训练数据意味着考虑到更多的信息。就以MNIST为例,数字可以有无数种手写体写法,我们仅以其中的1万种作为训练很可能考虑不到更多的情况,尤其是对于有特殊写作癖好的人。但随着训练数据的增多也就意味着网络考虑了更多种手写字体的写法,网络的泛化能力也就更强。
所以增加训练数据是最直接的解决过拟合问题的方法。但不幸的是,增加真实的带标签的训练数据是需要很高成本的,因此很少在实践中直接去寻找更多的训练数据。我们虽然很难获得更多很好的训练数据,但我们可以通过人工的方法去扩展数据量。
例如我们在MNIST数据集中有一个“5”:

然后我们通过对其旋转15°,它依然是那个“5”:

即便如此,两张图在像素点灰度值的分布上确实有很大的区别,这样就变成了一张新的图片。利用这种方法,我们可以对训练集上所有的样本都作不同角度的选择,这样就可以获得大量的训练数据,从而提高模型分类准确率。增加训练样本可以通过很多其他办法,并不单只是角度的旋转,还可以通过扭曲或者添加随机噪音等方法,不管怎样,通常增加训练样本量都是一个不错的方法。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章