NO.49.tip: 深度神经网络的组件

背景

术语深度神经网络(Deep Neural Network, DNN),在其现代用法中,指的是任何一种可以表示为计算图(computation graph)的可微函数,其中节点是原始运算(例如矩阵乘法),边以向量、矩阵或张量的形式表示数值数据。在最简单的形式中,该图可以被构造为节点或“层”的线性序列。术语“深度”指的是具有许多此类层的模型。

在此我们将讨论该领域中使用的一些基本构建块(节点类型)。如果函数计算的是给定训练集下模型预测的标量损失,我们可以将此梯度传递给优化例程,以便拟合模型。将这些模型与数据进行拟合被称为深度学习。

我们可以使用两种不同的方式将深度神经网络与概率模型相结合。第一种方式是使用将深度神经网络与概率模型相结合来定义条件分布中使用的非线性函数。例如,我们可以使用 来构建一个分类器,其中 是一个神经网络,用于将输入 和参数 映射到输出 logits。或者,我们可以使用有向图模型(见第 4 章)在多个变量上构建联合概率分布,其中每个条件概率分布 都是一个深度神经网络。这使得我们能够构建表达概率模型。

将深度神经网络和概率模型相结合的另一种方法是使用深度神经网络来近似后验分布,即,我们学习一个函数 来计算 ,其中 是隐藏变量(潜在变量和/或参数), 是观测变量(数据), 是推理网络, 是其参数。需要注意的是,在这种方法中,联合概率模型 可以是一个没有任何“神经”组件的“传统”模型。例如,模型可能是一个复杂的模拟器。因此,深度神经网络仅用于计算目的,而非统计/建模目的。

源与流

可微电路的构建块

我们将讨论在构建神经网络时使用的一些常见构建块。我们将构建块的输入表示为 ,将输出表示为 。

线性层

深度神经网络最基本的构建块是单个“神经元”,其对应于通过将向量值输入信号 乘以权重向量 ,然后添加偏置项 来计算的实值信号 。也就是说,

其中, 是函数 的参数,如图 16-1 所示。(为了清楚起见,省略了偏置项。)

通常,会将一组神经元组合成层(layer)。然后,我们可以将具有 个单位的层的激活表示为向量 。我们可以通过乘以权重矩阵 将激活的输入向量 转换为输出向量 ,加上偏移向量或偏移项 ,从而得到:

其中, 是函数 的参数。这被称为线性层(linear layer),或者全连接层(fully connected layer)。

通常在权重矩阵的第一列上预加偏置向量,并在向量 上附加一个 ,这样我们就可以更简洁地将其写成 ,其中 ,。如果需要的话,这允许我们忽略符号中的偏置项。

非线性现象

一堆线性层相当于一个线性层,其中我们将所有权重矩阵相乘。为了获得更强的表达能力,我们可以通过一个称为激活函数(activation function)的非线性函数对每一层进行逐元素(逐点)转换。这表示为:

一些常见的激活函数列表所示。

表 一些常见的神经网络激活函数列表

函数名称函数定义值域
sigmoid
双曲正切
softplus
ReLU
带泄露的 ReLU
ELU
swish
GELU

卷积层

在处理图像数据时,我们可以将相同的权重矩阵应用于图像的每个局部块,以减少参数的数量。如果我们在图像上“滑动”这个权重矩阵,并将结果相加,那么就得到了一种称为卷积(convolution)的技术;在这种情况下,权重矩阵通常被称为核或滤波器(filter)。

更准确地说,设 为输入图像, 为核。输出由 表示,(忽略边界条件)我们可以得到:

本质上,我们将以 为中心、大小为 的 的局部块与滤波器 进行比较;输出仅测量输入块与滤波器的相似程度。我们可以使用类似的方式定义一维或三维卷积。需要注意的是,由于边界效应,输出的空间大小可能小于输入的空间大小,尽管这可以通过使用填充(padding)来解决。

我们可以对多层输入重复这个过程,通过使用多个滤波器,可以生成多层输出。一般来说,如果我们有 个输入通道,并且想将其映射到 个输出(特征)通道,那么可以定义 个核,每个核的大小为 ,其中 、 是核的高度和宽度。第 个输出特征图是通过将所有 个输入特征图与第 个核进行卷积,然后将结果元素相加而获得的:

这被称为卷积层(convolutional layer)。

与使用线性层相比,卷积层的优点在于核的权重在输入中的各个位置之间共享。因此,如果输入中的模式改变位置,则相应的输出激活也将改变。这被称为平移等变性(shift equivariance)。在某些情况下,我们希望输出是相同的,无论输入模式发生在哪里;这被称为移位不变性(shift invariance),可以通过使用池化层(pooling layer)来获得,池化层计算输入的每个局部块中的最大值或均值。(注意,池化层没有可学习的参数。)其他形式的不变性也可以被神经网络捕获。

残差(跳过)连接

如果我们将大量的非线性层堆叠在一起,根据权重的大小以及非线性的性质,信号可能会被压缩到零,或者可能会膨胀到无穷大。类似的问题也会困扰通过网络反向传播的梯度。为了减少这种影响,我们可以添加跳跃连接(skip connection),也称为残差连接(residual connection),它允许信号跳过一个或多个层,从而防止其被修改。例如,以下计算:

现在,卷积层只需要学习一个偏移或残差来添加(或减去)输入,以匹配所需的输出,而不是直接预测输出。这样的残差通常较小,因此使用具有有界(例如,接近 1)权重的神经元更容易学习。

归一化层

为了学习“输入—输出”映射,最好对输入进行标准化处理,这意味着输入具有零均值和单位标准差。这确保了所需的权重幅度较小,并且在各个维度上具有可比性。为了确保内部激活具有此属性,通常会添加归一化层(normalization layer)。

最常见的方法是使用批量归一化(Batch Normalization, BN)。然而,这取决于能否访问一个批次为 $B>1$ 的输入样例。研究学者已经提出了各种替代方案来克服输入批次的需要,例如层归一化(layer normalization)、群组归一化(group normalization)、实例归一化(instance normalization)、滤波器响应归一化(filter response normalization)等。

dropout层

神经网络通常包含数百万个参数,因此有时会过拟合,尤其是在小数据集上训练时。可以使用许多方法来改善这种影响,例如将正则化因子应用于权重,或者采用完全贝叶斯方法。另一种常见的启发式方法被称为丢弃法(dropout),其中每次使用网络时都会随机省略边。更准确地说,如果 是从第 层中的节点 到第 层中的节点 的边的权重,那么我们将其替换为 ,其中 ,此处 是丢弃概率, 是保持概率。因此,如果我们采样 ,那么从层 中的单元 进入层 中的任何 的所有权重都将被设置为 0。

在训练过程中,对于连接到已“关闭”的神经元的权重,梯度将为零。然而,由于我们每次使用网络时都会对 进行重新采样,因此每一步都会更新不同的权重组合。结果是一个网络的集成,每个网络都具有略微不同的稀疏图结构。

在测试时,我们通常会关闭 dropout 噪声,因此模型的行为是确定性的。为了确保权重在测试时与训练时具有相同的期望值(从而使得神经元的输入激活平均而言也是相同的),在测试时我们应该使用 。对于伯努利噪声,我们有 ,因此在进行预测之前,应该将权重乘以保持概率 。然而,如果我们愿意,也可以在测试时使用 dropout。这被称为蒙特卡洛丢弃法(Monte Carlo Dropout, MCD)。

注意力层

在基于非参数核的预测方法中,例如高斯过程,我们使用核将输入 与每个训练样例 进行比较,以获得相似性得分的向量 。然后,使用该向量来抽取相应的 个目标值 的加权组合,如下所示:

更多信息可以参见 18.3.7 节。

我们可以按以下方法构建上式的可微和参数化版本。首先,使用学习嵌入替换存储的样例矩阵 ,以创建一组存储的键(key)。类似地,使用学习嵌入替换存储的输出矩阵 ,以创建一组存储的值(value),。最后,嵌入输入以创建一个查询(query)。需要学习的参数是这三个嵌入矩阵。

为了确保输出是输入的可微函数,我们使用软注意力层(attention layer)代替固定的核函数。更确切地说,我们定义:

其中, 是第 个注意力权重(attention weight);这些权重对于每个 满足 ,并且这些权重满足 。

注意力权重可以通过注意力得分(attention score)函数 来计算,该函数计算查询 与键 的相似性。例如,我们可以使用(缩放)点积注意力(dot product attention),其形式为:

(通过 进行缩放,其目的是为了减少输出对向量维度的依赖。)给定得分,我们可以使用 softmax 函数计算注意力权重:

在某些情况下,我们希望将注意力限制在字典的一个子集上,该子集对应于有效条目。例如,我们可能希望将序列填充到固定长度(用以实现高效的小批次处理),在这种情况下,我们应该“屏蔽”填充的位置。这被称为掩码注意力(masked attention;又称为屏蔽注意力)。我们可以通过将屏蔽条目的注意力得分设置为一个大的负数(例如 )来有效地实现这一点,从而使相应的 softmax 权重为 0。

在实践中,我们通常一次处理 个向量的迷你批次。设对应的查询矩阵、键矩阵和值矩阵的表示分别为 ,,。则

是对应于第 个查询的第 个输出。我们可以使用下式,并行计算所有的输出 :

其中逐行应用 softmax 函数。

为了增加模型的灵活性,我们经常使用多头注意力(multi-head attention)层。让第 个注意力头为:

其中,, 以及 均为线性投影矩阵。我们将多头注意力层的输出定义为:

其中, 是注意力头的数量,并且 。在某些权重矩阵未适当初始化的情况下,具有多个注意力头可以提高层的性能;经过训练之后,我们通常可以移除所有的注意力头(除其中一个注意力头之外)。

当一个注意力层的输出被用作另一个注意力层的输入时,该方法被称为自注意力(self-attention)。这是 Transformer 模型的基础。

循环层

我们可以通过使用当前状态 扩展输入 ,然后使用某种函数计算输出和新状态,从而使模型具有状态性(stateful):

这被称为循环层(recurrent layer),如图 16-8 所示。这构成了循环神经网络(Recurrent Neural Network, RNN)的基础。在普通循环神经网络中,函数 是一个简单的多层感知器,但也可能使用注意力。

乘法层

在本节中,我们将讨论乘法层(multiplicative layer),这对于组合不同的信息源来说非常有用。

假设我们有输入 和 ,在线性层(以及卷积层)中,通常将输入连接起来,得到 ,其中 和 。我们可以通过使用相乘交互来增加模型的表达能力,例如双线性形式(bilinear form),如下所示:

其中, 是一个权重张量,其定义为:

也就是说,输出的第 个条目是 和 的加权内积,其中权重矩阵是 的第 个“切片”。其他参数的大小为 、 以及 。

这个公式包括许多有趣的特殊情况。特别是,超网络(hypernetwork)可以视为这种方式。超网络是为另一个神经网络生成参数的神经网络。具体来说,我们使用 代替 。如果 和 是仿射的,这等价于乘法层。为了理解这一点,设 ,。如果我们定义 ,,那么我们就得到了式 (16)。

我们还可以将循环神经网络中使用的门控层视为相乘交互的一种形式。特别地,如果超网络计算对角矩阵 ,那么我们可以定义 ,这是标准的门控机制。注意力机制也是相乘交互的一种形式,尽管注意力机制涉及查询、键和值之间的三方交互。

如果超网络仅计算卷积层每个通道的标量权重,再加上偏置项,则会出现另一种变体:

这被称为 FiLM,代表“逐特征线性调制”(feature-wise linear modulation)。

隐式层

到目前为止,我们主要关注显式层(explicit layer),显式层指定如何使用 将输入转换为输出。我们还可以定义隐式层(implicit layer),隐式层根据约束函数间接指定输出:

关于如何寻找到该约束优化问题解决方案的细节可能因问题而异。例如,我们可能需要运行内部优化例程,或者调用微分方程求解器。这种方法的主要优点是内部计算不需要显式存储,从而节省了大量的内存。此外,一旦找到了解决方案,我们就可以利用隐函数定理将梯度传播到整个层。这使我们能够在端到端框架中使用更高级别的原语。