文章目录

  • 参数惩罚
  • L2 正则化
  • L1 正则化
  • Dropout
  • 附录


  神经网络在训练集中的损失值很低,但在测试集中的损失却很大,这就是过拟合(overfitting)现象。过拟合时,神经网络对于特定的特征数据表现极佳,但对于大多数数据表现很差,即模型的泛化性(generalization)差。

HIDDEN LAYERS 神经网络 神经网络regularization_机器学习


  在上图中我们可以看到,黄线非常好的拟合了我们给出的样本点,但看起来没有那么合理。蓝线尽管没有完全拟合上样本点,但似乎看起来就是我们要找的预测线。我们假设蓝线就是正确的预测线,那么黄线就是一种过拟合现象。解决过拟合的方法主要有三种(出自吴恩达《机器学习》2022 版):

  • 增加样本数量。如果我们给出更多的样本点,那么就可以把上图中的黄线逐渐拉向蓝线。
  • 去除不必要的特征,防止其对预测结果产生较大的干扰。比如我们做一个房价预测,显然不需要把明天会不会下雨这个特征引入。
  • 正则化(regularization)。这也是本文主要论述的内容。

  正则化目前主流的方法有:参数惩罚、Dropout等。接下来将分别对其进行论述。

参数惩罚

  再次回到上文中的图片,我们为什么会觉得图中蓝线更合理呢?这是因为我们下意识地遵循了奥卡姆剃刀原理(Occam’s Razor),换成中国话来说就是避繁就简(西方人真麻烦,就一个词还得搞个原理)。当一个问题有多种解决办法时,我们选择其中最简单地一个,而往往简单的办法在现实中泛化性最好。参数惩罚就是遵循了奥卡姆剃刀原理,即让神经网络中那些无关紧要的权重值变为零或使其趋向于零,这也就相当于在网络中去除了那条对应的通路。参数惩罚最终目的就是得到一个符合训练集的最简单的网络。其概念公式如下:
HIDDEN LAYERS 神经网络 神经网络regularization_正则化_02  其中 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_03 为损失值,HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_04 为新的损失值,HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_05 是正则化函数,HIDDEN LAYERS 神经网络 神经网络regularization_机器学习_06 是第 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_07 层的权重矩阵,HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_08 是常量参数(常取值为 HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_09)。原损失值在式中被称为损失项;在损失值中新加入的这部分被称为正则项,它也将参与损失值求梯度的过程。这样权重在反向传播的过程中,不单单得到是原损失值对其的偏导,还有正则项对其的偏导。其中正则项就起到惩罚的作用,它会促使所有权重值向零靠近。这是读者可能有疑问:它对所有的权重进行惩罚,那最后所有的权重不都变成零了?对于网络中那些重要的权重施加惩罚,必然会导致网络的预测结果不理想,那么损失项的值就会上升,损失项的偏导又会把它拉回原来的位置。而对于那些不重要的权重施加惩罚,则不会导致损失值的上升,也就没有被拉回原值的机会,最终就会逐渐向零靠近。

L2 正则化

  L2 正则化(L2 regularization)即正则函数中使用了 L2 范数(L2 norm)。正则函数的表达式如下:

HIDDEN LAYERS 神经网络 神经网络regularization_正则化_10  通过上式我们可以得出:对于某权重 HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_11,正则项对其偏导数为 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_12。通过这一点我们可以推理出 L2 正则化的特点是会让不必要的权重靠近零而不是等于零。如下图所示:

HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_13


  HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_11 是以每次 HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_15 的递减方式向零靠近,但同时 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_12 也在不断减小,最终 HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_11

L1 正则化

  与 L2 正则化类似,L1 正则化中使用了 L1 范数。L1 正则函数的表达式如下:

HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_18  通过上式我们可以得出:对于某权重 HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_11,正则项对其偏导数为 HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_08。通过这一点我们可以推理出 L1 正则化的特点是会让不必要的权重等于零。如下图:

HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_21


  HIDDEN LAYERS 神经网络 神经网络regularization_HIDDEN LAYERS 神经网络_11 是以每次 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_23

  • 计算效率。L2 正则化中的函数是全域可导的,而 L1 正则化中的函数含有绝对值,相比之下 L2 正则化求导计算效率更高。(不必深究,这可能牵涉到自动求导的相关理论)
  • 稀疏性。稀疏性是指一个矩阵或向量中只有少数元素是非零的。前面提到 L1 正则化会将大部分非必要的权重值置零,L2 正则化会将大部分非必要的权重值无限接近零。所以使用 L1 正则化的网络的预测结果稀疏性较强。

Dropout

  Alex Krizhevsky 在2012年提出了 AlexNet 神经网络,在该网络中首次应用了 Dropout 技术来缓解过拟合现象。AlexNet 也赢得了 2012 ImageNet 竞赛冠军。文章《Improving neural networks by preventing co-adaptation of feature detectors》第一次对该技术进行了介绍。另一篇文章《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》对该技术进行了更为详尽的介绍。笔者参考以上两篇文章完成了本章节的内容。
  在论述之前,我们先讲一些其它的技术以便能更好的理解 Dropout 的思想。集成学习是机器学习的一种范式。在集成学习中,我们会同时训练多个模型(被称为弱模型)来解决同一个问题。在应用时,所有弱模型会同时作出预测,而后将所有预测结果组合成一个结果。集成学习相比单一模型会有更准确的预测结果和更高的鲁棒性。
  引导聚集(Bootstrap aggregating, Bagging)算法是集成学习的一种。该算法首先从训练集中有放回的抽取多个子训练集,而后用这些子训练集分别训练一个神经网络。而后在应用时,让所有网络对同一个特征同时作出预测,最后选取所有预测结果中占比最高的一个作为最终结果(假设网络是一个分类模型)。实验结果表明,Bagging 算法能够有效抑制过拟合现象。我们从一个直观的角度来解释 Bagging 抑制过拟合的原因。训练过程中,各个网络都会产生过拟合,而由于训练数据集不同,各个网络过拟合的方向会有不同。在最终的对预测结果进行组合的时候,各网络的过拟合会被相互抵消一部分,从而使整体显示出抑制过拟合的效果。
  Bagging 算法有抑制过拟合的优势,但训练成本、模型的复杂度极高。因此 Dropout 的作者想在单一网络中实现类似集成学习的方式,这样就可以克服 Bagging 的缺点。Dropout 的大体思想是,在每次训练时各神经元都会以一定的概率被剔除出本次训练,这样对于每次训练的网络,其结构都不尽相同;在应用时,神经元将不会再被剔除,全体神经元都将参与预测。通过以上方式,Dropout 也就将单一网络改造成了类似集成学习的结构,以 “多个网络” 参与训练,而以 “多个网络” 的叠加形态参与应用。
  Dropout 在一定程度上也打破了神经元之间相互的依赖关系,使各个神经元能够更好的发挥自己的能力,而不是依赖其它神经元。从这个角度看,网络也就拥有了更高的鲁棒性。

threshold


weight 1
weight 2
weight i
weight n


           sum 
         

           Activation 
          
 function          
           times 
         

           output 
         

           input 1 
         

           input 2 
         

           input i 
         

           input n 
         

           Bernounlli


HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_24;设最终输出结果为 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_25;设神经元参与训练不被剔除的概率为 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26;记 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_27 为随机函数,其特性是以 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26 的概率输出 HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_29,以 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_30 的概率输出 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_31。那么,加入 Dropout 后的计算公式如下:
HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_32  接下来对以上公式进行解释。当 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_27 输出 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_31 时,有 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_35HIDDEN LAYERS 神经网络 神经网络regularization_机器学习_36,则 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_37,则损失值 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_07 对于该神经元内所有可训练参数的偏导数值都将为 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_31,这也就意味着所有可训练参数得不到更新(不考虑优化器提供的动量)。此时,该神经元正向传播时输出了 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_31,反向传播时其所有可训练参数没有得到更新,即该神经元没有参与训练。相应的当 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_27 输出 HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_29 时,神经元即参与训练。因此该神经元以 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26 的概率参加训练,以 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_30 的概率不参加训练。
  至于为何要除以 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26,原因如下:由于加入了概率, HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_46 符合 0-1 分布,其数学期望为 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_47 。我们知道在结束训练后,神经网路应用时不会再有神经元被剔除,那时该神经元输出值的数学期望为 HIDDEN LAYERS 神经网络 神经网络regularization_神经网络_24 。因此为了保持训练时和应用时该神经元输出值的数学期望保持一致,就需要在训练时除以 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26,即 HIDDEN LAYERS 神经网络 神经网络regularization_深度学习_50。当然,你也可以在应用时将输出值乘以 HIDDEN LAYERS 神经网络 神经网络regularization_正则化_26

附录

  以下为生成过拟合示意图的代码。

import matplotlib.pyplot as plt
import numpy as np


def f1(x):
    return x**2


def f2(x):
    a, b, c, d, e = -3.804788961038961, 1, 6.662608225108225,  -3.2467532467532467,  0.38893398268398266
    return a * x + b * x**2 + c * x**3 + d * x**4 + e * x**5


x = np.array([-0.5, 0.8, 3.1, 5.02])
y = f2(x)

ax = plt.gca()
ax.scatter(x, y, color='black', label='sample points')

x = np.linspace(-1, 5.2, 100)
y = f1(x)
ax.plot(x, y, label='just right')

y = f2(x)
ax.plot(x, y, label='overfit')

ax.legend()
plt.show()

  以下为生成 L2 正则化中使用到的图的代码。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2, 100)
y = x**2

ax = plt.gca()
ax.plot(x, y, label='$y=x^2$')

x = 1.9
xa = [x]
for _ in range(0, 10):
    x = x - 0.3*x
    xa.append(x)

ya = [x**2 for x in xa]

ax.plot(xa, ya, 'o:', label='Descending path of $x$')

ax.legend()
plt.show()

  以下为生成 L1 正则化中使用到的图的代码。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-1, 2, 100)
y = abs(x)

ax = plt.gca()
ax.plot(x, y, label='$y=|x|$')

x = 1.8
xa = [x]
for _ in range(0, 6):
    x = x - 0.3
    xa.append(x)

ya = [x for x in xa]

ax.plot(xa, ya, 'o:', label='Descending path of $x$')

ax.legend()
plt.show()