L2正则化为什么能够使得模型更简单?全是因为

204 阅读10分钟

跟我一起机器学习系列文章将首发于公众号:月来客栈,欢迎文末扫码关注!

从上一篇文章的介绍可以知道,模型产生过拟合的现象表现为:在训练集上误差较小,而在测试集上误差较大。并且笔者还说到,之所以产生过拟合现象是由于训练数据中存在一定的噪音,而我们为了尽可能的做到拟合每一个样本点(包括噪音),往往就会使用复杂的模型。最终使得训练出来的模型很大程度上受到了噪音数据的影响,例如真实的样本数据可能更符合一条直线,但是由于个别噪音的影响使得训练出来的是一条弯曲的曲线,从而使得模型在测试集上表现糟糕。因此,我们可以将这一过程看作是糟糕的训练集导致了糟糕的泛化误差。但仅仅从过拟合的表现形式来看糟糕的测试集(噪音多)也能导致糟糕的泛化误差。接下来,本篇文章就分别从这两个角度来介绍一下**正则化(regularization)**方法中最常用的L_2正则化是如何解决这个问题的。

1 正则化

以线性回归为例,假设现在我们给线性回归的目标函数后面再加上一个L_2正则化项,看看会发生什么样的变化:

\begin{aligned}
J&=\sum_{i=1}^m\left(y^{(i)}-(\sum_{j=1}^nx^{(i)}_jw_j+b)\right)^2+\color{red}{\frac{\lambda}{2n}\sum_{j=1}^n(w_j)^2}\color{black};\;\;(\lambda>0)
\end{aligned}\tag{1}

公式(1)中的红色部分便是我们新加入的L_2正则化项,它有什么作用呢?根据先前的介绍可以得知,当真实值与预测值之间的误差越小(表现为损失值趋于0),也就代表着模型的预测效果越好,并且可以通过最小化目标函数来达到这一目的。由公式(1)可知,为了最小化目标函数J,红色项的结果也必将逐渐的趋于0。这使得最终优化求解得到的w_j均趋于0附近,进而得到一个平滑的预测模型。那这样做的好处是什么呢?

1.1 糟糕的测试集导致糟糕的泛化误差

所谓糟糕的测试集导致糟糕的泛化误差是指:训练集本身没有多少噪音,但是由于测试集含有大量噪音,使得训练出来的模型在测试集上没有足够的泛化能力,而产生了较大的误差。这种情况可以看作是模型过于准确而出现了过拟合现象。那正则化方法是怎么解决这个问题的呢?

假如式子(2)就是根据(1)中的目标函数训练得到的预测模型:

y=\sum_{j=1}^nx_jw_j+b\tag{2}

现在新输入样本(含噪声)的某个特征维度由训练时的x_j变成了现在的(x_j+\Delta x_j),那么其预测输出就由训练时的y变成了现在的y+\Delta x_jw_j,即产生了\Delta x_jw_j的误差。但是,由于w_j接近于0附近,所以这使得最终只会产生很小的误差。且如果w_j越是接近于0,产生的误差就越小,也就意味着模型越能够抵抗噪音的干扰,一定程度提升了模型的泛化能力[1]。

由此便可以知道,通过在原始目标函数中加入正则化项,便能够使得训练得到的参数趋于平滑,进而能够使得模型对噪音数据不再那么敏感,缓解了模型过拟合的现象

1.2 糟糕的训练集导致糟糕的泛化误差

所谓糟糕的训练集导致糟糕的泛化误差是指:由于训练集中包含有部分噪音,我们在训练过程中为了能够尽可能的最小化目标函数而使用了较为复杂的模型,使得最终得到模型并不能在测试集上有较好的泛化能力。但这种情况就完全是因为模型不准确而出现了过拟合的现象,这也是最常见的过拟合原因。那L_2正则化方法又是怎么解决在训练过程中就能够能够降低对噪音数据的敏感度的呢?为了便于后面理解,我们先从图来直观理解一下正则化到底对目标函数做了什么。

如图所示,左右两边红色曲线为原始目标函数,蓝色曲线为加了L_2正则化后的目标函数。可以看出红色曲线的极值均发生了改变,也就是产生极值的极值点均发生了改变,且不约而同的都更靠近原点了。再来看一张等高线的投影图:

图中红色曲线同样为原始目标函的等高线,蓝色曲线为施加正则化后目标函数的等高线。可以看出,目标函数的极值点同样发生了变化,从原始的(\frac{1}{2},\frac{1}{2})变成了(\frac{1}{16},\frac{1}{4}),而且也是更靠近原点(w_1,w_2变得更小了)。到此我们似乎可以发现,**正则化具有能够使得原始目标函数极值点发生改变,且同时还有使参数变小的作用。**事实上正是因为这个原因才使得正则化具有缓解过拟合的作用,但原因在哪儿呢?

以目标函数J_1 = \frac{1}{6}(w_1 - \frac{1}{2})^2 + (w_2 - \frac{1}{2})^2为例,其取得极值的极值点为(\frac{1}{2},\frac{1}{2}),且J_1在极值点处的梯度为(0,0)。当对其施加正则化R=(w_1^2+w_2^2)时,由于R的梯度方向是远离原点的(因为R为一个二次曲面),所以给目标函数加上正则化,实际上就等价于给目标函数施加了一个远离原点的梯度[2]。说得通俗点就是,正则化给原始目标函数的极值点施加了一个远离原点的梯度(甚至可以想象成是施加了一个力的作用)。因此,这也就意味着对于施加正则化后的目标函数J_2=J_1+R来说,J_2的极值点(上图蓝色圆点)相较于J_1的极值点(上图红色原点)更加的靠近与原点。而这也就是正则化本质之处。做完了铺垫,下面进入正题:

假如有一个模型A,它在含有噪音的训练集上表示异常出色,使得目标函数J_1(\hat{w})的损失值等于0(也就是拟合到了每一个样本点),即在w=\hat{w}处取得了极值。现在,我们在J_1 的基础上加入了正则化项构成新的目标函数J_2,然后我们来分析一下通过最小化J_2求得的模型B到底产生了什么样的变化。

\begin{aligned}
J_1&=\sum_{i=1}^m\left(y^{(i)}-(\sum_{j=1}^nx^{(i)}_jw_j+b)\right)^2\\[2ex]
J_2&=J_1+\color{red}{\frac{\lambda}{2n}\sum_{j=1}^n(w_j)^2}\color{black};\;\;(\lambda>0)
\end{aligned}\tag{3}

由于J_2是由J_1加正则化项构成,同时根据先前的铺垫可知,J_2将在离原点更近的极值点w=\tilde{w}处取得J_2的极值,也即是通过最小化含正则化项的目标函数J_2,我们将得到w=\tilde{w}这个最优解。但是请注意,此时的w=\tilde{w}将不再是J_1的最优解,即J_1(\tilde{w})\neq0。因此通过最小化J_2求得的最优解w=\tilde{w}将使得J_1(\tilde{w})>J_1(\hat{w}),而这就意味着模型B比模型A更简单了,也就代表着从一定程度上缓解了A的过拟合现象。

同时,由公式(1)可知,通过增大参数\lambda的取值则可以增大正则化项对应的梯度,而这将使得最后求解得到更加简单的模型(参数值更加的趋近于0)。也就是**\lambda越大,一定程度上越能缓解模型的过拟合现象**。因此,参数\lambda又叫做惩罚项或者惩罚系数。最后,从上面的分析可知,在第一种情况中正则化可以看作是使得训练好的模型不再对噪音数据那么敏感;而对于第二种情况来说,正则化则可以看作是使得模型不再那么复杂。但其实两者归结起来都是一回事儿,那就是通过较小的参数取值,使得模型变得更加简单。

1.3 简单模型

通过上面的介绍,现在我们已经知道了L_2正则化是如何来简化模型的。但是有的朋友可能还存在着一个疑惑(或者误解):认为高次数多项式表示的模型一定比低次数多项式表示的模型复杂,例如5次多项式就要比2次多项式复杂,而这是错的[3]。高次项代表的是更大的模型空间,其中既包含了复杂的模型,也同时包含了简单的模型。而我们只需要将复杂模型对应位置的权重参数调整到更接近于0,就可以将其进行简化。

2 参数更新

在给目标函数施加正则化后也就意味着其关于参数的梯度发生了变化,幸运的是正则化是被加在原有目标函数中的,因此其关于参数w的梯度也只是加上了对应梯度的参数,同时关于偏置b的梯度并没有改变。下面就总结一下线性回归和逻辑回归算法加上L_2正则化后的变化。

2.1 线性回归

\begin{aligned}
J(W,b)&=\frac{1}{2m}\sum_{i=1}^m\left(y^{(i)}-(W^Tx^{(i)}+b)\right)^2+\color{red}{\frac{\lambda}{2n}\sum_{j=1}^nW_j^2}\\[2ex]
\frac{\partial J}{\partial W_j}&=\frac{1}{m}\sum_{i=1}^m\left(y^{(i)}-(W^Tx^{(i)}+b)\right)\cdot(-x_j^{(i)})+\color{red}{\frac{\lambda}{n}W_j}\\[2ex]
\frac{\partial J}{\partial b}&=-\frac{1}{m}\sum_{i=1}^m\left(y^{(i)}-(W^Tx^{(i)}+b)\right)\\[2ex]
\end{aligned}\tag{4}

其中红色部分为加入L_2正则化后所发生的变化。

2.2 逻辑回归

\begin{aligned}
J(W,b)&=-\frac{1}{m}\sum_{i=1}^m\left[y^{(i)}\log{h(x^{(i)})+(1-y^{(i)})\log{(1-h(x^{(i)}))}}\right]+\color{red}{\frac{\lambda}{2n}\sum_{j=1}^nW_j^2}\\[2ex]
\frac{\partial J}{\partial W_j}&=-\frac{1}{m}\sum_{i=1}^m\left[y^{(i)}-h(x^{(i)})\right]x^{(i)}_j+\color{red}{\frac{\lambda}{n}W_j}\\[2ex]
\frac{\partial J}{\partial b}&=-\frac{1}{m}\sum_{i=1}^m\left[y^{(i)}-h(x^{(i)})\right]
\end{aligned}\tag{5}

其中红色部分为加入L_2正则化后所发生的变化。

2.3 梯度下降

W=\color{red}{(1-\alpha\frac{\lambda}{n})}\color{black}W-\alpha\frac{\partial J}{\partial W}\tag{6}

其中红色部分为加入L_2正则化后所发生的变化,可以看出L_2正则化令权重W先自身乘以小于1的数,再减去不含惩罚项的梯度。因此,L_2正则化又叫权重衰减[4]。

3 示例

由于文章篇幅有限,在这里就只展示部分关键代码,完整示例可参见文末引用[5]。

  • 损失函数

    def cost_function(X, y, W, bias, lam):
        m, n = X.shape
        y_hat = prediction(X, W, bias)
        J = 0.5 * (1 / m) * np.sum((y - y_hat) ** 2)
        return J + lam / (2 * n) * np.sum(W ** 2)
    
  • 梯度下降

    def gradient_descent(X, y, W, bias, alpha, lam):
        #...修改梯度公式,添加正则化对应的梯度
        grad_w = -(1 / m) * np.matmul(X.T, (y - y_hat)) + (lam / n) * W 
        grad_b = -(1 / m) * np.sum(y - y_hat)  # 求解梯度
    	#...........
        return W, bias
    

下图所示左边为未添加正则化项时,训练误差和测试误差的走势,可以明显看出测试误差远大于训练误差,这是典型的过拟合现象。右图为使用正则化后训练误差和测试误差的走势,可以看出虽然训练误差有些许的增加,但是测试误差得到了很大程度上的缓解[4]。

4 总结

在这篇文章中,笔者首先通过示例详细介绍了如何通过L_2正则化方法来缓解模型的过拟合现象,以及介绍了为什么L_2正则能够使模型变得更简单。其次笔者介绍了加入正则化后原有梯度更新公式的变化之处,其仅仅只是加上的正则化项对应的梯度。最后笔者通过一个示例来展示了L_2正则化的效果。但与此同时,这篇文章笔者只是介绍了使用最为频繁的L_2正则化,例如还有L_1正则化等,读者可以自行查阅。本次内容就到此结束,感谢阅读!

若有任何疑问与见解,请发邮件至moon-hotel@hotmail.com并附上文章链接,青山不改,绿水长流,月来客栈见!

引用

[1] 李宏毅 ML讲座1:回归 - 案例研究

[2] l1 相比于 l2 为什么容易获得稀疏解?答主:王赟 Maigo www.zhihu.com/question/37…

[3] 机器学习中使用正则化来防止过拟合是什么原理?答主:俞扬 www.zhihu.com/question/20…

[4] 动手深度学习

[5]示例代码:关注公众号回复“示例代码”即可直接获取!