前馈神经网络
简介
前馈神经网络 (Deep feedforward network) 可以说是深度学习最核心的模型之一。前馈神经网络的目的是对于输入 \(x\) ,假设我们要模拟从输入到输出的真实函数 \(f^*\) ,神经网络想要找到这样的映射 \(y=f(x ; \theta)\) 和合适的参数 \(\theta\) 使得其预测尽量接近于真实函数 \(f^*\) 。下面分别解释一下前馈,神经,和网络三个词的含义。
其中,前馈代表了所有的信息都从输入 \(x\) 经过某些中间的计算而最终输出到 \(y\) ,而不存在从模型 的输出到输入的反贵(feedback),对于有反馈的情况即为循环神经网络(recurrent neural network)。前馈网络已经广泛应用在工业界,其重要性不言而喻,而且它也是理解在自然语言处理中应用广泛的循环神经网络的基础。
而网络则代表了该模型是将不同的基本函数组合在一起形成的模型。例如通过将三个函数 \(f^{(1)}, f^{(2)}, f^{(3)}\) 串联起来构成最终的函数 \(f(x)=f^{(3)}\left(f^{(2)}\left(f^{(1)}(x)\right)\right) , f^{(1)}\) 就是网络的第一层, \(f^{(2)}\) 就是网络的第二层,以此类推。这个链的长度又被称作网络的深度 (depth),深度学习也因此得名。而前馈网络的最后一层被称作输出层(output layer),对于我们的训练数据,每一个输入 \(x\) 都有相应的标记 \(y \approx f^*(x)\) ,而网络的输出层的结果需要尽量接近 \(y\) ,但对于其它层来说,和训练数据没有这样的直接对应关系,即我们的算法只要求最后的输出接近于真实的标记,而对于中间每层的目的并没有明确定义,所以这些层又被称作隐藏层(hidden layer)。
最后,神经代表了它的灵感部分受到了神经科学的影响。每一隐藏层通常是矢量值,而这些隐藏层的维度定义了网络的宽度。我们可以将每层看做从一个大的从矢量到矢量的函数映射,但从另一方面也可以将矢量的每个元素看做一个小的神经元,每个神经元进行了矢量到标量的映射操作(激活函数,activation function),而每一层是不同的神经元并行运算的综合。
前馈神经网络的提出是为了解决传统线性模型的一些限制。线性模型如逻辑回归或者线性回归的优势是我们有的可以快速求出解析解,有的可以利用convex optimization来解决。但同时,线性模型也受限于只能模拟线性关系,而很难学习不同输入参数间的关系。为了将线性模型扩展到非线性函数,我们可以对于输入 \(x\) 做非线性变换 \(\phi(x)\) ,再利用对于 \(\phi(x)\) 的线性模型解决该问题,例如支持向量机中提到的kernel trick (支持向量机)。我们可以将 \(\phi\) 理解为从 \(x\) 向其蕴含的特征的映射,或者理解为对于 \(x\) 的一种新的表征(representation)。
- 对于如何选取映射 \(\phi\) 有如下几种思路:选取一个比较通用的 \(\phi\) ,例如kernel trick中的RBF kernel (也称作Gaussian kernel),如果 \(\phi(x)\) 的维度足够高,我们总能够使其匹配训练集,但很难推广到测试集。因为这种模型只是假设了局域变化不大的前提,而并没有包含任何有价值先验信息。
- 人工选取合适的 \(\phi\) ,实际上这是在深度学习流行之前普遍采用的方法,但是这需要大量的相关经验与人力资源,而且不同领域间的知识很难迁移。
- 深度学习的策略是利用神经网络学习合适的用隐藏层代表的映射 \(\phi\) ,即模拟 \(y=f(x ; \theta, w)=\phi(x ; \theta)^T w\) ,其中 \(\theta\) 是 \(\phi\) 的模拟参数,而 \(w\) 是从 \(\phi\) 到最终输出的映射参 数。它结合了第一和第二种方法,我们可以从比较通用的函数家族中学习 \(\phi\) ,同时也可以利用 经验对函数家族的选择进行一些限制。与第二种方法比较,其优势在于我们只需要找到一个比较合适的函数家族,而不需要知道确切的函数。
而这个非线性变换 \(\phi(x)\) 在深度学习中通常通过多层的带有RELU激活函数的隐藏层来进行自动拟合,在输出层则不使用激活函数,而是对变换后的样本进行分类或拟合。
整体架构设计
神经网络的设计主要包含两方面:
-
损失函数的选择
-
模型的具体架构。
对于损失函数,我们通常选择的是减小模型的概率分布与真实的概率分布之间的差异,即交叉熵 (cross-entropy) :
损失函数的具体形式依赖于模型的概率分布 \(p_{\text {model }}(y \mid x)\) ,例如在之前的总结中最大似然法与最大后验概率估计一一深度学习花书第五章 (三) 我们知道,假如模型概率分布是高斯分布 \(p_{\text {model }}(y \mid x)=N(y ; f(x ; \theta) ; I)\) ,则损失函数就是均方误差的形式:
由于神经网络的非线性的特征,我们通常需要用梯度下降的方法逐渐逼近其极值, 而且不能保证损失一定会收敛。假如损失函数很容易饱和即在某些区间趋于不变的话,则其梯度很小,梯度下降算法很难更新,所以我们希望损失函数在我们所研究的区间内尽量不饱和。这也是为 什么我们通常选取交叉熵的形式,因为很多概率分布函数都会出现指数形式 (如sigmoid函数) 而 在某些区间饱和,交叉熵中的log函数正好可以抵消其饱和,使得模型可以较快更新纠正错误预测。因此常用的损失函数还是极大似然估计(交叉熵)。
损失函数的具体形式依赖于神经网络输出层的选择,假设我们的神经网络已经得到了一系列隐藏特 征 \(h=f(x ; \theta)\) ,输出层就是从隐藏特征向我们的预测目标的映射。我们已经讨论了连续分布下的损失函数,但是对于离散情况并没有进行讨论。通常来说对于不同的输出分布,我们会有不同的输出函数及损失函数,常见的有如下几种:
Bernoulli Distribution
对于输出是Bernoulli Distribution的二元分布,我们通常选择sigmoid函数 \(\sigma(z)=\frac{1}{1+e^{-z}}\) 表示。令 \(z=w^T h+b\) ,我 们的输出层函数即为 \(P(y=1)=\sigma(z), P(y=0)=1-\sigma(z)=\sigma(-z)\),可以合并起来表示为 \(P(y)=\sigma((2 y-1) z)\) ,其对应的损失函数为 \(J(\theta)=-\log \sigma((2 y-1) z)=\varsigma((1-2 y) z)\) ,其中 \(\varsigma(x)=\log (1+\exp (x))\) 为softplus function 。
可以看出只有当 \((1-2 y) z\) 的值极负时,才会出现饱和,而这种情况只出现在我们的模型已经能够做出准确预测的情况,即 \(y=1\) 且 \(z\) 极正,或者 \(y=0\) 而 \(z\) 极负,在这种情况下,梯度很小,但由于我 们已经得到了足够准确的预测,我们并不需要更新我们的网络。对于对z作出错误预测的情况,即 \(y=1\) 且 \(z\) 为负,或 \(y=0\) 且 \(z\) 为正,则 \((1-2 y) z=|z|\) 为正值,在此区间 softplus function并不饱和,梯度较大,所以对于错误预测,网络能够很好的通过梯度下降算法迅速纠正错误。
Multinoulli Distribution
如果我们需要描述目标是多个class的概率分布,我们需要将处理二元分类问题的sigmoid函数扩展,即对于多元分类问题常用的Softmax函数。对于二元分布,我们只需要一个标量来表述class为 1 的概率 \(\hat{y}=P(y=1 \mid x)\) ,对于目标是 \(\mathrm{n}\) 个 class的情况,我们需要矢量来表述 \(\hat{y}\) ,其中 \(\hat{y}_i=P(y=i \mid x)\) ,每一个 \(\hat{y}_i\) 都需要满足在 \([0,1]\) 区间内,且所有 \(\hat{y}_i\) 的和为 1 ,所以我们需要用 softmax函数:
为了最小化损失函数,对于 \(\mathrm{y}=\mathrm{i}\), 我们则希望最大化 \(\log P(y=i ; z)=\log \operatorname{softmax}(z)_i=z_i-\log \sum_j \exp \left(z_j\right)\)
其中第一项 \(z_i\) 是当前直接贡献项,我们希望将它变大,而将第二项变小,第二项可以做如下的直观理解: 由于 \(\log \sum_j \exp \left(z_j\right) \approx \max _j z_j\) ,第二项可以理解为我们队最不正确的预测做出的惩罚,如果正确项已经是softmax输入中贡献最大的,则两项可近似抵消,说明这个数据对整体的损失贡献较小,我们可以集中精力处理其他没有正确分类的数据。
可以看出,如果我们选取的损失函数不是交叉熵的形式,则对于 softmax函数来说,当 \(z\) 为负值时,则其梯度接近于零,例如采取如mean square error形式的损失函数,则模型很难更新。而交叉熵保证了梯度不会消失。另一方面,对于 \(z\) 较大的情况,则 softmax趋于 1 饱和,梯度也接近于零,只有采取交叉熵的形式才能很好的抵消饱和的影响。
Gaussian Distribution
对于输出是高斯分布的情况之前已经总结过,输出层常常是线性的变换 \(\hat{y}=W^T h+b\) ,而线性输出层用来得到高斯分布的均值 \(p(y \mid x)=N(y ; \hat{y}, I)\) ,最小化交叉熵就转化为最小化均方差的形式。由于线性输出不存在饱和区间,所以能较好的应用梯度下降算法。
Mixture Gaussian Distribution
我们也可以将高斯分布推广到对于同一个 \(x\) 可能有几个 \(y\) 的峰值的混合高斯分布情况,它的输出层也 被称为混合密度层(Mixture of Density)即
\(p(y \mid x)=\sum_{i=1}^n p(c=i \mid x) N\left(y ; \mu^{(i)}(x) ; \Sigma^{(i)}(x)\right)\) 其中 \(p(c=i \mid x)\) 是对于 \(\mathrm{n}\) 个组分的 multinoulli分布。
我们同样的采取交叉熵作为其损失函数。
下面的表很好的总结了以上的常见概率分布,输出层与损失函数的关系:
Output Type | Output Distribution | Output Layer | Cost Function |
---|---|---|---|
Binary | Bernoulli | Sigmoid | Binary cross entropy |
Discrete | Multinoulli | Softmax | Discrete cross entropy |
Continuous | Gaussian | Linear | Gaussian cross entropy (MSE) |
Continuous | Mixture of Gaussian | Mixture Density | Cross entropy |
lan介绍了隐藏层的众多种类的函数,包括他本人提出的maxout units,但正如他本人在后来演讲中承认的,前馈网络大部分采取前面提到的ReLU函数就可以比较有效的解决,其他更复杂的隐藏层函数模型效果和ReLU类似,并没有明显优势,而鉴于ReLU简单的形式和较好的结果,大部分前馈神经网络中仍选择ReLU作为隐藏层函数。