购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第2章
神经网络基础

神经网络也称为人工神经网络(Artificial Neural Networks,ANNs),是机器学习的一个子集,也是深度学习算法的基础。人工智能神经网络受到了神经科学的启发。在大脑中,神经元是相互连接形成网络的细胞。每个神经元既能接收电信号,也能发送电信号。一旦神经元接收到的电信号超过某个阈值,神经元就会被激活,从而将电信号传递到前方。

人工神经网络是受生物神经网络启发的学习数学模型。人工神经网络建模数学函数,根据网络的结构和参数将输入映射到输出。在人工神经网络中,网络的结构是通过对数据进行训练来塑造的。然而在现实中,人类的神经网络比人工神经网络更强大,更复杂,因此不要在两者之间画等号。

2.1 神经网络单元

神经网络由节点层组成,分别是输入层、一个或多个隐藏层和一个输出层。每个节点都是一个人工神经元,与下一个节点相连,每个节点都有一个权重和阈值。当一个节点的输出超过阈值时,该节点被激活,并将其数据发送到网络的下一层。如果低于阈值,则不传递任何数据。下面来看神经网络的基本结构——神经元。

2.1.1 神经元

神经元(Neuron)是一个通用的计算单元,它接收 n 个输入并产生一个单一的输出。区分不同神经元输出的是它们的参数(也称为它们的权重)。其中被广泛使用的神经元选择是sigmoid单元(在后面的章节中会详细解释激活函数)。该单元接收 n 维输入向量 x ,并产生标量激活(输出) a 。该神经元还与一个 n 维权重向量 w 和一个偏置标量 b 相关联。然后,该神经元的输出为:

也可以把 b 融合到 w 之中,相应的 x 添加一行全部为1的向量即可。这样就不必再单独考虑 b 的值了,如公式(2-2)所示。

在sigmoid神经元中,输入向量 x 首先被缩放、求和,然后加上偏置单元,最后经过压缩的sigmoid函数处理,如图2-1所示。神经元是构成神经网络的基本单元之一,也是允许网络引入非线性特性的多种函数之一。

图2-1 神经元传输流程

2.1.2 神经元层

从单个神经元可以扩张到神经元层(Neuron Layer)。输入可以经过不同的神经元,也就是说,输入(Input) x 可以成为多个上述神经元的输入。

如果将不同神经元的权重表示为{ w (1) ,…, w ( m ) },将偏置表示为{ b 1 ,…, b m },可以将相应的线性组合激活为{ a 1 ,…, a m }:

为了后面简化表达,先定义一些概念:

有了这些定义就可以将缩放和偏置的输出表示为式(2-7):

激活函数可表示为:

可以将这些激活看作某些特征加权组合的指示器,然后就可以利用这些激活的组合来执行分类任务了。

2.2 前馈计算

命名实体识别任务(Named Entity Recognition,NER)也称为“专名识别”,旨在识别文本中具有特定意义的实体,如人名、地名、机构名、专有名词等。从前面的内容可以得知,分类任务可以通过激活的组合来实现,而命名实体识别正是一种典型的自然语言处理分类任务。

以简化的命名实体识别任务为例:判断中心词是否为实体(如地名)。例如,在句子“Temples in Kyoto are mesmerizing.”中,需要识别Kyoto为地名。在这个任务中不仅需要捕捉中心词周围的上下文词,还需要为它们的关系建模。softmax非线性决策无法仅通过将上下文词或中心词的向量直接输入softmax层来完成,因为softmax层仅对输入向量执行指数运算和归一化操作,并不能增强模型表达能力。要解决这个问题,需要通过中间层对特征进行评分,从而实现更复杂的语义建模。

这个分阶段的计算过程可以表达为:

单隐藏层神经网络中的维度:如果用一个十维的词向量来表示每个词,并使用一个5个词的窗口作为输入,那么输入 x ∈ℝ 50 。如果在隐藏层中使用9个sigmoid单元,并且从激活值中生成一个分数(score)输出,那么权重矩阵 W ∈ℝ 9×50 ,偏置向量 b ∈ℝ 9 ,输出权重矩阵 U ∈ℝ 9×1 ,分数 s ∈ℝ。

2.3 最大间隔目标函数

与大多数机器学习模型一样,神经网络也需要一个优化目标,即好坏度量。这里使用一个常用的错误度量,即最大间隔目标函数。使用这个目标函数的目的是确保为True标记的数据点计算的分数高于为False标记的数据点(如"Not all temples in Kyoto are ancient.",以前5个词的窗口为例,中心词并不是地点)计算的分数。那么现在的目标就是最大化 s T - s F (或者说最小化 s F - s T )。注意,只有当False标记的数据点计算出的分数高于True标记的数据点时才会关心这个差值,因为其他时候只要 s T > s F 就是正确的(损失为0)。也就是说,这种计算方式和支持向量机中的合页函数很相似。所以,最大间隔目标函数为:

这个公式实现了一个基本想法,但是并没有足够的安全边界,也就是说, s F s T 靠得太近了。可以加入一个安全边界 Δ ,使得目标函数在 s T - s F < Δ 时计算代价,而非在 s T - s F <0时才计算。修改公式(2-12)如下:

间隔调整设置为 Δ =1,并使得优化问题中的其他参数适应这个变化,同时保持性能不受影响。选择1的理由是,可以在公式两边除以同一个数使其最后变为1,所以选择任何正数和选择1没有差别。优化目标的最终版本如下:

2.4 反向传播

反向传播(Backpropagation)是神经网络训练中的核心算法,它通过计算误差的梯度来指导网络中各层参数的更新。反向传播算法的本质是通过逐层传递误差信息,依照链式法则计算每个参数对最终误差的影响,从而使网络的参数在每次迭代中得以调整,最终逐步优化网络性能。在神经网络的前向传播阶段,输入数据经过各层的线性变换与非线性激活函数,逐层传递并生成最终输出。与真实标签相比,输出的差异通过损失函数计算得出误差(也称为损失)。反向传播的目标是最小化这个误差。

反向传播的关键步骤是:

(1)计算损失函数的梯度:根据网络的输出和真实标签之间的误差,通过损失函数计算误差值。

(2)逐层反向传递误差:从输出层开始,误差通过网络的权重和激活函数的导数逐层反向传递至输入层。

(3)更新参数:利用梯度下降法或其变体,将计算得到的梯度用于更新每一层的权重和偏置,逐步逼近最优解。

通过反复执行这个过程,反向传播能够使网络学习到如何调整参数,以便更好地拟合训练数据,最终提升模型在任务中的表现。

2.4.1 以单个神经元的梯度更新为例

本节将会讨论当 J 是正值时,如何训练模型中的不同参数。如果成本(cost)为0,则不需要进行参数更新。通常使用梯度下降(或其变体,如随机梯度下降)来更新参数,因此需要对更新公式中的任何参数进行梯度信息的计算:

反向传播是一种通过微分的链式法则计算神经网络中任意参数的损失梯度的技术。在反向传播的具体计算之前,可以从最简单的神经网络开始进行定义:一个仅包含一个隐藏层和单个输出单元的神经网络。为了便于理解和推导反向传播的计算,首先需要明确相关的基本概念:

(1) x i 是神经网络的输入。

(2) s (score)是神经网络的输出。

(3)每一层(包括输入和输出层)都有神经元,它们接收一个输入并产生一个输出。第 k 层的第 j 个神经元接收输入 并产生标量激活输出

(4)在 处计算的反向传播误差:

(5)第1层指的是输入层,而不是第一个隐藏层。对于输入层, x j = = 。因为在这一层不存在任何转换和参数。

W k 是将第 k 层的输出映射到第( k +1)层的输入的传递矩阵。因此,根据2.2节中提到的两个权重( W U ),可以将 W (1) W (2) 分别定义为: W (1) = W W (2) = U

的意义:从第一层出发的权重,连接第一层的第三个神经元和第二层的第二个神经元。

现在反向传播计算的准备工作已完成。假设成本函数 J= (1+ s F - s T )是正数,所以需要更新 (以单个神经元为例),可以看出 只对 以及 有影响,如图2-2所示。

图2-2 与 相连的部分子网络

反向传播的梯度仅受到它们所贡献数值的影响。通过与 相乘, 被用于分数的前向计算。从最大间隔损失可以得到最后一层的损失:

为例,使用链式法则来推算损失梯度:

本质上是从第二层中第 i 个神经元向后传播的误差。 是传递给第二层第 i 个神经元的输入(通过 W ij )。

偏置 的梯度就是 (从公式(2-17)推导的倒数第三步开始可以推出)。

2.4.2 误差的回传

在2.4.1节中计算了当目标函数 s T 发生变化时,网络中第一层的权重 会如何影响目标函数的变化。而此计算是停留在当前层的权重上的,如果需要计算每一层的权重梯度,就需要将误差不断回传。现在来看将 δ ( k ) 传播到 δ ( k -1) 的一般步骤,如图2-3所示。

(1)在第 k 层的神经元 i 上有从 传播回来的误差

(2)通过将 乘以路径权重 ,将这个误差向后传播到

(3) 收到的误差是

(4)可能有多个节点从 流出(从正向来看)。因此, 收到的总误差是

(5)在 处有了正确的误差,通过与本地梯度 相乘,将其传播到第 k -1层的神经元 j 上。

(6)达到 的误差,

图2-3 误差从 δ ( k ) 传播到 δ ( k -1) 的步骤

2.4.3 向量化

到目前为止我们已经介绍了如何计算模型中特定参数的梯度。本节会使用向量化一次性更新所有权重矩阵和偏置向量,有助于读者更直观地理解误差在矩阵-向量层面的传播过程。

由2.4.2节的结论 可以很容易推广到矩阵:

在公式(2-19)中,符号◦表示两个向量元素间的逐元素乘法操作,即ℝ N ⋅ℝ N →ℝ N

2.5 神经网络的算法实现

在了解了神经网络的基本原理、前向传播与反向传播机制之后,接下来通过一段完整的Python代码来展示神经网络的具体算法流程。该段代码首先使用NumPy构建一个多层前馈神经网络(Feedforward Neural Network),其支持多种激活函数和损失函数,然后在经典的MNIST手写数字识别任务中进行训练与评估。以下是完整的代码实现及其训练过程。

2.6 神经网络的激活函数

经过2.1节至2.5节的讲解,较为系统地呈现了神经网络的整体结构与工作流程,包括前向传播、反向传播、损失函数的计算及参数更新等核心内容。然而,在这个过程中还有一个关键组成部分尚未深入展开介绍,那就是激活函数。激活函数不仅决定神经网络的非线性表达能力,还直接影响模型的学习效率与最终性能。因此,接下来的内容将围绕激活函数的定义、常见类型、数学性质及其在实际应用中的优缺点进行详细介绍,为后续网络结构设计和优化提供理论基础与实践参考。

2.6.1 为何需要激活函数

激活函数在神经网络中扮演着至关重要的角色,它的存在使得神经网络具备处理非线性关系的能力。如果没有激活函数,则神经网络仅进行线性变换,无法学习复杂的模式和非线性关系。激活函数引入了非线性元素,使得每个神经元在前向传播时能够引入非线性变换。这种非线性特性允许神经网络学习和捕捉数据中的复杂模式,从而更好地适应现实世界中的各种任务和问题。

假设有一个没有激活函数的神经网络,该网络包含一个输入层、一个隐藏层和一个输出层。在这种情况下,神经网络的每个神经元将仅进行线性变换,即将输入信号与权重相乘并加上偏置。在这个过程中,隐藏层和输出层的计算可以简化为加权求和的线性运算,而没有其他非线性的变换。这意味着无论添加多少隐藏层,整个网络只能够表示线性关系。

举例:一个没有激活函数的神经网络用于二元分类任务。假设输入特征为( x 1 , x 2 ),对应的权重参数为( w 1 , w 2 ),偏置为 b 。在没有激活函数的情况下,输出 y 可以表示为:

在上面这种情况下,无论如何调整权重和偏置,神经网络的输出始终是输入特征的线性组合。也就是说网络只能表示输入与输出之间的简单线性关系,无法处理实际问题中的复杂非线性模式。例如,在图像识别任务中,不同物体的边缘、纹理等特征往往呈现复杂的非线性变化。因此,如果不使用激活函数,神经网络将无法学习和捕捉这些复杂的非线性特征,从而大大限制了它在处理真实世界问题时的表现能力。

2.6.2 激活函数的特征

激活函数的主要目的是引入非线性,因为多个线性变换的组合仍然是线性的。如果没有激活函数,神经网络的多层结构就没有意义,因为它们将等效于单一的线性变换。通过激活函数,神经网络可以捕捉到数据中的非线性关系,如图像中的边缘、纹理等特征,从而提高网络的表达能力和适应性。

激活函数通常具有以下特性:

非线性:激活函数引入非线性,使得神经网络可以学习非线性关系。

可微分性:激活函数通常是可微分的,这是因为在反向传播算法中需要计算梯度,可微分性使得优化算法能够调整网络参数。

将输入映射到特定范围:某些激活函数将输入映射到特定的范围,如sigmoid函数将输入映射到(0, 1)区间,tanh函数将输入映射到(-1, 1)区间。

常见的激活函数包括sigmoid函数、tanh函数、ReLU函数(Rectified Linear Unit)等。选择适合任务的激活函数对于神经网络的性能和训练效果至关重要。

2.6.3 常见激活函数

激活函数是神经网络中不可或缺的组成部分,它决定了神经元的输出如何映射输入。不同的激活函数具有不同的特性,适用于不同的任务和网络结构。本节将介绍几种常见的激活函数,包括它们的定义、优缺点及应用场景,为选择合适的激活函数提供指导。

1.sigmoid激活函数

sigmoid函数以任意实数作为输入,并将输出值限定在0~1的范围内。输入值越大,输出值越接近1,而输入值越小(更负数),输出值越接近0,其表达式为:

它的导数表达式为:

sigmoid激活函数及其导数示意如图2-4所示。

图2-4 sigmoid激活函数及其导数

1)sigmoid激活函数被广泛使用的理由

sigmoid函数通常用于需要将输出解释为概率的模型,因为概率的范围在0~1之间,而sigmoid函数的输出范围正好符合这一需求。此外,sigmoid函数是可微的,并且能够提供平滑的梯度,其S形曲线确保了输出值的平稳变化,避免了梯度的剧烈波动。这一特性对于神经网络的训练尤为重要,有助于实现稳定的梯度更新。

2)sigmoid函数的缺陷

在输入范围-3~3之间,sigmoid函数的梯度较为明显,但在其他区域,函数图像变得非常平坦。这意味着当输入值大于3或小于-3时函数的梯度会非常小,逐渐趋近于0,导致网络无法继续学习,从而出现梯度消失的问题。因此,在循环神经网络(RNN)中,sigmoid并非首选激活函数。此外,sigmoid函数的输出在0点周围呈现不对称性,这会导致所有神经元的输出具有相同的符号,从而增加了神经网络训练的难度和不稳定性。

在选择激活函数时,需要根据具体任务要求和网络架构来权衡这些优势和限制。

2.双曲正切函数(tanh函数)

tanh函数与sigmoid/logistic激活函数非常相似,甚至具有相同的S形状,但输出范围为-1~1。在tanh函数中,输入值越大,输出值越接近1.0,而输入值越小,输出值越接近-1.0,其表达式为:

其导数表达式为:

tanh激活函数及其导数示意如图2-5所示。

1)tanh函数的优势

tanh激活函数的输出以0为中心,因此可以将输出值映射为负数、中性或正数。这一特性使其在神经网络的隐藏层中得到了广泛应用。由于tanh函数的输出范围在-1~1之间,隐藏层的输出均值通常为0或非常接近0。这种特性有助于数据居中,使传递给下一层的数据更具可学习性,从而提高网络的训练效率和性能。

图2-5 tanh激活函数及其倒数

2)tanh函数的缺点

tanh函数存在一些局限性,需要在使用时加以考虑。首先,梯度消失问题(Vanishing Gradients)是其主要缺点之一。与sigmoid函数类似,当输入值大于3或小于-3时,tanh函数的梯度会变得非常小,接近于0。在反向传播过程中,这会导致梯度逐渐消失,使神经网络难以有效学习,在深度网络中尤为明显。其次,计算复杂度也是一个问题。由于tanh函数需要进行指数运算,这在硬件资源有限的嵌入式系统中可能会降低计算效率。此外,输出范围限制也是tanh函数的一大弱点,其输出范围为-1~1,这意味着输出值并非从0开始。在需要将激活函数的输出解释为概率的任务中,这种限制可能不合适。最后,tanh函数并非稀疏激活函数。当输入接近0时,其输出的梯度仍不为0,这可能导致网络中许多神经元同时处于活跃状态,从而增加了计算的复杂性。

3.ReLU激活函数

ReLU代表修正线性单元。虽然它看起来像一个线性函数,但是由于ReLU的导数存在,因此它能够进行反向传播,同时计算效率更高。ReLU函数并不会同时激活所有的神经元,只有当线性变换的输出小于或等于0时神经元才会被停用。ReLU激活函数的表达式为:

其梯度表达式为:

ReLU激活函数及其导数示意如图2-6所示。

1)使用ReLU作为激活函数的优势

ReLU激活函数相比sigmoid和tanh函数在计算上更加高效,因为它仅激活一部分神经元,降低了计算复杂度。此外,ReLU的线性且非饱和特性使得其在反向传播过程中能够避免梯度消失问题,从而加速了梯度下降算法向损失函数全局最小值的收敛过程。这种特性使得ReLU成为深度神经网络中常用的激活函数之一。

2)ReLU的缺陷问题

ReLU函数的负值部分会导致梯度为0,使得某些神经元在反向传播过程中无法更新权重和偏置,从而陷入“死亡神经元”问题,即这些神经元永远不会被激活。此外,所有负输入值都会被直接置0,这在某些情况下可能会降低模型对数据的拟合能力,影响训练效果。

图2-6 ReLU激活函数及其导数

4.带泄露线性整流函数

带泄露线性整流函数(Leaky ReLU)是ReLU函数的改进版本,旨在解决ReLU的神经元死亡问题,因为它在负区域具有一个小的正斜率。Leaky ReLU的表达式如下:

它的梯度表达式为:

Leaky ReLU激活函数的示意如图2-7所示。

图2-7 Leaky ReLU激活函数( k =0.08)及其导数

Leaky ReLU的优势与ReLU相同,而且它允许在负输入值的情况下进行反向传播。通过对负输入值进行这样的小修改,图表左侧的斜率变为非0值。因此,在该区域将不再遇到“死亡神经元”。

Leaky ReLU函数存在一些局限性。首先,对于负输入值,预测结果可能不稳定,影响模型的健壮性。其次,由于负值对应的梯度较小,参数更新速度较慢,可能导致模型训练时间延长。

5.Scaled Exponential Linear Unit

Scaled Exponential Linear Unit(SELU)是一种修正线性单元(ReLU)的变体,具有特殊的性质,使得它在深度神经网络中表现良好。

SELU激活函数的导数在不同区域的定义如下:

λ α 是预先选择的常数,通常为1.0507和1.67326。SELU的主要特点是在深度前馈网络中使用时,它可以使每个层输出的均值和方差保持稳定,有助于缓解梯度消失问题,从而支持更深的网络结构。这种性质对于深度学习非常重要,因为在深度网络中,梯度通常会逐渐减小到接近0,使得训练变得困难。而SELU通过保持激活函数的均值接近0,方差接近1,有助于维持梯度的稳定性。

SELU激活函数及其导数示意如图2-8所示。

图2-8 SELU激活函数及其导数

1)SELU的优点

SELU具有多个优势,使其在深度神经网络中表现优越。首先,它能够保持每一层输出稳定的均值和方差,从而提高梯度稳定性,有效缓解梯度消失问题,使梯度在深层网络中更容易传播,加速模型收敛。其次,SELU具备自归一化(self-normalizing)特性,在特定条件下可以使输入和输出保持相对稳定的分布,这有助于网络训练,使每一层的输入处于合适的范围内。最后,SELU的参数( λ α )是预设固定的,无须在训练过程中进行额外调整,从而简化了网络配置,提高了训练的便捷性。

2)SELU的缺点

SELU在应用中存在一定的局限性。首先,其要求输入数据需以0为中心,并且方差接近1,否则性能可能下降。因此,在实际应用中需要额外的预处理步骤来确保数据满足这些条件。其次,SELU并不适用于所有类型的网络,尽管其在深度前馈神经网络中表现良好,但在处理稀疏数据或序列数据(如循环神经网络)时可能不是最佳选择。最后,SELU的计算复杂度相对较高,相比ReLU等简单激活函数,其计算涉及指数运算,在大规模深度网络中可能会增加计算负担。

2.6.4 常见激活函数的Python实现

在掌握了常见函数的定义及其性质之后,下面给出Python实现代码。下面的代码实现了多种函数及其导数,便于在实际的神经网络训练过程中进行调用与测试。

2.7 数据预处理

数据预处理(Data Preprocessing)是数据挖掘过程中至关重要的一步,它包括对原始数据进行清理和转换,使其适合进行分析。数据预处理的目标是提高数据质量,使其更符合特定的数据挖掘任务需求。

数据预处理步骤如下:

1)数据清理

数据清理是数据预处理的首要步骤。在这一阶段,需要识别并纠正数据中的错误或不一致性,包括处理缺失值、异常值和重复项。数据清理可以确保数据的一致性和准确性,为后续的分析提供可靠的基础。

2)数据整合

数据整合涉及将来自多个来源的数据合并,形成一个统一的数据集。这一步可能会面临不同数据格式、结构和语义的挑战,因此需要使用记录链接和数据融合等技术来处理。数据整合可以确保数据的完整性和一致性。

3)数据转换

数据转换是将数据转换为适合分析的格式的过程。常见的数据转换技术包括归一化、标准化和离散化。通过这些技术,数据被调整到一个统一的范围,消除了不同特征之间的尺度差异,便于比较和分析。

4)数据减少

当数据集过于庞大时需要进行数据减少。数据减少通过特征选择和特征提取等技术降低数据集的维度同时保留关键信息,这有助于提高模型的训练效率和准确性。

5)数据离散化

在某些数据挖掘算法中需要将连续数据划分为离散的类别或区间。数据离散化通常通过分箱或聚类等方法来实现,将连续数据转化为离散形式,便于算法处理。

6)均值中心化

均值中心化(Zero Centering)是数据预处理中的重要步骤,旨在通过去除均值来规范化数据分布。对于给定的输入数据集 X ,通常先在训练集上计算其均值向量 μ ,即 ,然后将其从训练集、验证集和测试集的每个样本中减去,从而得到归零化后的数据 = x i - μ 。这个过程可以确保数据在不同子集间的一致性和可比性,并有助于消除不同样本间的偏差,使数据更加规范化。均值归零化不仅能提升模型的训练稳定性,还能优化梯度下降的收敛速度,提高最终模型的学习效果和泛化能力。

7)标准化

标准化是数据预处理中的另一项重要技术,旨在将数据缩放到一个共同范围内。标准化通过消除不同特征之间的尺度差异,使模型的权重更加均衡,有助于建立更准确的模型。此外,标准化还包括将每个输入特征维度缩放到相似的数量级范围。由于不同特征通常以不同的单位进行测量,标准化处理后,所有特征被视为同等重要。标准化的具体做法是对每个特征先减去其在训练集上的均值,再除以该特征的标准差。

数据预处理可以确保分析过程的准确性和可靠性,为后续的数据挖掘工作奠定坚实的基础。无论数据多么复杂或混乱,经过适当的预处理,都可以变得更加清晰,并适用于机器学习模型的训练和分析。

2.8 参数初始化

完成数据预处理之后,下一步是为机器学习模型的训练过程做准备。其中,参数初始化起着至关重要的作用。合理的参数初始化不仅有助于加快模型的收敛速度,还能提高模型的最终性能。下面详细介绍模型训练的架构和步骤,以确保参数初始化能够顺利融入整个训练流程中。

2.8.1 训练架构

在构建机器学习算法时,通常需要定义一个架构(例如逻辑回归、支持向量机、神经网络)并对其进行训练从而学习参数。以下是神经网络的一般训练过程。

(1)初始化参数。

选择合适的方法对模型的参数进行初始化,如随机初始化、Xavier初始化和He初始化等。这一步为模型提供了初始权重和偏置值,是后续训练的基础。

(2)选择优化算法。

确定用于更新模型参数的优化算法,如梯度下降(Gradient Descent)、随机梯度下降(SGD)和Adam等。优化算法决定参数更新的策略和效率。

(3)重复以下步骤,直到满足停止条件。

①正向传播输入:将输入数据通过神经网络的各层计算每一层的输出,最终得到模型的预测结果。

②计算成本函数:评估模型预测结果与实际标签之间的差异,计算损失值(成本函数),如均方误差(MSE)、交叉熵损失等。

③使用反向传播计算梯度:通过反向传播算法,计算成本函数相对于每个参数的梯度,这些梯度表示参数调整的方向和幅度。

④根据优化算法更新参数:使用选定的优化算法根据计算得到的梯度调整每个参数,以减少成本函数的值。

(4)模型评估与预测。

在模型训练完成后,使用新的测试数据点,通过训练好的模型进行预测,评估其在未见数据上的表现。

通过上述步骤,机器学习模型能够从初始参数开始,经过多次迭代优化,逐步学习到能够准确预测的参数值。合理的数据预处理和参数初始化是确保模型训练有效性和高效性的关键因素。接下来将进一步探讨模型评估、超参数调优及实际应用中的优化策略。

2.8.2 权重初始值设置

现在来讨论权重的初始值设定问题。用0作为权重的最初值怎么样呢?当初始化方法为0时,所有的权重都被初始化为0,这会导致神经元在训练过程中学习相同的特征。这是因为在正向传播中,所有隐藏单元的激活值将相同,导致它们的梯度也相同。在反向传播中,这些相同的梯度将传播回输入层,导致所有权重的更新值相同。因此,在整个训练过程中,所有神经元都会以相同的方式响应输入数据,无法学习到不同的特征,限制了网络的表达能力。

实际上,任何常数初始化方案都会表现得非常糟糕。我们考虑一个具有两个隐藏单元的神经网络,并假设将所有偏置初始化为0,权重初始化为某个常数 α 。如果在该网络中正向传播一个输入( x 1 , x 2 ),则两个隐藏单元的输出将为ReLU( α x 1 + α x 2 )。因此,在训练过程中,这两个神经元将以完全相同的方式更新,导致无法学习到彼此差异化的特征,从而阻止神经网络对输入数据中复杂模式的有效建模。

1.使用值过小或过大的问题

使用过小或过大的权重虽然能够打破对称性,但可能会对模型训练产生不利影响。若权重值较大,激活值会随着网络层数的增加呈指数级增长,导致梯度爆炸,进而影响学习的稳定性,使训练过程变得缓慢。相反,若权重值较小,激活值会随层数增加呈指数级衰减,从而引发梯度消失,使得网络难以学习有效的特征。这两种情况都会导致神经网络的训练过程变得困难,要么训练速度极慢,要么模型出现发散,无法有效收敛。因此,在网络初始化时,权重的选择至关重要,通常需要采用合适的初始化方法(如Xavier初始化或He初始化)来保持梯度的稳定传播。

2.如何避免梯度消失或者爆炸

为了避免梯度消失或梯度爆炸,权重初始化需要满足两个关键条件。首先,激活值的平均值应接近0。当激活值的均值接近0时,网络能够学习到对输入数据的平均响应,从而保持梯度的一致性。这意味着网络对输入的“响应居中”,避免参数在训练过程中向某一极端方向偏移。如果激活值的均值远离0,梯度可能会在参数空间内朝某个特定方向集中,导致训练过程不稳定。其次,激活值的方差应在每一层保持一致。这确保信息在网络层间传递时不会出现剧烈变化。如果方差在不同层之间显著变化,可能会引发梯度消失或梯度爆炸。例如,在使用sigmoid激活函数时,较大的输入值会导致梯度趋近于零,从而引发梯度消失问题。

因此,选择合适的权重初始化方法对于高效训练至关重要。不恰当的初始化可能会导致梯度问题或降低模型对输入数据的敏感性,从而影响训练的稳定性和收敛速度。通过合理的初始化策略,可以有效打破对称性,使不同神经元学习到不同的特征,提高网络的表达能力,并帮助优化算法更快地收敛到全局最优解。因此,在设计神经网络时,选择合适的初始化方法是一个不可忽视的重要步骤。

3.正确选择初始值

基于前面提出的两个关键条件——激活值的均值应接近0以及方差在每一层中保持一致,反向传播中的梯度信号才能在各层中稳定传递,避免因数值过大或过小而出现梯度爆炸或梯度消失问题。为了实现这一点,梯度必须在网络各层之间保持适度的尺度,以便顺利传播至输入层。

(1)前一层的激活值为:

其中, g [ l -1] 是第 l -1层的激活函数, z [ l -1] 是第 l -1层的线性组合输出。

(2)第 l 层的线性组合输出为:

其中, W [ l ] 是第 l 层的权重矩阵, b [ l ] 是第 l 层的偏置向量。

(3)第 l 层的激活值为:

其中, g [ l ] 是第 l 层的激活函数。

(4)为了保证梯度在前向传播和反向传播过程中既不会爆炸也不会消失,通常要求以下条件:

在保持激活平均值接近0的基础上,确保信号在每层之间的传播不会逐渐偏离。例如,如果某一层的激活输出的均值突然偏离0,那么下一层的梯度传播可能会受到影响,导致训练不稳定。在前向传播中,期望和方差应当在各层之间保持一致,这样可以避免梯度爆炸或消失问题,使梯度信号能够有效地在整个网络中传播。

将权重初始化为接近0的小随机数通常是一种有效的起始化方法,因为它有助于打破对称性,避免所有神经元在训练初期学习到相同的特征。如果所有权重的初始值相同,则神经元会同步更新,导致它们始终学习到相同的特征,这将限制网络的表达能力。

通过将权重初始化为小的随机数,网络中的每个神经元在训练开始时能够学习到不同的特征,从而加速训练过程。此外,使用接近0的初始化值,尤其是在使用激活函数(如sigmoid或tanh)时,可以有效避免梯度消失或梯度爆炸的问题,这不仅提高了训练的稳定性,还有助于模型更快地收敛,最终提升整体性能。

虽然上面的这种初始化策略效果通常良好,但是在深度网络中,为了进一步提高性能,研究人员开发了一些更复杂的初始化方法,如Lecun初始化、Xavier/Glorot初始化和He初始化,这些方法可以根据网络结构和激活函数的特性来调整权重的初始值,使得网络更容易训练和收敛。以Lecun初始化为例,对于sigmoid和tanh激活单元,可在权重矩阵 W 上使用以下正态分布的随机初始化(均值为0,方差为1/ n {( l -1)} )方式,从而实现快速收敛并降低错误率:

换句话说,第 l 层的所有权重都是从均值为 μ =0,方差为 σ 2 =1/ n ( l -1) (其中 n ( l -1) 是第 l -1层中神经元的数量)的正态分布中随机采样的(即Lecun正态初始化),而偏置则被初始化为0。这种方法旨在保持激活的方差以及在各层之间传播的梯度的方差。如果没有这样初始化,梯度方差(代表信息量的一种指标)通常会随着在各层之间的反向传播而减小。

2.9 学习率

在模型开发过程中,学习率是最重要的指之一。学习率决定模型参数更新的步长,从而影响了模型学习的速度。在下面这个简单的梯度下降(Gradient Descent)公式中, α 表示学习率:

增大学习率 α 似乎可以加快收敛速度。然而,较大的学习率并不一定能确保更快地收敛。使用非常大的学习率可能会导致损失函数发散,因为参数的更新使模型越过了凸优化问题中的最小值点。在非凸模型(通常使用的模型)中,较大的学习率会导致不可预测的结果,但损失函数发散的可能性非常高。

避免损失函数发散的一种简单方法是采用非常小的学习率,这样就可以仔细地搜索参数空间。如果学习率设置得太小,可能会导致在合理的时间内无法收敛,或者陷入局部最小值。所以和其他超参数一样,学习率必须经过有效调整。

学习率退火(Learning Rate Annealing)是指在随机梯度下降训练过程中按预设计划逐步降低学习率的技术,它不同于自适应学习率(Adaptive Learning Rate)算法(如AdaGrad RMSProp、Adan)那样基于梯度统计为每个参数动态调整学习率。这种方法旨在提高模型性能的同时减少总体训练时间。它之所以被称为“退火”,因为它会随着训练进程的推进而逐渐减小,类似于物理中的降温过程。

在学习率退火方法中,学习率在训练期间逐步减小,从而以不同的速度更新网络权重。退火策略的优势在于,在训练过程的开始阶段使用较大的学习率值时,可以进行较大的修改。随着训练的进行,学习率逐渐减小,导致对权重的更新变得更小。学习率逐渐降低有助于更有效地收敛优化过程,可以提高模型的准确性和效率。

实施学习率退火的策略包括阶梯衰减(Step Decay)、指数衰减(Exponential Decay)和倒数时间衰减(Inverse Time Decay)。

阶梯衰减:在固定训练周期后,学习率按一定比例减小。这样可以在训练初期快速搜索参数空间,训练后期再进行微调。

指数衰减:学习率按指数规律逐渐减小。公式为:

其中, α 0 是初始学习率, k 是一个超参数。随着时间推移,学习率逐渐减小,确保模型更稳定地收敛到最优解。

倒数时间衰减:学习率随着训练周期数的增加按倒数减小。这种方式可以避免学习率过快减小,从而保持训练效果。

以上策略的核心思想是:当训练初期学习率较大时,模型可以快速调整参数,做出较大幅度的改变;而在训练后期,当学习率变小时,保证模型能逐步逼近最优解,避免剧烈的参数波动。

2.10 梯度下降优化算法

前面的章节已经使用梯度下降来更新神经网络的参数。本节将详细介绍梯度下降算法及其变体,以及在此基础上发展出的各种优化算法。梯度下降是一种用于最小化目标函数 J ( θ )的方法,其是沿着该目标函数梯度的相反方向来更新模型参数 θ ∈ℝ d 。学习率 α 确定每次更新的步长大小,从而控制优化过程的速度。

简单来说,梯度下降的过程就像沿着一个目标函数表面斜坡下行,寻找最低点。通过不断沿着斜坡最陡峭的方向前进,模型参数逐步接近目标函数的最小值。这个过程可以类比为在山坡上行走,步步向下,最终抵达山谷的最低点,也就是目标函数的最优解。

2.10.1 梯度下降的变体

梯度下降有3种变体,区别在于使用多少量的数据来更新目标函数的梯度。根据数据量的多少,在参数更新的准确性和执行更新所需时间之间进行权衡。

1.批量梯度下降

批量梯度下降(Batch Gradient Descent)是一种梯度下降算法,它使用整个训练数据集的数据来计算每一步的梯度,然后更新模型参数。这也是最原始的梯度下降算法。回顾一下梯度下降的定义:

具体步骤如下:

(1)计算整个训练数据集的梯度(即损失函数对所有训练样本的偏导数)。

(2)使用计算得到的梯度来更新模型参数,通常使用学习率(Learning Rate)来控制更新步长。

以下是批量梯度下降的伪代码,展示了如何使用整个训练集计算梯度并更新模型参数的过程。

批量梯度下降的优势在于每次更新都使用全体数据,可以更准确地指引参数朝着最优方向更新。由于要处理整个数据集,其可能在大规模数据集上比较耗时。我们根据梯度的方向和学习率的大小进行参数更新。对于凸形误差曲面,批量梯度下降保证收敛到全局最小值,对于非凸曲面,它则收敛到局部最小值。

2.随机梯度下降

和批量梯度下降相比,随机梯度下降(Stochastic Gradient Descent,SGD)对每个训练样本 x ( i ) 和标签 y ( i ) 进行参数更新。它的定义如下:

在批量梯度下降中,由于每次更新都要对整个数据集计算梯度,针对相似样本会出现重复(冗余)计算;随机梯度下降(SGD)则一次只用单个样本更新参数,从而显著减少这部分冗余计算。随机梯度下降通过一次执行一个更新来消除这种冗余。因此,它通常要快得多,还可以用于在线学习。随机梯度下降频繁执行更新,具有高方差,导致目标函数波动较大。虽然批量梯度下降会收敛到参数所在盆地的最小值,而随机梯度下降由于其波动性,一方面能够跳跃到新的、潜在更好的局部最小值,另一方面也使得它在接近精确最小值时的收敛变得更加复杂,因为随机梯度下降往往会超过最小值点(Overshooting)。然而,当逐渐降低学习率时,随机梯度下降在收敛性质上与批量梯度下降趋于一致,在非凸优化问题中,在几乎肯定收敛于某个局部最小值,而在凸优化问题中则几乎肯定收敛于全局最小值。

3.小批量梯度下降

小批量梯度下降(Mini-batch Gradient Descent)结合了上面两种方法,其也是最常用的梯度下降方法。它的定义如下:

小批量梯度下降算法的优点有两个方面:首先,通过减小参数更新的方差,使模型的收敛更加稳定。在训练过程中,模型需要稳定地朝着最优解前进,避免出现震荡或跳跃的情况。对于深度学习任务,这种稳定性尤为重要,因为它能确保学习过程更加可靠和可控。

其次,采用小批量梯度下降,可以充分利用现代深度学习库中高度优化的矩阵运算。这些优化使得计算相对于小批量的梯度非常高效。在深度学习中,通常需要处理大规模的数据集和复杂的网络结构,高效的矩阵运算能够大大提高训练速度,使模型更快地学习到数据的特征和规律。

通常情况下,小批量大小在50~256之间,但这个范围可能根据具体的应用场景而有所变化。无论采用什么小批量,小批量梯度下降通常是训练神经网络的首选算法。

小批量梯度下降法的Python示例代码如下:

4.梯度下降算法所遇到的难题

小批量梯度下降通常情况下比批量梯度下降和随机梯度下降表现好。然而,使用普通的小批量梯度下降并不能确保良好的收敛性,而且还面临一些需要克服的挑战,如选择适当的学习率非常困难。学习率太小会使收敛速度极慢,而学习率太大可能会阻碍收敛,使得损失函数在最小值附近波动甚至发散。

在训练过程中调整学习率是在上一节调整学习率中提过的另一种方法。例如,退火方法根据预定义的时间表(Learning Rate Schedules)或当相邻两个周期之间的目标变化低于某个阈值时降低学习率。然而,这些调度和阈值必须提前定义,无法自动适应数据集的特性。梯度下降算法中所有参数更新都采用相同的学习率。如果数据稀疏而特征的频率差异很大,全部以相同程度进行更新并不是最好的方法。相反,理想情况是对那些出现频率较低的特征进行更大幅度的更新,以更好地反映它们的重要性。

在神经网络中,非凸误差函数常常具有许多局部最小值,但实际问题并不是这些局部最小值,而是鞍点。鞍点是指一个维度上升,另一个维度下降的点,如图2-9所示。这些鞍点周围通常都是相同误差的平稳区域,使得随机梯度下降很难摆脱,因为在所有维度上梯度都接近于0。克服这些挑战需要采用更智能、更自适应的优化方法,以确保算法能够稳定、快速地收敛到全局最优解或较好的局部最优解。

图2-9 鞍点示例

2.10.2 动量

梯度下降是一种优化算法,它沿着目标函数的负梯度方向前进,以找到函数的最小值。在梯度下降中,我们从定义在权重上的误差函数的某一点开始,尝试移动到该函数的全局最小值点。在实际问题中,误差曲面通常非常复杂,只有通过先上升到更高的位置,然后下降到全局最小值点,才能取得进展。因此梯度下降面临的一个重要问题是,在具有大量曲率或梯度噪音的优化问题中,它可能在搜索空间内跳跃,而且可能会陷入梯度为0的区域。

动量(Momentum)是梯度下降优化算法的一种扩展,它允许搜索在搜索空间的某个方向上积累惯性,并且能够克服梯度噪音引起的振荡,在搜索空间的平坦区域上更顺畅地进行搜索,如图2-10所示。

图2-10 是否带有动量对随机梯度下降的影响

动量是一种方法,可以帮助加速随机梯度下降(SGD)在相关方向上的更新并抑制震荡,如图2-10右图所示。实现这一点的方式是将过去时间步的更新向量的一部分(其参数符号用表示)加到当前时间步的更新向量上。

动量可以想象为推动一个球从山上滚下。随着球不断下坡,它会积累越来越多的速度(动量),变得越来越快,直到达到最大速度为止(如果有空气阻力,速度不会无限增加,这时 γ <1)。参数更新也会发生类似的情况:动量项对于梯度方向相同的维度增加更新,对于梯度方向不同的维度减少更新,由此能够实现更快的收敛并减小震荡。

动量梯度更新的Python代码如下:

2.10.3 Nesterov加速梯度

Nesterov加速梯度(Nesterov Accelerated Gradient,NAG)是建立在动量方法基础上的一种优化算法,具有更快的收敛速度和减小震荡的优势。动量相当于一个盲目地顺着坡度滚动的球。如果有一个具有前瞻性概念的球,能够在坡度再次上升之前知道减速的时机就更好了,这就是NAG。

NAG的定义如下:

通过计算 θ - γv t -1 得到参数在下一次迭代中可能的位置估计,这是因为动量项乘以 γ 是对当前梯度的一个估计,而减去这个估计就相当于提前考虑了动量对参数位置的影响。

由于梯度是在预估的更新位置计算的, θ - γ v t -1 提供了对下一步位置的近似。这种方法在计算梯度之前预估参数的移动方向,能够提前了解参数的变化趋势。

这种做法使得在更新参数时更有针对性和智能性。通过提前计算可能的下一个位置,NAG能够更准确地估计梯度并调整参数的更新方向,从而改善优化的效果,这是NAG相对于普通动量的一项优势。

下面是NAG的简化版Python代码:

2.10.4 自适应梯度算法

自适应梯度算法(Adaptive Gradient Algorithm,AdaGrad)是一种基于梯度的优化算法,其独特之处在于根据参数自适应地调整学习率。对于不经常出现的参数,AdaGrad执行较大的更新,而对于频繁出现的参数则执行较大幅度的更新。这使得自适应梯度算法特别适用于处理稀疏数据。例如,Pennington等人成功地使用AdaGrad来训练GloVe词嵌入,因为不经常出现的词汇需要比常见词汇执行更大的更新。

在传统的优化算法中,所有的参数 θ 同时接收相同的学习率 α 进行更新。例如,对于一个具有两个参数的简单模型,更新规则可能如下:

其中, 分别表示损失函数对参数 θ 1 和参数 θ 2 的梯度。相比之下,在AdaGrad中,每个参数 θ i 都有自己独特的学习率,这个学习率会根据历史梯度的平方和进行调整。AdaGrad的更新规则对于每个参数 θ i 可能是不同的。AdaGrad在每个时间步 t 中会为每个参数 θ i 使用不同的学习率,首先说明AdaGrad如何为每个参数分配独立的学习率并分别执行更新,然后将其向量化。将 g t,i 设置为目标函数相对于参数 θ i 在时间步 t 的梯度,其更新规则如下:

每个时间步 t 的每个参数 θ i 的SGD更新如下:

在AdaGrad的更新规则中,针对每个参数 θ i ,它会根据之前计算得到的 θ i 的梯度来修改每个时间步 t 的总体学习率 α

其中, G t ∈ℝ d × d 是一个对角矩阵,其每个对角元素 i , i 是到时间步 t 为止 θ i 的梯度平方和。 ε 是一个平滑项,用于避免除以0的情况(通常在1×10 -8 的数量级上)。AdaGrad的学习率调整基于历史梯度信息,通过维护参数累积的历史梯度平方和,并将其平方根作为学习率的分母。对于出现频率较低的参数,历史梯度平方和较小,学习率较大;而对于出现频率较高的参数,历史梯度平方和较大,学习率较小。下面进行详细解释。

假设有一个包含3个参数的模型,即 d =3。在时间步 t =1时,每个参数 θ 1 θ 2 θ 3 的梯度分别为2、3和1。那么 G 1 就是一个对角矩阵,其对角线上的元素为这些梯度的平方和,即对角线元素分别为2 2 、3 2 和1 2 。因此, G 1 是一个3×3的对角矩阵:

当下一个时间步 t =2时,梯度分别为1、2和3,则 G 2 的对角线元素将是之前的平方和加上新的平方和:

随着时间的推移,对角矩阵 G t 会累积每个参数的梯度平方和。AdaGrad的学习率调整基于历史梯度平方和,因此对于频率较低的参数,其历史梯度平方和较小。较小的历史梯度平方和会导致学习率较大,使得这些参数在更新时可以有更大的步幅,以更快地适应它们的变化。这有助于对付那些在训练数据中不频繁出现但可能对模型性能产生重要影响的参数。如果没有平方根运算,该算法的性能会大大下降。

由于 G t 包含对所有参数 θ 的过去梯度的平方和,现在可以通过执行 G t g t 之间的逐元素矩阵-向量乘法(用符号⊙表示)来向量化实现:

AdaGrad的主要优势之一是消除了手动调整学习率的需求,大多数实现使用默认值0.01并保持不变。AdaGrad的主要弱点也在于它在分母中累积了平方梯度:由于每个添加的项都是正的,累积和在训练过程中不断增加。这反过来导致学习率收缩,最终变得无限小,此时算法将无法获取额外的知识。

AdaGrad的Python简易版代码如下:

2.10.5 Adadelta优化算法

Adadelta是一种自适应学习率的优化算法,旨在解决AdaGrad算法中学习率逐渐减小的问题。其核心思想是根据参数的历史梯度信息自适应地调整学习率。与AdaGrad从训练开始累积全部梯度平方值不同,Adadelta仅在一个固定大小的滑动窗口内累积历史梯度信息。为了避免低效地存储 w 个先前的平方梯度,梯度和的计算以所有过去平方梯度的衰减平均形式递归定义。时间步 t 的运行平均 取决于先前的平均值和当前的梯度。这种设计有助于解决学习率快速衰减的问题,使得算法更适应不同参数的更新需求。

Adadelta核心的衰减平均定义如下:

是过去梯度的平方的衰减平均。当前时刻 t 的梯度平方的衰减平均取决于上一时刻 t -1的梯度平方的衰减平均和当前时刻 t 的梯度平方。衰减平均意味着过去的信息在计算中逐渐减弱,对当前时刻的影响逐渐降低。这是通过引入衰减系数(通常用0≤γ<1表示)来实现的,该系数决定了过去信息的权重。因此, 是对过去梯度平方进行的加权平均,其中,权重随时间逐渐减小,这种性质使得算法能够适应梯度变化。

在2.10.4节中,向量化更新后的表达式为:

G t 直接替换为 就有了Adadelta参数更新表达式的雏形:

分母就是梯度的均方根(Root Mean Square,加权平均也是平均),所以可以进一步简化为:

Adadelta进一步处理了一个之前所有梯度下降算法都没有解决的问题,就是参数 θ 的更新受到梯度值 g 的直接影响,这可能会导致在参数更新中出现较大的波动,因为它没有充分考虑参数更新的大小。Adadelta引入了参数更新的平方的衰减平均 ,可以更好地适应参数更新的大小。 的定义是一样的,区别仅仅是Δ θ 2 而非 g 2

同样也可以用均方根的形式简化

由于 是未知的(在当前时刻还不知道Δ θ t ,因为这是要求的值),所以用上一步RMS[Δ θ ] t -1 的值来近似RMS[Δ θ ] t 。这样,学习率 α 不再需要手动调整,Adadelta能够根据参数更新的历史信息自动调整步长,从而实现更稳定的优化过程。

Adadelta的最终更新表达式为:

Adadelta的Python简易版代码如下:

2.10.6 RMSprop优化算法

RMSprop和Adadelta几乎同时出现,都是为了解决AdaGrad学习率急剧减小的问题。RMSprop实际上与前面推导的Adadelta的第一个更新向量是相同的。RMSprop同样通过平方梯度的指数衰减平均来缩放梯度,从而实现自适应学习率。

1.RMSprop的更新公式

(1)RMSprop的更新公式:

其中, 是梯度平方的指数移动平均(Exponential Moving Average,EMA), γ 是衰减系数, g t 是当前的梯度。

(2)参数更新:

其中, α 是全局学习率, ε 是防止除0的小常数。

2.RMSprop和Adadelta的主要区别

RMSprop和Adadelta在全局学习率和参数更新量的处理上存在显著差异。在全局学习率方面,RMSprop依赖于一个全局学习率,并通过梯度的均方根(RMS)估计对学习率进行缩放,而Adadelta则无须手动设置全局学习率,而是通过参数更新量的均方根动态调整步长,实现完全自适应的学习率调整。在参数更新量的平滑方面,RMSprop仅对梯度的平方进行平滑,直接使用计算得到的更新步长。而Adadelta则对梯度的平方和参数更新量的平方同时进行平滑,从而使更新步长的缩放更加稳定,提升了模型训练的健壮性。

3.小结

虽然RMSprop和Adadelta都利用梯度平方的指数加权移动平均来调整学习率,但是它们在具体的参数更新方式上存在本质差异。RMSprop通过计算梯度的均方根(RMS)直接缩放学习率,以调整每次参数更新的幅度;而Adadelta则采用更新量的均方根来调节步长,实现了完全自适应的更新机制,无须依赖全局学习率。这种差异使得Adadelta能够更灵活地适应不同问题的优化需求。

RMSprop的Python简易版代码如下:

2.10.7 Adaptive Moment Estimation(Adam)优化算法

Adam是一种优化算法,旨在自适应地为每个参数计算学习率。Adam的更新规则实际上是RMSProp的一种变体,但加入了类似动量的更新。Adam算法维护两个移动平均向量,分别表示梯度的一阶矩(均值)和二阶矩(未中心化的方差)。这两个矩量分别记为 m t v t

具体而言,Adam算法的更新规则如下:

(1)计算一阶矩 m t (均值):

其中, g t 是时间步 t 的梯度, β 1 是用于控制一阶矩衰减的超参数。

(2)计算二阶矩 v t (未中心化的方差):

其中, β 2 是用于控制二阶矩衰减的超参数。

(3)对一阶和二阶矩进行偏差校正:

这一步是为了抵消在初始时间步和衰减率较小时引入的偏差。

(4)使用偏差校正后的一阶和二阶矩来更新参数:

其中, α 是学习率, ε 是为了数值稳定性而添加的极小常数。

Adam的Python简易版代码如下:

动量优化算法引入了历史梯度信息,以模拟物体在运动中的积累速度和方向。与传统的梯度下降仅依赖当前梯度不同,动量优化算法在参数更新时会综合考虑当前和过去的梯度,从而增强方向一致性并加速收敛。这有助于加速收敛过程,特别是在面临曲折、崎岖的损失曲面时,可以减少震荡并更快地找到全局最小值。Adam算法结合了梯度信息和历史信息,使得参数更新更加平稳和高效。

2.11 神经网络的验证及调整方法

在了解了神经网络的基本结构之后,还需要确认它的计算是否正确,尤其是梯度的计算。为此,可以使用一种叫作“数值梯度检验”的方法来验证模型中的梯度是否正确。这个方法的原理是:通过对参数进行非常小的变化,计算出损失函数的数值导数,再将这个数值导数与神经网络中计算出的梯度进行比较。如果两者相近,则说明梯度的计算是正确的。

虽然梯度检验在直接用于网络训练时计算效率较低,但是它可以非常精确地估算相对于任何参数的导数,因此,它是验证解析梯度正确性的一个有效手段。如果给定具有参数向量 θ 和损失函数 J 的模型,则关于 θ 的数值梯度可以用以下中心差分公式表示:

其中, e 是一个小的数值(通常在1×10 -5 左右)。 J ( θ ( i +) )表示在进行前向传播时,给定输入的情况下,参数 θ 的第 i 个元素被扰动+ e 时计算的误差。 J ( θ ( i -) )表示在相同输入情况下,参数 θ 的第 i 个元素扰动- e 时计算的误差。因此,通过两次前向传播,可以近似计算模型中任何给定参数元素的梯度。这种数值梯度的定义直接来源于导数的定义。虽然这种数值梯度计算方法比较精确,但是每次计算单个元素的梯度都需要在网络中进行两次前向传播,计算代价非常高。因此,这种方法通常仅用于验证梯度的正确性,在实际训练中并不使用。

梯度检验的Python代码如下:

2.11.1 正则化

在解释正则化之前,有必要先了解几个关键的概念。这些概念不仅是理解正则化的基础,也是深入掌握机器学习模型训练和优化的核心。这些概念包括模型过拟合、欠拟合以及正则化项在损失函数中的作用和影响。只有清楚这些基础概念,才能全面理解正则化在提高模型泛化能力和减少模型复杂度方面的意义。

1.过拟合和欠拟合

要训练机器学习模型,需要提供一些数据供其学习。将数据点绘制出来并找出最能反映变量间关系的那条线,这个过程称为数据拟合。如果模型能够准确捕捉数据中的必要模式,同时避开随机噪声和无关模式,那么这种方式就称为最佳拟合。

当机器学习模型对训练数据观察得过多时,不仅会学到重要的模式,还会捕捉到其中的噪声和无关的模式。虽然在训练数据集上表现得很好,但是由于对噪声的过度拟合(Over-fitting),它在测试数据集上无法做出准确预测。过拟合的本质是模型试图将每个数据点都紧密地拟合到曲线上,而不仅仅是学习到数据中的真正规律。

相反,如果模型对数据的观察不足,它就无法找到有效的模式,也无法很好地适应测试数据集,更别提在新数据上表现出色了。在这种情况下,模型既没能学到变量间的关系,也无法准确预测或分类新的数据点,这就是所谓的欠拟合(Under-fitting)。

2.偏差和方差

当模型偏差(Bias)较高时,它无法从数据中有效地进行学习。这种模型对训练数据关注不足,过于简单化,导致验证误差和训练误差都较高且相似,既在训练数据上表现不佳,又无法在新数据上取得好结果,这就是所谓的欠拟合。

方差(Variance)反映模型对特定数据集的敏感度。高方差的模型过度关注训练数据,不能很好地泛化到新数据上。这种模型通常在训练数据上表现出色,但验证误差和训练误差之间的差距较大,在测试数据上会有较高的错误率,这就是过拟合的表现。

最理想的模型能够同时捕捉数据中的重要模式,并能很好地泛化到新数据上。这种平衡出现在偏差和方差都处于适当水平时,这种方式称为偏差-方差折衷。通过调节模型复杂度,可以在过拟合和欠拟合之间找到这种平衡。

3.惩罚项/正则项

与许多机器学习模型一样,神经网络也容易出现过拟合。在过拟合情况下,模型在训练数据集上表现得近乎完美,但无法在未知数据上泛化。为了解决这种过拟合(或“高方差”)问题,常用的一种技术是引入L2正则化惩罚。其核心思想是在损失函数 J 中添加一个额外项,当参数过于复杂时会产生相应的惩罚。添加正则项后,整体损失函数的计算方式如下:

其中,‖ W ( i ) F 是Frobenius范数,其定义为:

Frobenius范数具有二次性质(计算矩阵各元素的平方和),因此L2正则化有效地降低了模型的灵活性,减少了过拟合现象。这种约束也可以解释为贝叶斯先验信念,即最优权重接近于0——这种接近程度取决于 λ 的值。

λ 是一个超参数,用于控制正则化项相对于原始代价函数的权重。选择正确的 λ 值非常关键,必须通过超参数调优来确定。如果 λ 值过高,则大部分权重会被设置得太接近于0,导致模型无法从训练数据中学到有用信息,在训练、验证和测试集中表现较差。如果 λ 值太低,就容易再次发生过拟合。

另外,偏差项不受正则化的影响,不会计入上述代价项中。可以将偏差看作模型对数据的平均倾向,而权重则控制了模型对数据的波动性。正则化主要关注减小权重的波动性,以避免过度拟合,而不会对偏差进行类似的操作,因为它不会引入与数据噪声相关的变化。这样的处理可以确保模型保持适度的复杂性,同时能够更好地泛化到未知数据。

2.11.2 暂退法

在神经网络调参中,暂退法(Dropout)是一种常用的正则化技术,用于减少过拟合的风险。Dropout的核心思想是在训练期间随机忽略部分神经元,使模型在训练时不会过于依赖某些特定的神经元。

1.暂退法的工作原理

暂退法是通过在训练期间随机“丢弃”部分神经网络节点来实现的。这种方法使得网络在每次前向和后向传播中,都像是一个随机结构的子网络。也就是说,模型的每一层在每次迭代时,看起来都像是由不同数量的神经元和不同的连接组成的。

在训练过程中,以概率 p 保持每个神经元的活性,即有1- p 的概率将该神经元的输出设为0。这样可以防止神经元之间的共适应性,确保模型从数据中学到更稳健、更有意义的信息,进而有效减少过拟合。

这种随机丢弃节点的操作实际上相当于同时训练了大量不同结构的“子网络”,并在训练过程中对这些子网络的预测结果进行平均。正因为如此,Dropout能够增强模型的泛化能力,从而在测试数据上取得更好的性能。

2.Dropout在训练和测试中的区别

在每次前向和后向传播中,Dropout会随机丢弃部分神经元,仅对活跃的神经元进行计算。这种随机丢弃机制使模型在训练时变得更加嘈杂,因为不同神经元被随机移除,每个神经元在概率基础上对输入负责。当进行反向传播时,只有在前向传播中保持活跃的神经元才会传递梯度。在测试阶段,模型不再丢弃神经元,而是使用完整的网络来计算预测结果。为了确保训练和测试期间神经元输出的期望值一致,通常采取两种调整方式:在测试时将每个神经元的输出乘以保留概率 p ,或在训练时对保持活跃的神经元输出除以 p (即“缩放”方式)。这种调整方法能够确保在训练和测试期间神经元输出的期望值大致相同,从而提升模型预测的稳定性。

3.Dropout的提出与应用

Srivastava等人在“Dropout: A Simple Way to Prevent Neural Networks from Overfitting”一文中首次提出了这种技术。Dropout的提出极大地推动了神经网络正则化方法的发展,并被广泛应用于各种深度学习模型中。

在实际应用中,Dropout通常被应用在每个神经元层的输出 h 上,以概率 p 保持活性。这种随机丢弃节点的方式使网络在训练过程中变得更加稳健,从而提升模型在实际任务中的表现。

总的来说,Dropout是一种简单而有效的正则化方法,在训练时可随机忽略部分神经元,确保模型不会过度依赖特定的神经元,从而有效减少过拟合。其本质是在训练过程中同时训练大量不同结构的“子网络”,并在测试时使用完整网络进行预测,这种方法使模型在处理新数据时具备更强的泛化能力。

参考文献

[1] Goodfellow I, Bengio Y, Courville A. Deep learning [M]. Cambridge, MA: MIT Press, 2016: 217-219.

[2] Srivastava N, Hinton G, Krizhevsky A, et al. Dropout: A simple way to prevent neural networks from overfitting [J]. Journal of Machine Learning Research, 2014, 15 (1): 1929-1958.

[3] He K, Zhang X, Ren S, Sun J. Deep residual learning for image recognition [C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR). Las Vegas, NV: IEEE, 2016: 770-778.

[4] Bishop C M. Pattern recognition and machine learning [M]. New York, NY: Springer, 2006: 249-253.

[5] Rumelhart D E, Hinton G E, Williams R J. Learning representations by back-propagating errors [J]. Nature, 1986, 323(6088): 533-536.

[6] Nair V, Hinton G E. Rectified linear units improve restricted Boltzmann machines [C]//Proceedings of the 27th International Conference on Machine Learning (ICML). Haifa, Israel: Omnipress, 2010: 807-814.

[7] Ng A Y. Feature selection, L1 vs. L2 regularization, and rotational invariance [C]//Proceedings of the 21st International Conference on Machine Learning (ICML). Banff, Canada: Association for Computing Machinery, 2004: 78-85.

[8] LeCun Y, Bengio Y, Hinton G. Deep learning [J]. Nature, 2015, 521(7553): 436-444.

[9] Hochreiter S, Schmidhuber J. Long short-term memory [J]. Neural Computation, 1997, 9(8): 1735-1780.

[10] Kingma D P, Ba J L. Adam: A method for stochastic optimization [C]//Proceedings of the 3rd International Conference on Learning Representations (ICLR). San Diego, CA: OpenReview, 2015: 1-15. HwPuvcYD3tBb/Cskm/fK0xqNnR2EH9Snz74KV2djafQnrj64QEENBhYsou6x6hPA

点击中间区域
呼出菜单
上一章
目录
下一章
×