看过西瓜书和李航的《统计学习方法》,对机器学习的基本算法算是有了初步的理解。机器学习的算法和思想固然重要,在实际中也有很多应用场景,但在超大数据集的表现上,深度学习才是当下效果最好的工具。可惜的是,花书这样一本经典著作的中文版翻译和机翻差不多水平,因此看的时候只能放慢速度。闲言少叙,下面是第六章的学习记录。
1、深度前馈网络概念
深度前馈网络(deep feedforward network),也叫作前馈神经网络(feedforward neural network)或者多层感知机(multilayer perceptron, MLP),是典型的深度学习模型。前馈网络的目标是近似某个函数 。例如,对于分类器,将输入映射到一个类别。前馈网络定义了一个映射,并且学习参数的值使它能够得到最佳的函数近似。
下面我们把“深度前馈网络”这个词拆开来看:
这种模型被称为前向(feedforward)的,是因为信息流过的函数,流经用于定义的中间计算过程,最终到达输出。在模型的输出和模型本身之间没有反馈(feedback)连接。
前馈神经网络被称作网络(network)是因为它们通常用许多不同函数复合在一起来表示。该模型与一个有向无环图相关联,而图描述了函数是如何复合在一起的。例如、、连接在一个链上以形成。这些链式结构是神经网络中最常用的结构。被称为网络的第一层,被称为第二层,以此类推。链的全长称为模型的深度。
那么深度前馈网络的各层之间有什么区别呢?从功能来讲,训练样本直接指明了输出层在每一点x上必须做什么,它必须产生一个接近 y 的值。但训练数据并没有给出其它层中的所需的输出,所以这些层被称为隐藏层(hidden layer)。
一种理解前馈网络的方式是从线性模型开始,并考虑如何克服它的局限性。如果各层的函数都是线性函数,那么复合后的函数依然是线性的,此时我们的网络模型等价于线性模型。为了提高模型的表示能力,我们需要将各层的设置为非线性的,从而得到一个非线性映射。我们可以认为提供了一组描述的特征,或者认为它提供了的一个新的表示。
2、基于梯度的学习
设计和训练神经网络与使用梯度下降训练其他任何机器学习模型并没有太大不同。神经网络和线性模型等算法的最大区别,在于神经网络的非线性导致大多数我们感兴趣的代价函数都变得非凸。这意味着神经网络的训练通常使用迭代的、基于梯度的优化,仅仅使得代价函数达到一个非常小的值;而不是像用于训练线性回归模型的线性方程求解器或者用于训练逻辑回归或 SVM 的凸优化算法那样保证全局收敛。
用于非凸损失函数的随机梯度下降没有这种收敛性保证,并且对参数的初始值很敏感。对于前馈神经网络,将所有的权重值初始化为小随机数是很重要的。偏置可以初始化为零或者小的正值。
2.1、代价函数
大多数现代的神经网络使用最大似然来训练。这意味着代价函数就是负的对数似然,它与训练数据和模型分布间的交叉熵等价。这个代价函数表示为
使用最大似然来导出代价函数的方法的一个优势是,它减轻了为每个模型设计代价函数的负担。明确一个模型则自动地确定了一个代价函数。
用于实现最大似然估计的交叉熵代价函数有一个不同寻常的特性,那就是当它被应用于实践中经常遇到的模型时,它通常没有最小值。如果模型可以控制输出分布的密度(例如,通过学习高斯输出分布的方差参数),那么它可能对正确的训练集输出赋予极其高的密度,这将导致交叉熵趋向负无穷。正则化技术提供了一些不同的方法来修正学习问题,使得模型不会通过这种方式来获得无限制的收益。
2.2、输出单元
一种简单的输出单元是基于仿射变换的输出单元,仿射变换不具有非线性。这些单元往往被直接称为线性单元。给定特征,线性输出层产生一个向量,线性输出层经常被用来产生条件高斯分布的均值:
最大化其对数似然此时等价于最小化均方误差。
许多任务需要预测二值型变量的值。具有两个类的分类问题可以归结为这种形式。此时最大似然的方法是定义在条件下的 Bernoulli 分布。为保证模型给出了错误答案时,总能有一个较大的梯度。可以使用sigmoid输出单元结合最大似然来实现。sigmoid 输出单元定义为:
这种在对数空间里预测概率的方法可以很自然地使用最大似然学习。因为用于最大似然的代价函数是,代价函数中的抵消了中的。如果没有这个效果,sigmoid 的饱和性会阻止基于梯度的学习做出好的改进。因此,最大似然几乎总是训练输出单元的优选方法。
当我们想要表示一个具有 n 个可能取值的离散型随机变量的分布时,我们可以使用函数。它可以看作是函数的扩展。
函数最常用作分类器的输出,来表示个不同类上的概率分布。比较少见的是,函数可以在模型内部使用,例如如果我们想要在某个内部变量的个不同选项中进行选择。函数的形式为:
和一样,当使用最大化对数似然训练来输出目标值时,使用指数函数工作地非常好。
3、隐藏单元
隐藏单元的设计是一个非常活跃的研究领域,并且还没有许多明确的指导性理论原则。
整流线性单元(Rectified Linear Unit, ReLU)是隐藏单元极好的默认选择。许多其他类型的隐藏单元也是可用的。决定何时使用哪种类型的隐藏单元是困难的事(尽管整流线性单元通常是一个可接受的选择)。我们这里描述对于每种隐藏单元的一些基本直觉。这些直觉可以用来建议我们何时来尝试一些单元。通常不可能预先预测出哪种隐藏单元工作得最好。设计过程充满了试验和错误,先直觉认为某种隐藏单元可能表现良好,然后用它组成神经网络进行训练,最后用验证集来评估它的性能。
大多数的隐藏单元都接受输入向量 x,计算仿射变换,然后使用一个逐元素的非线性函数。大多数隐藏单元的区别仅仅在于激活函数的形式。
3.1、整流线性单元及其扩展
整流线性单元使用激活函数:
整流线性单元通常作用于仿射变换之上:
当初始化仿射变换的参数时,可以将 b 的所有元素设置成一个小的正值,例如 0.1。这使得整流线性单元很可能初始时就对训练集中的大多数输入呈现激活状态,并且允许导数通过。
整流线性单元的一个缺陷是它们不能通过基于梯度的方法学习那些使它们激活为零的样本。整流线性单元的各种扩展保证了它们能在各个位置都接收到梯度。
整流线性单元的三个扩展基于当时使用一个非零的斜率:
绝对值整流(absolute value rectification)固定来得到:,它用于图像中的对象识别 (Jarrett et al., 2009a);渗漏整流线性单元(Leaky ReLU)(Maas et al., 2013) 将固定成一个类似 0.01 的小值;参数化整流线性单元(parametric ReLU)将作为学习的参数 (He et al., 2015)。
maxout 单元(maxout unit)(Goodfellow et al., 2013a) 进一步扩展了整流线性单元。maxout单元将划分为每组有个值的组,而不是使用作用于每个元素的函数。每个maxout单元则输出每组中的最大元素:
这里是组的输入索引集。因为激活函数中有了max操作,所以整个maxout网络也是一种非线性的变换。
maxout的拟合能力是非常强的,它可以拟合任意的的凸函数。最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合,而maxout又是取k个隐隐含层节点的最大值,这些”隐隐含层"节点也是线性的,所以在不同的取值范围下,最大值也可以看做是分段线性的(分段的个数与k值有关)。
整流线性单元和它们的这些扩展都是基于一个原则,那就是如果它们的行为更接近线性,那么模型更容易优化。
3.2、logistic sigmoid与双曲正切函数
在引入整流线性单元之前,大多数神经网络使用 logistic sigmoid 激活函数:
或者是双曲正切激活函数:
这些激活函数紧密相关,因为:
我们已经看过 sigmoid 单元作为输出单元用来预测二值型变量取值为 1 的概率。与分段线性单元不同,sigmoid 单元在其大部分定义域内都饱和——当 z 取绝对值很大的正值时,它们饱和到一个高值,当 z 取绝对值很大的负值时,它们饱和到一个低值,并且仅仅当 z 接近 0 时它们才对输入强烈敏感。sigmoid 单元的广泛饱和性会使得基于梯度的学习变得非常困难。因为这个原因,现在不鼓励将它们用作前馈网络中的隐藏单元。当使用一个合适的代价函数来抵消 sigmoid 的饱和性时,它们作为输出单元可以与基于梯度的学习相兼容。
当必须要使用 sigmoid 激活函数时,双曲正切激活函数通常要比 logistic sigmoid 函数表现更好。在而的意义上,它更像是单位函数。因为 tanh 在 0 附近与单位函数类似。
4、架构设计
架构(architecture)一词是指网络的整体结构:它应该具有多少单元,以及这些单元应该如何连接。
在链式架构中,主要的架构考虑是选择网络的深度和每一层的宽度。我将会看到,即使只有一个隐藏层的网络也足够适应训练集。更深层的网络通常能够对每一层使用更少的单元数和更少的参数,并且经常容易泛化到测试集,但是通常也更难以优化。对于一个具体的任务,理想的网络架构必须通过实验,观测在验证集上的误差来找到。
4.1、万能近似性质和深度
万能近似定理(universal approximation theorem)
一个前馈神经网络如果具有线性输出层和至少一层具有任何一种 ‘‘挤压’’ 性质的激活函数(例如logistic sigmoid激活函数)的隐藏层,只要给予网络足够数量的隐藏单元,它可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的 Borel 可测函数。前馈网络的导数也可以任意好地来近似函数的导数 (Hornik et al., 1990)。
万能近似定理意味着无论我们试图学习什么函数,我们知道一个大的MLP一定能够表示这个函数。
然而,我们不能保证训练算法能够学得这个函数。即使 MLP能够表示该函数,学习也可能因两个不同的原因而失败。首先,用于训练的优化算法可能找不到用于期望函数的参数值。其次,训练算法可能由于过拟合而选择了错误的函数。
总之,具有单层的前馈网络足以表示任何函数,但是网络层可能大得不可实现,并且可能无法正确地学习和泛化。在很多情况下,使用更深的模型能够减少表示期望函数所需的单元的数量,并且可以减少泛化误差。
存在一些函数族能够在网络的深度大于某个值d时被高效地近似,而当深度被限制到小于或等于d时需要一个远远大于之前的模型。在很多情况下,浅层模型所需的隐藏单元的数量是n的指数级。
Montufar et al. (2014) 的主要定理指出,具有个输入深度为每个隐藏层具有个单元的深度整流网络可以描述的线性区域的数量是:
根据经验,更深的模型似乎确实在广泛的任务中泛化得更好。
4.2、其他架构上的考虑
目前为止,我们都将神经网络描述成层的简单链式结构,主要的考虑因素是网络的深度和每层的宽度。在实践中,神经网络显示出相当的多样性。
一般的,层不需要连接在链中,尽管这是最常见的做法。许多架构构建了一个主链,但随后又添加了额外的架构特性,例如从层 i 到层 i + 2 或者更高层的跳跃连接。这些跳跃连接使得梯度更容易从输出层流向更接近输入的层。
架构设计考虑的另外一个关键点是如何将层与层之间连接起来。默认的神经网络层采用矩阵 W 描述的线性变换,每个输入单元连接到每个输出单元。许多专用网络具有较少的连接,使得输入层中的每个单元仅连接到输出层单元的一个小子集。这些用于减少连接数量的策略减少了参数的数量以及用于评估网络的计算量,但通常高度依赖于问题。
5、反向传播和其他的微分算法
当我们使用前馈神经网络接收输入并产生输出时,信息通过网络向前流动。输入提供初始信息,然后传播到每一层的隐藏单元,最终产生输出。这称之为前向传播(forward propagation)。在训练过程中,前向传播可以持续向前直到它产生一个标量代价函数。反向传播(back propagation)算法 (Rumelhart et al., 1986c),经常简称为backprop,允许来自代价函数的信息通过网络向后流动,以便计算梯度。
5.1、计算图
将计算形式化为图形的方法有很多。这里,我们使用图中的每一个节点来表示一个变量。变量可以是标量、向量、矩阵、张量、或者甚至是另一类型的变量。为了形式化我们的图形,我们还需引入操作(operation)这一概念。操作是指一个或多个变量的简单函数。我们的图形语言伴随着一组被允许的操作。我们可以通过将多个操作复合在一起来描述更为复杂的函数。
如果变量 y 是变量 x 通过一个操作计算得到的,那么我们画一条从 x 到 y 的有向边。我们有时用操作的名称来注释输出的节点,当上下文很明确时,有时也会省略这个标注。计算图的实例如下:
5.2、递归地使用链式法则来实现反向传播
使用符号到符号的方法计算导数的示例如下。在这种方法中,反向传播算法不需要访问任何实际的特定数值。相反,它将节点添加到计算图中来描述如何计算这些导数。通用图形求值引擎可以在随后计算任何特定数值的导数。 本例从表示的图开始,运行反向传播算法,指导它构造表达式对应的图。
这部分花书上讲了很多内容……我看得有些失去耐心……可能是讲得太细致了吧……我对反向传播算法的认识很简单,就是一个链式法则,一层一层计算梯度然后向后传播。这里根据之前上课时候的课件内容做下简单回顾:
总之反向传播算法的要点就是以恰当的顺序计算梯度,从而充分利用链式法则来提高计算效率。我个人认为理解BP的最佳方式就是自己画个图手推一遍。