<audio id="audio" title="23 深度学习 | 前方有路，未来可期：深度前馈网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/85/09/85714aa92045ae1bc4b065b5dc64a709.mp3"></audio>

深度前馈网络（Deep Feedforward Network）是具有深度结构的前馈神经网络，可以看成是进化版的多层感知器。与只有一个或两个隐藏层的浅层网络相比，深度前馈网络具有更多的隐藏层数目，从而具备了更强的特征提取能力。

深度前馈网络不考虑输入数据可能具备的任何特定结构，也就是不使用关于数据的先验信息。但特征提取能力增强的代价是运算复杂度的提升。因而，**网络架构的建立、损失函数的选择、输出单元和隐藏单元的设计、训练误差的处理等问题就成为深度前馈网络设计中的一系列核心问题**。

**在深度前馈网络的设计中，确定架构是首要考虑的关键问题**。架构决定着网络中包含多少基本单元，以及这些基本单元之间如何相互连接。几乎所有前馈网络采用的都是链式架构，即前一层的输出是后一层的输入。在这样的链式架构中，层的数目和每一层中神经元的数目就是网络的主要变量。

介绍多层感知器时我曾提到了通用逼近的性质，这个性质的严格形式是通用逼近定理。**通用逼近定理的内容是如果一个前馈网络具有单个隐藏层，这个隐藏层又有足够但是有限数目的神经元，这个神经网络就可以以任意精度逼近任意连续函数**。虽然在这个定理的初始证明中，隐藏神经元的传递函数是具有“挤压”性质的非线性函数，但定理的成立性实际上并不取决于传递函数的性质，而是由网络的前馈架构所决定的。

通用逼近定理是一个存在性定理，它说明需要的神经网络是肯定存在的，却并没有指明具体的构造方法。所以在给定一个目标函数时，我们可以确定单隐藏层的感知器一定能够将它表示出来，却对隐藏层需要多少神经元毫无把握。这个数目很可能是个天文数字，这会让网络结构在计算机上根本无法实现。即使能够设计出这么复杂的算法，要对它进行训练和泛化也近乎天方夜谭。

深度前馈网络的出现克服的正是单隐藏层带来的复杂性问题：**使用深度架构的模型既能减少表示目标函数时所需要的单元数量，也能有效降低泛化误差，在一定程度上抑制过拟合的发生**。深度架构对复杂函数具有更强的表示能力，这一点已经在数学上得到证明。除此之外，深度架构也暗含了这样的假设：**待学习的复杂函数可以视为若干简单函数的层次化结合**。由于深度学习的思想本就借鉴自神经科学，这个假设也就合情合理了。

在层与层之间，深度架构采用的最常见的方式是**全连接**，意味着相邻层次中的任意神经元都两两相连。全连接是最简单也最复杂的架构，说它简单是因为连接方式只有一种选择，不需要考虑保留哪些连接或是放弃哪些连接；说它复杂是因为这种方式需要确定的参数最大，给网络训练带来了很大的麻烦。目前也有大量神经网络使用了稀疏的连接方式，这需要结合应用场景具体分析。

**任何机器学习算法都可以看成是对某个预设函数的最优化方法，深度前馈网络也不例外**。与其他神经网络一样，深度前馈网络也利用**梯度信息**进行学习，在处理误差时采用的是**反向传播方法**，利用反向传播求出梯度后再使用**随机梯度下降法**寻找损失函数的最小值。但深度网络的非线性特性常常会影响到学习算法的收敛性能，这也是使用非线性函数的神经网络的一个固有特性。

在学习中，损失函数的选择是深度神经网络设计中另一个重要环节。深度前馈网络选择损失函数的准则与其他机器学习算法并无二致：**回归问题的损失函数通常是最小均方误差，而分类问题的损失函数通常是交叉熵**（Cross-Entropy）。

交叉熵描述的是真实的数据分布和神经网络输出分布之间的差异性。当我们使用神经网络的输出去预测符合真实分布的测试数据时，网络输出并不能完全消除关于测试数据的不确定性。这部分剩余的不确定性可以由泛化误差体现，在信息论中则由交叉熵来定义。

如果$p(x)$和$q(x)$是两个离散分布，则两者的交叉熵可以表示为

$$ H(p, q) = - \sum_x p(x) \log q(x) $$

在深度前馈网络中，损失函数被定义为分类结果$\mathbf{y}$关于训练数据$\mathbf{x}$的条件概率的负对数之和

$$ J(\mathbf{\theta}) = - \sum_k \ln p(\mathbf{y}_k | \mathbf{x}_k)$$

确定损失函数后，网络的训练过程就是找到使以上表达式最小的参数$\mathbf{\theta}$的过程。**其实无论是最小均方误差还是交叉熵，体现的都是概率论中最大似然估计的原理**。最小均方误差与最大似然估计的关系在线性回归算法中已有说明，你可以回忆一下。而分类问题中，只要条件概率具有高斯分布的形式，训练数据与模型分布之间的交叉熵的最大化与最小均方误差同样殊途同归。

使用对数似然作为损失函数的一个优点是它的通用性，概率论上的直观意义使它适用于几乎所有的模型。另一个好处则体现在它可以避免因损失函数饱和造成的梯度消失，这是由于对数操作可以抵消掉大部分传递函数中的指数效果，从而更清晰地展示出变化趋势。

损失函数的表示与输出单元的选择密切相关，输出单元的传递函数决定了交叉熵的具体表达式。输出层的作用是对隐藏层提取出的特征施加额外的变换以得到输出，变换的形式则有多种选择。最简单的变换形式就是线性变换，它将隐藏特征的线性组合作为输出，简单而实用。

除了线性变换，**对数几率函数**也是一种常用的变换函数，其形式在机器学习模块的逻辑回归中已经做过介绍。对数几率函数得到的是一类软输出，因为它能将隐藏特征的线性组合映射到概率之上。将对数几率函数加以推广就可以得到**softmax函数**，也叫**柔性最大值函数**。对数几率函数只能解决二分类问题，softmax函数则可以解决多分类问题，也就是每个样本可以同时属于不同的类别。softmax函数的形式同样在逻辑回归中做了介绍，你可以回忆一下。

前面介绍的三种传递函数是输出单元的常见选择，对大部分机器学习模型是通用的。**而在深层前馈网络的设计中，一个独有的问题就是隐藏单元的设计，也就是隐藏神经元的传递函数如何选择**。但这个问题目前尚不存在放之四海而皆准的通用准则，关于这个环节的有限知识全都集中在一类常用的激活函数上，也就是**整流线性单元**（Rectified Linear Unit, ReLU）。

整流线性单元是隐藏单元理想设计的万金油，当你不知道选择何种激活函数时，那么用它准保没错。整流线性单元的数学表达式是

$$ {\text{ReLU}}(x) = \max { 0, x } $$

整流线性单元在一半定义域上取值为0，在另一半定义域上则处于激活状态。虽然在0点这个间断点上不满足可微的条件，但在激活的区域上，整流线性单元的一阶导数是常数1，二阶导数则恒等于0。相比于引入二阶效应的其他激活函数，整流线性单元的梯度方向在学习中具有更大的用处。

整流线性单元的一个缺点是它可能会“杀死”特定的隐藏神经元，因为一旦取值为0，这个函数就不会重新激活。解决这个问题的方法是对原始函数做一些微小的修正，得到的变体包括**渗漏整流单元**（Leaky ReLU）和**指数整流单元**（Exponential ReLU），它们的共同点是将原来的0输出替换为一个较小的数值，以避免神经元的失效。

除了整流线性单元之外，**对数几率函数**和**双曲正切函数**等其他函数也可以用于隐藏神经元中，但并不常见。相比于这些函数，整流线性单元的优势在于它的线性特性，这一性质使得模型更加容易优化，对黑箱中的隐藏神经元而言尤其如此。

可如果要针对执行特定任务的深度前馈网络选择最优化的隐藏单元，就是个依赖经验的过程。想要预测哪种隐藏单元的性能最佳完全依赖于直觉，至于直觉靠不靠谱，就得通过验证数据集来检验训练效果。从这个角度看，说深度学习是撞大运的炼金术不是没有道理的。

今天我和你分享了作为学习模型的深度前馈网络存在的一些共性问题，其要点如下：

- 深度前馈网络利用深度架构实现工程上可实现的对任意函数的通用逼近；
- 深度前馈网络使用梯度下降的方法进行学习；
- 深度前馈网络的损失函数通常是交叉熵或最小均方误差；
- 深度前馈网络的隐藏神经元通常使用整流线性单元作为传递函数。

在深度前馈网络中，深度结构是在空间维度上展开的，那么能否在时间维度上引入类似的结构，实现不同时刻之间的信息流动呢？

欢迎发表你的观点。

<img src="https://static001.geekbang.org/resource/image/06/c1/069de9897e302f8f9dc372b7459a0ec1.jpg" alt="" />
