第十四节过拟合解决手段L1和L2正则
第十三节中,我们讲解了过拟合的情形,也就是过度的去拟合训练集上的结果了,反倒让你的模型太复杂。为了去解决这种现象,我们提出用L1,L2正则去解决这种问题。
(相关资料图)
怎么把正则应用进去?我们重新审视目标函数,以前我们可以理解目标函数和损失函数是一个东西。而有正则的含义之后,目标函数就不再是损失函数了,而是损失函数加惩罚项。而这个惩罚项听起来好像是一个Optionally,一个可选项,但并不是,通常一定要加惩罚项,否则你训练出来模型极有可能是过拟合的。所以通常惩罚项是一定要加的,以前总讲线性回归一定要回归,一定要把损失函数降到最低,到今天你应该深刻地烙印在脑子里,它要降到最低的不光是损失函数,而是目标函数。
首先我们回忆机器学习的流程,先建立一个目标函数(在线性回归里面怎么建立的目标函数? 最大似然),然后找到使目标函数最小的一组W,就是我们要求的W。这一节以后我们目标函数变一变之前咱们说的线性回归的目标函数是:
其实这并不是完整版的目标函数,我们实际优化的也不光是它,而是变成了两项,损失项加上λ的正则项,
这个λ跟刚才学习率λ是两个不同的超参数。我们损失项的意义是要让训练集上的误差尽量小,而正则项的意义是让模型尽量简单,防止过拟合。目标函数其实就是损失函数和正则项线性相加,之前讲的目标函数只讲了损失项,损失项指的是什么?指的是我们的损失函数,虽然到目前为止我们只讲了一个MSE损失函数,但实际上你应该举一反三,虽然你不知道其它损失函数长什么样,但你知道会有各种各样的损失函数,只要这个损失函数降到最低了,我们这会儿运算出来的模型,就是我这个算法得到的最终结果。接下来介绍什么叫正则项,我刚才说的防止它一味的去追求损失函数最低而导致模型变复杂了,我们看目标函数的这么一个形式,
,虽然这么花里胡哨,但最终还是要把它交给SGD的算法去最优化。我机器还是傻乎乎的,你让我最优化损失函数,我就最优化损失函数,你不想让我光追求最优化损失函数,那你交给我点其他的东西,我也会一起帮你优化。我们最终是想让损失函数相对较小的时候,模型也相对简单,所以我们就看着Ω(θ)它应该具有一个什么样的特征?模型越复杂的时候Ω(θ)会越大,模型也简单的时候Ω(θ)就越小。举个例子来理解相对概念,比如当损失项函数的最小值是0.18,结果当0.18的那组θ带到模型评估的函数Ω(θ)里面,发现Ω(θ)值是20,此时是不是模型太复杂了? 当你损失函数上升了一点,上升到0.19的时候,θ虽然它已经不是最优解了,但此时发现这组θ带入到Ω(θ)里面,20直接降到了5,此时机器会选择哪种模型?第一组θ还是第二组θ?应该是第二组θ,因为它达到了一个在损失函数尽量小的同时,你要让我的模型尽量的简单。
λ是干嘛的?λ是评估你到底多看重模型的简单性的。假如刚才这个例子,λ设成0.0000001,对它来说你虽然从20减到了5,但是你乘的系数很少,你的简单在它眼里看起来它并不在乎,比如你在公司你自我陶醉一般的做了很多工作,老板可能并不在乎。这就是说你这个模型到底有多看重模型复杂程度的惩罚的。为什么管它叫惩罚项,正则项也叫惩罚项,它是一个惩罚系数,你追求到了损失函数是0.18,但是你把这个模型搞复杂了,我就要惩罚你一下,给你加上一个惩罚项Ω(θ)为20,假如你损失函数是0.19了,你的惩罚性Ω(θ)就变小了,总体的效果会变好,也就是说正则项实际上是达到了一个为了追求损失函数最小而把模型搞复杂了去惩罚的这种情况。 这种情况发生了,我就要惩罚你,我让你损失函数不再是最优的了,就不会最后出现模型给你选出来一个损失函数是最低的,但是复杂度一下上升了好多的这种情况。
怎么样评估这个模型复不复杂?我们回忆下参数型模型的本质是什么?是不是就那一组W,所以也只能从这一组W上来评估,没别的东西了。所以我们现在来探索评判模型的复杂度的Ω(θ)到底是什么?其实它非常简单,对于线性模型如何评估复杂程度,通常通过L0范数L1范数和L2范数,范数的值越大,该模型越复杂。
咱们讲一下什么叫L0范数,L1范数和L2范数?L0范数,所有参数W中非零元素的个数。比如100个维度里边有80个没有用,它是怎么判定没用的?是不是直接把W调成0了? 那W里边的零越多,这个模型就越简单,所以非零元素的个数越多,代表模型越复杂,因此L0范数可以作为我刚才Ω(θ)的一个候选人。假如Ω(θ)是L0的话,你有一个W是0.1,你直接给它减成0了,发现损失函数就上升了一点点,但是你就直接少考虑了一个维度,所以能一定程度上阻止你的过拟合,因为这个维度,我彻底不考虑了,这个是L0范数的作用,但是L0范数不可导,不能求导有什么麻烦?梯度下降没法工作。你要想做梯度下降,老得求负梯度,你一求负梯度就发现这个家伙求不了。梯度下降这个东西你用不上了,所以通常我们不用L0范数作为Ω(θ)项。
因此Ω(θ)我们改为用L1范数,L1范数是所有参数的绝对值之和(也称L0的最佳凸近似)。
,这个话理解成它是L0的方便计算的替代品,它能达到跟L0差不多的效果,让大多数没什么用的这些W变为零,但是它又可导,能交给梯度下降来做。 假如损失函数是MSE,加上L1正则后|,你再去优化交给SGD的东西,就不再是原来的MSE函数了,而是MSE+0.1*Σ|W让它一起去做优化,优化出来的结果会是什么样的? 优化出来的结果会有相当一部分的W变为了0。所以通常分类任务也好,回归任务也好,我们说特征太多,这些特征好麻烦,我也不知道哪个有用,哪个没用,你就可以,你直接给他加一个L1范数跑一下,哪些W是零了,那些特征就直接去掉。能够筛选掉那些W为0的特征,一定是没有它也不会引起损失函数巨大上升的那些特征。比如我刚才举那个例子,张三家关没关窗户,对于下雨的影响,它一定本身不大。 你加了一把L1正则训练出来模型之后,就会发现张三家关没关窗户这一列的属性的权重变为了零,如果加了L1正则它还不是零,说明从数据集上来看,这一列就是对下雨影响很大。但是可能发生吗这种事?明显不可能,说明什么?说明你收集的数据绝对不够多。或者你收集的数据不是全部的数据,是张三给你的数据,他一收集就老要打开窗户看下雨,经常会有这种荒唐的事发生。比如你发现你怎么跑模型? 这个模型效果都不好,很可能是你收集上的这些数据本身就已经被筛选过了。比如你拿你用户数据的时候,你发现有一列的值只有安卓手机能提供给你,iPhone提供不了,所以你的数据就是一个有偏斜的数据,经过一次预筛选了,像我刚才讲的故事,张三一看下雨他就把窗户打开了,因果反制,所以你收集的数据只收集到了他们家开窗户的时候的数据,数据本身是有问题的。因此我们加上L1正则后,发现一些明显跟你的最终结果不应该有关系的数据还有了关系,那说明这个数据本身有问题。这也是一个检验数据的一种方式。所以通常L1范数是用来做特征选择的。
我们对比下L0和L1:L0和L1都可以使参数稀疏。所谓稀疏化就是0比1多,假如你给了我200个数,我发现里边只有三个数不为零,你接记下这三个数的大小和三个数的位置就可以存下来了,而不用真把这200个数存下来,这其实是一个稀疏向量。所以使参数稀疏化,也就让不重要的那些维度的参数归为0,重要的会更偏向为1。L1范数比L0范数有一个优点,它是可微可导的,功能又类似,所以只选择L1范数,而基本没有见过用L0范数的,L1想做的事是尽量的让没用的特征变成零,因此L1的意义是特征选择,与此同时增强了模型的解释性,模型解释性是非常重要的一个事儿。 比如有一个业务场景,有一天银行来找到你了,说我们想训练一个模型,做一个客户还款能力的预测,丢给你一堆数据,你最后确实做出来一个模型,我问你这个东西好用不好用,你心里也没底,你去交活的时候,你说我们这400多个特征全用上了,连客户今天穿没穿花衣服都有,你能跟客户交差,说你这模型真有用吗?不能够的,你一定要把参数的量减下来,给她去解释,为什么这个东西在里面,你看这个模型确实让人更放心,让客户也有信心,你权重是高是低还好,你最终八竿子打不着的东西都抄进来了,明显这个模型是有问题的,是有缺陷的。所以模型的解释性不是一个没有意义的事儿,他一定要能解释得通这个东西才敢上线去生产,一定不能跟你的常识都是违背的,如果你发现跟你常识违背的模型,你一定要去经过实验来看看是不是真的有用,如果真有用了,这个东西叫知识发现,代表你发现了一个新的相关的指数,代表你有一个新的知识发现,但大部分情况下八竿子打不着的那些特征,通常一定是没有用的,一定是哪里有错了。你应该去考虑,所以L1有特征选择和增强模型解释性的功能。如果有些维度被你训练的时候,机器给它加了很大权重,但是只能让损失函数降低一点点,那么很有可能会产生了过拟合现象,因此我们要惩罚那些带不来什么提高又浪费了好多资源的这种权重。举个例子,比如你们家本来吃饭空间就有限,一哥们不干活,天天还在你们家吃饭,占用了大量的资源,但最后他也没说没贡献,他每个月贡献给你一毛钱,你觉得这个容忍你还要吗?,你为了挣这一毛钱还不够我给你收拾碗筷的。这个也一样,你为了提升那一点点损失函数,还不够你给我模型增加复杂度的带来的过拟合风险,所以我选择不要这个维度了。
我们再来讨论下L2正则,定义是L2范数的平方。什么叫L2范数?假如有a,b,它俩的L2范数就是
。假如你有一组W,W的L2范数就是
,这个东西定义为L2范数,通常写作
,这个就像一个运算符一样,代表了这种运算。那么L2范数的平方是我们的L2正则,因为又一次平凡,所以就把L2范数的根号给去掉,你就会看到,它实际上是把所有的W的平方给加合起来。也就是L2正则表达式:
,什么情况下这个值会大?W普遍比较大的时候,这个情况会大,或者说W的绝对值比较大的时候,这个情况会大。 当模型把好多的权重都认为比较重要的时候,这个东西是不是会变大?而且会越重要,大的越厉害,惩罚的越厉害。因此,把L2正则加上又会发生什么?它会想做到尽量的把W给压缩小一点,但是它不是每种W都压缩,它会优先压缩那些特别大的W优先,因为这些W对正则项带来的提升是越好的,让正则项变得越小,所以会优先压缩那些最大的W,然后真正特别重要的W,它权重也会很大,这种东西也被压缩了。 这是我们想要的结果吗?明显不是。你会发现我优化的时候不是单独用一个正则项,在前面还加着损失项,所以它一定会压缩那些又大又没什么用的那些W。所谓有用没用怎么评估?就是你W变一变损失函数根本没发生什么改变的情况下,这种W是不是又大又没用?他会优先的把这些又大又没用的W给尽量压小,防止模型去过拟合。因此L2正则。默认一定是要带上的,很明显不带任何惩罚项的损失函数根本就不能用。 它光追追求训练集上发热损失函数最小了,因为一丝不苟地只追求最小,它无论付出多大的代价,都要最小,因此一定会过拟合。所以在实际情况中一定会带上L2正则。因此我们的目标函数obj里面永远是两项,第一项是loss,第二项是L2,这个是防止过拟合的。我们总结下L2范数的作用,它是会使所有的W的绝对值都相对变小,而不会变到零,让大家都小一些,特别重要的权重小的比较少,不太重要的权重往下减的多一点,它的作用就是抵抗过拟合。如果训练出来的权重代表这一个特征对最终结果影响的重要性,由于我们观察到的特征一定不是完备的,“强迫”算法用并不完备的观察特征尽全力去拟合训练集,一定会将一些训练集中的巧合作为规律习得,然而这些巧合并不一定在未来预测时也会出现,因此这就是过拟合现象。我们要把这种现象去掉或者减少,就是通过正则去抵抗过拟合。
下一节中我们讨论L1正则和L2正则的区别。