Skip to content

第7章 梯度与初始化

第 6 章介绍了迭代优化算法。这些算法是用于求函数最小值的通用方法。在神经网络的场景下,它们寻找使损失最小化的参数,从而使模型能够从输入准确预测训练输出。基本方法是随机选择初始参数,然后进行一系列小的调整,使损失平均而言逐步降低。每次调整都基于损失对当前位置处参数的梯度。

本章讨论两个神经网络特有的问题。首先,我们考虑如何高效地计算梯度。这是一个严峻的挑战,因为撰写本书时最大的模型拥有约 1012 个参数,而训练算法的每次迭代都需要计算每个参数的梯度。其次,我们考虑如何初始化参数。如果初始化不当,初始损失及其梯度可能会极端地大或极端地小。在任何一种情况下,都会阻碍训练过程。

7.1 问题定义

考虑一个网络 f[x,ϕ],它具有多元输入 x、参数 ϕ,以及三个隐藏层 h1h2h3

(7.1)h1=a[β0+Ω0x]h2=a[β1+Ω1h1]h3=a[β2+Ω2h2]f[x,ϕ]=β3+Ω3h3,

其中函数 a[] 对输入的每个元素分别施加激活函数。模型参数 ϕ={β0,Ω0,β1,Ω1,β2,Ω2,β3,Ω3} 由每层之间的偏置向量 βk 和权重矩阵 Ωk 组成(图 7.1)。

我们还有单个损失项 i,它返回给定模型预测 f[xi,ϕ] 与真实标签 yi 时训练输入 xi 的负对数似然。例如,这可以是最小二乘损失 i=(f[xi,ϕ]yi)2。总损失是所有训练数据上这些项的求和:

(7.2)L[ϕ]=i=1Ii.

训练神经网络最常用的优化算法是随机梯度下降(SGD),它按如下方式更新参数:

(7.3)ϕt+1ϕtαiBti[ϕt]ϕ,

其中 α 是学习率,Bt 包含迭代 t 的批次索引。为了计算该更新,我们需要计算导数:

(7.4)iβkiΩk,

对每层 k{0,1,,K} 的参数 {βk,Ωk} 以及批次中的每个索引 i。本章第一部分描述反向传播算法(backpropagation algorithm),它能高效地计算这些导数。

在本章第二部分,我们考虑在训练开始前如何初始化网络参数。我们描述选择初始权重 Ωk 和偏置 βk 的方法,以使训练保持稳定。

7.2 计算导数

损失的导数告诉我们,当对参数做出微小改变时,损失如何变化。优化算法利用这一信息来调整参数以使损失减小。反向传播算法计算这些导数。其数学细节较为复杂,因此我们先做两个直观观察。

观察 1: Ωk 中的每个权重将源隐藏单元处的激活值相乘,并将结果加到目标隐藏单元上。因此,对权重的任何微小改变的效果都会被源隐藏单元的激活值放大或衰减。由此,我们需要对批次中的每个数据样本运行网络,并存储所有隐藏单元的激活值。这被称为前向传播(forward pass)(图 7.1)。所存储的激活值随后将用于计算梯度。

观察 2: 偏置或权重的微小改变会引起后续网络中的一连串变化。该改变修改其目标隐藏单元的值。这进而改变后续层中隐藏单元的值,然后再改变更后面一层的隐藏单元,如此传递,直到改变模型输出,最终改变损失。

因此,要知道改变一个参数如何影响损失,我们还需要知道后续每个隐藏层的变化如何传递给其后继者。在考虑同一层或更早层的其他参数时,也需要这些同样的量。因此我们可以一次性计算并重复利用它们。例如,考虑计算馈入隐藏层 h3h2h1 的权重微小改变的效果:

  • 要计算馈入隐藏层 h3 的权重或偏置的微小改变如何影响损失,我们需要知道 (i) 层 h3 的变化如何改变模型输出 f,以及 (ii) 输出的变化如何改变损失 (图 7.2a)。
  • 要计算馈入隐藏层 h2 的权重或偏置的微小改变如何影响损失,我们需要知道 (i) 层 h2 的变化如何影响 h3,(ii) h3 如何改变模型输出,以及 (iii) 输出如何改变损失(图 7.2b)。
  • 要计算馈入隐藏层 h1 的权重或偏置的微小改变如何影响损失,我们需要知道 (i) 层 h1 的变化如何影响层 h2,(ii) 层 h2 的变化如何影响层 h3,(iii) 层 h3 如何改变模型输出,以及 (iv) 模型输出如何改变损失(图 7.2c)。

图 7.1

图 7.1 反向传播前向传播。目标是计算损失 关于每个权重(箭头)和偏置(未显示)的导数。换言之,我们想知道每个参数的微小改变将如何影响损失。每个权重将其源处的隐藏单元激活值相乘,并将结果贡献给目标处的隐藏单元。因此,对权重的任何微小改变的效果都会被源隐藏单元的激活值缩放。例如,蓝色权重作用于第 1 层的第二个隐藏单元;如果该单元的激活值翻倍,则对蓝色权重微小改变的效果也会翻倍。因此,要计算权重的导数,我们需要计算并存储隐藏层处的激活值。这被称为前向传播,因为它涉及按顺序运行网络方程。

图 7.2

图 7.2 反向传播的反向传播。a) 要计算馈入层 h3 的权重(蓝色箭头)的改变如何影响损失,我们需要知道 h3 中的隐藏单元如何改变模型输出 f,以及 f 如何改变损失(橙色箭头)。b) 要计算馈入 h2 的权重(蓝色箭头)的微小改变如何影响损失,我们需要知道 (i) h2 中的隐藏单元如何改变 h3,(ii) h3 如何改变 f,以及 (iii) f 如何改变损失(橙色箭头)。c) 类似地,要计算馈入 h1 的权重(蓝色箭头)的微小改变如何影响损失,我们需要知道 h1 如何改变 h2,以及这些改变如何通过网络传播到损失(橙色箭头)。反向传播先在网络末端计算导数,然后反向回溯以利用这些计算中固有的冗余性。

当我们反向遍历网络时,可以发现大多数所需的项已在前一步中计算过,无需重复计算。以这种方式反向遍历网络来计算导数,被称为反向传播(backward pass)。

反向传播背后的思想相对容易理解。然而,推导需要矩阵微积分,因为偏置项和权重项分别是向量和矩阵。为了帮助理解其底层机制,下一节先用一个更简单的标量参数玩具模型来推导反向传播。然后我们在 7.4 节将同样的方法应用于深度神经网络。

7.3 玩具示例

考虑一个模型 f[x,ϕ],它有八个标量参数 ϕ={β0,ω0,β1,ω1,β2,ω2,β3,ω3},由函数 sin[]exp[]cos[] 复合而成:

(7.5)f[x,ϕ]=β3+ω3cos[β2+ω2exp[β1+ω1sin[β0+ω0x]]],

以及最小二乘损失函数 L[ϕ]=ii,其中各项为:

(7.6)i=(f[xi,ϕ]yi)2,

其中 xi 是第 i 个训练输入,yi 是第 i 个训练输出。你可以将其想象为一个简单的神经网络,每层有一个输入、一个输出、一个隐藏单元,以及各层之间分别使用 sin[]exp[]cos[] 作为激活函数。

我们的目标是计算导数:

(7.7)iβ0,iω0,iβ1,iω1,iβ2,iω2,iβ3,iω3.

当然,我们可以手动推导这些导数的表达式并直接计算它们。但是,其中一些表达式相当复杂。例如:

(7.8)iω0=2(β3+ω3cos[β2+ω2exp[β1+ω1sin[β0+ω0xi]]]yi)ω1ω2ω3xicos[β0+ω0xi]exp[β1+ω1sin[β0+ω0xi]]sin[β2+ω2exp[β1+ω1sin[β0+ω0xi]]].

这类表达式既难以正确推导和编码,又未能利用其中固有的冗余性;注意上式中三个指数项是相同的。

反向传播算法是一种高效的方法,可同时计算所有这些导数。它包含 (i) 前向传播,在其中我们计算并存储一系列中间值和网络输出;以及 (ii) 反向传播,在其中我们从网络末端开始计算每个参数的导数,并在向起点回溯时重复利用先前的计算。

图 7.3

图 7.3 反向传播前向传播。我们依次计算并存储每个中间变量,直到最终计算出损失。

前向传播: 我们将损失的计算视为一系列计算步骤:

(7.9)f0=β0+ω0xih1=sin[f0]f1=β1+ω1h1h2=exp[f1]f2=β2+ω2h2h3=cos[f2]f3=β3+ω3h3i=(f3yi)2.

我们计算并存储中间变量 fkhk 的值(图 7.3)。

反向传播 #1: 现在我们计算 i 关于这些中间变量的导数,但按逆序进行:

(7.10)if3,ih3,if2,ih2,if1,ih1,if0.

第一个导数很直接:

(7.11)if3=2(f3yi).

下一个导数可以用链式法则计算:

(7.12)ih3=f3h3if3.

左边询问当 h3 改变时 i 如何变化。右边告诉我们可以将其分解为 (i) 当 h3 改变时 f3 如何变化,以及 (ii) 当 f3 改变时 i 如何变化。在原始方程中,h3 改变 f3f3 改变 i,这些导数代表了这条链的效应。注意这些导数中的第二个已经在前一步中计算过了,另一个是 β3+ω3h3 关于 h3 的导数,即 ω3

图 7.4

图 7.4 反向传播的反向传播 #1。我们从函数末端反向计算损失关于中间量的导数 i/fki/hk。每个导数由前一个导数乘以 fk/hkhk/fk1 形式的项得到。

我们以这种方式继续,计算输出关于这些中间量的导数(图 7.4):

(7.13)if2=h3f2(f3h3if3)ih2=f2h2(h3f2f3h3if3)if1=h2f1(f2h2h3f2f3h3if3)ih1=f1h1(h2f1f2h2h3f2f3h3if3)if0=h1f0(f1h1h2f1f2h2h3f2f3h3if3).

在每种情况下,括号内的量已在上一步中计算过,最后一项具有简单的表达式。这些方程体现了上一节的观察 2(图 7.2);如果我们按逆序计算,就可以重复利用之前计算过的导数。

反向传播 #2: 最后,我们考虑当参数 {βk}{ωk} 改变时损失 i 如何变化。再次应用链式法则(图 7.5):

(7.14)iβk=fkβkifkiωk=fkωkifk.

在每种情况下,右边的第二项已在方程 7.13 中计算过。当 k>0 时,fk=βk+ωkhk,因此:

(7.15)fkβk=1fkωk=hk.

图 7.5

图 7.5 反向传播的反向传播 #2。最后,我们计算 i/βki/ωk。每个导数由 i/fk 乘以 fk/βkfk/ωk 得到。

这与上一节的观察 1 一致;权重 ωk 变化的效果正比于源变量 hk 的值(前向传播中已存储)。从 f0=β0+ω0xi 得到的最后的导数是:

(7.16)f0β0=1f0ω0=xi.

反向传播比单独计算各导数(如方程 7.8)既简单又高效。

7.4 反向传播算法

现在我们对三层网络(图 7.1)重复这一过程。直觉和大部分代数运算是相同的。主要区别在于中间变量 fkhk 是向量,偏置 βk 是向量,权重 Ωk 是矩阵,而且我们使用 ReLU 函数而非 cos[] 等简单代数函数。

前向传播: 我们将网络写为一系列顺序计算:

(7.17)f0=β0+Ω0xih1=a[f0]f1=β1+Ω1h1h2=a[f1]f2=β2+Ω2h2h3=a[f2]f3=β3+Ω3h3i=l[f3,yi].

图 7.6

图 7.6 修正线性单元的导数。修正线性单元(橙色曲线)在输入小于零时返回零,否则返回输入本身。它的导数(青色曲线)在输入小于零时返回零(因为此处斜率为零),在输入大于零时返回一(因为此处斜率为一)。

其中 fk1 表示第 k 个隐藏层的预激活值(即经过 ReLU 函数 a[] 之前的值),hk 包含第 k 个隐藏层的激活值(即 ReLU 函数之后的值)。项 l[f3,yi] 表示损失函数(例如最小二乘损失或二元交叉熵损失)。在前向传播中,我们逐步完成这些计算并存储所有中间量。

反向传播 #1: 现在让我们考虑当预激活值 f0f1f2 改变时损失如何变化。应用链式法则,损失 i 关于 f2 的导数表达式为:

(7.18)if2=h3f2f3h3if3.

右边三项的大小分别为 D3×D3D3×DfDf×1,其中 D3 是第三层隐藏单元数,Df 是模型输出 f3 的维度。

类似地,我们可以计算当 f1f0 改变时损失如何变化:

(7.19)if1=h2f1f2h2(h3f2f3h3if3)(7.20)if0=h1f0f1h1(h2f1f2h2h3f2f3h3if3).

注意在每种情况下,括号内的项已在前一步中计算过。通过反向遍历网络,我们可以重复利用先前的计算。

此外,各项本身都很简单。反向计算方程 7.18 右边的各项,我们有:

  • 损失 i 关于网络输出 f3 的导数 i/f3 取决于损失函数,但通常具有简单的形式。

  • 网络输出关于隐藏层 h3 的导数 f3/h3 为:

(7.21)f3h3=h3(β3+Ω3h3)=Ω3T.

如果你不熟悉矩阵微积分,这个结果可能不太直观。

  • 激活函数输出 h3 关于其输入 f2 的导数 h3/f2 取决于激活函数。它将是一个对角矩阵,因为每个激活值只取决于对应的预激活值。对于 ReLU 函数,对角项在 f2 小于零的地方为零,其余地方为一(图 7.6)。我们不实际乘以这个矩阵,而是提取对角项作为向量 I[f2>0] 并进行逐元素乘法,这样更高效。

方程 7.19 和 7.20 右边的项具有类似的形式。当我们反向遍历网络时,交替执行 (i) 乘以权重矩阵 ΩkT 的转置,以及 (ii) 基于馈入隐藏层的输入 fk1 进行阈值化。这些输入在前向传播中已经存储过。

反向传播 #2: 现在我们知道如何计算 i/fk,可以集中精力计算损失关于权重和偏置的导数。要计算损失关于偏置 βk 的导数,我们再次使用链式法则:

(7.22)iβk=fkβkifk=βk(βk+Ωkhk)ifk=ifk,

这已在方程 7.18 和 7.19 中计算过。

类似地,权重矩阵 Ωk 的导数为:

(7.23)iΩk=fkΩkifk=Ωk(βk+Ωkhk)ifk=ifkhkT.

从第二行到第三行的推导并不显然。然而,这个结果很有意义。最终结果是一个与 Ωk 大小相同的矩阵。它线性地依赖于 hk(在原表达式中 hkΩk 所乘)。这也与最初的直觉一致:Ωk 中权重的导数正比于它们所乘的隐藏单元值 hk。回忆一下,我们已在前向传播中计算过这些值。

7.4.1 反向传播算法总结

我们现在简要总结最终的反向传播算法。考虑一个深度神经网络 f[xi,ϕ],它接收输入 xi,有 K 个使用 ReLU 激活的隐藏层,以及单个损失项 i=l[f[xi,ϕ],yi]。反向传播的目标是计算损失关于偏置 βk 和权重 Ωk 的导数 i/βki/Ωk

前向传播: 我们计算并存储以下量:

(7.24)f0=β0+Ω0xihk=a[fk1]k{1,2,,K}fk=βk+Ωkhk.k{1,2,,K}

反向传播: 我们从损失函数 i 关于网络输出 fK 的导数 i/fK 开始,反向遍历网络:

(7.25)iβk=ifkk{K,K1,,1}iΩk=ifkhkTk{K,K1,,1}ifk1=I[fk1>0](ΩkTifk),k{K,K1,,1}

其中 表示逐元素乘法,I[fk1>0] 是一个向量,在 fk1 大于零的位置包含 1,其余位置为 0。最后,我们计算第一组偏置和权重的导数:

(7.26)iβ0=if0iΩ0=if0xiT.

我们对批次中的每个训练样本计算这些导数,并将它们求和以得到 SGD 更新所需的梯度。

注意反向传播算法极为高效;前向传播和反向传播中计算量最大的步骤都是矩阵乘法(分别乘以 ΩΩT),这只需要加法和乘法。然而,它的内存效率不高;前向传播中的中间值必须全部存储,这可能限制我们能训练的模型大小。

7.4.2 自动微分

虽然理解反向传播算法很重要,但在实践中你不太可能需要自己编写它。现代深度学习框架如 PyTorch 和 TensorFlow 能根据模型规格自动计算导数。这被称为自动微分(algorithmic differentiation)。

框架中的每个功能组件(线性变换、ReLU 激活、损失函数)都知道如何计算自身的导数。例如,PyTorch 的 ReLU 函数 zout=relu[zin] 知道如何计算其输出 zout 关于输入 zin 的导数。类似地,线性函数 zout=β+Ωzin 知道如何计算输出 zout 关于输入 zin 以及参数 βΩ 的导数。自动微分框架还知道网络中操作的序列,因而拥有执行前向传播和反向传播所需的全部信息。

这些框架利用了现代图形处理单元(GPU)的大规模并行性。前向传播和反向传播中的矩阵乘法等计算天然适合并行化。此外,如果模型和前向传播中的中间结果不超过可用内存,还可以对整个批次并行执行前向传播和反向传播。

由于训练算法现在并行处理整个批次,输入变成了多维张量(tensor)。在这个语境下,张量可以看作矩阵向任意维度的推广。因此,向量是一维张量,矩阵是二维张量,三维网格的数字是三维张量。到目前为止,训练数据都是一维的,所以反向传播的输入将是一个二维张量,其中第一个维度索引批次元素,第二个维度索引数据维度。在后续章节中,我们将遇到更复杂的结构化输入数据。例如,当输入是 RGB 图像时,原始数据样本是三维的(高度 × 宽度 × 通道)。此时,学习框架的输入将是一个四维张量,其中额外的维度索引批次元素。

7.4.3 扩展到任意计算图

我们描述的反向传播是在一个自然顺序结构的深度神经网络中进行的;我们依次计算中间量 f0h1f1h2fk。然而,模型不必局限于顺序计算。在本书后面,我们将遇到具有分支结构的模型。例如,我们可能取某一隐藏层的值,通过两个不同的子网络处理,然后再合并。

幸运的是,只要计算图是无环的,反向传播的思想仍然适用。现代自动微分框架(如 PyTorch 和 TensorFlow)能够处理任意的无环计算图。

7.5 参数初始化

反向传播算法计算随机梯度下降和 Adam 所使用的导数来训练模型。现在我们讨论在训练开始前如何初始化参数。要理解这为何至关重要,考虑在前向传播中,每组预激活值 fk 的计算如下:

(7.27)fk=βk+Ωkhk=βk+Ωka[fk1],

其中 a[] 施加 ReLU 函数,Ωkβk 分别是权重和偏置。假设我们将所有偏置初始化为零,将 Ωk 的元素按均值为零、方差为 σ2 的正态分布初始化。考虑两种情况:

  • 如果方差 σ2 非常小(例如 105),则 βk+Ωkhk 的每个元素将是 hk 各元素的加权和,而权重非常小;结果可能具有比输入更小的幅度。此外,ReLU 函数将小于零的值截断,因此 hk 的值域将是 fk1 的一半。结果是,随着网络深度的推进,隐藏层预激活值的幅度会越来越小。

  • 如果方差 σ2 非常大(例如 105),则 βk+Ωkhk 的每个元素将是 hk 各元素的加权和,而权重非常大;结果可能具有比输入大得多的幅度。ReLU 函数将值域减半,但如果 σ2 足够大,预激活值的幅度仍会随着网络深度的推进而越来越大。

在这两种情况下,预激活值可能变得如此之小或如此之大,以至于无法用有限精度浮点运算来表示。

即使前向传播是可处理的,同样的逻辑也适用于反向传播。每次梯度更新(方程 7.25)都包含乘以 ΩT。如果 Ω 的值初始化不合理,梯度幅度可能在反向传播过程中不可控地减小或增大。这两种情况分别被称为梯度消失问题(vanishing gradient problem)和梯度爆炸问题(exploding gradient problem)。前者导致模型更新变得极其微小,后者导致更新变得不稳定。

7.5.1 前向传播的初始化

我们现在给出上述论点的数学版本。考虑相邻预激活值 ff 之间的计算,它们的维度分别为 DhDh

(7.28)h=a[f]f=β+Ωh

其中 h 表示激活值,Ωβ 分别表示权重和偏置,a[] 是激活函数。

假设输入层 f 的预激活值 fj 具有方差 σf2。考虑将偏置 βi 初始化为零,权重 Ωij 按均值为零、方差为 σΩ2 的正态分布初始化。现在我们推导后续层预激活值 f 的均值和方差的表达式。

中间值 fi 的期望(均值)E[fi] 为:

(7.29)E[fi]=E[βi+j=1DhΩijhj]=E[βi]+j=1DhE[Ωijhj]=E[βi]+j=1DhE[Ωij]E[hj]=0+j=1Dh0E[hj]=0,

其中 Dh 是输入层 h 的维度。我们使用了期望的运算规则,并假设隐藏单元 hj 和网络权重 Ωij 在第二行和第三行之间是独立的。

利用这个结果,我们可以看到预激活值 fi 的方差 σfi2 为:

(7.30)σfi2=E[fi2]E[fi]2=E[(βi+j=1DhΩijhj)2]0=E[(j=1DhΩijhj)2]=j=1DhE[Ωij2]E[hj2]=j=1DhσΩ2E[hj2]=σΩ2j=1DhE[hj2],

其中我们使用了方差恒等式 σ2=E[(zE[z])2]=E[z2]E[z]2。我们再次假设权重 Ωij 和隐藏单元 hj 的分布在第三行和第四行之间是独立的。

假设前一层的预激活值 fj 的分布关于零对称,则其中一半会被 ReLU 函数截断,二阶矩 E[hj2] 将是 fj 方差 σf2 的一半:

(7.31)σfi2=σΩ2j=1Dhσf22=12DhσΩ2σf2.

图 7.7

图 7.7 权重初始化。考虑一个有 50 个隐藏层、每层 Dh=100 个隐藏单元的深度网络。网络有 100 维输入 x、单一固定目标 y=0,使用最小二乘损失函数。偏置向量 βk 初始化为零,权重矩阵 Ωk 用均值为零、五种不同方差 σΩ2{0.001,0.01,0.02,0.1,1.0} 的正态分布初始化。a) 隐藏单元激活值的方差随网络层数变化。对于 He 初始化(σΩ2=2/Dh=0.02),方差是稳定的。但对于更大的值,方差快速增加;对于更小的值,方差快速减小(注意纵轴为对数刻度)。b) 反向传播中梯度的方差(实线)延续了这一趋势;如果初始化时使用大于 0.02 的值,梯度幅度在反向传播过程中快速增加。如果使用更小的值,则幅度减小。这分别被称为梯度爆炸和梯度消失问题。

这意味着,如果我们希望后续预激活值 f 的方差 σf2 与原始预激活值 f 在前向传播中的方差 σf2 相同,我们应该设置:

(7.32)σΩ2=2Dh,

其中 Dh 是权重所作用的原始层的维度。这被称为 He 初始化(He initialization)。

7.5.2 反向传播的初始化

类似的论证建立了梯度 l/fk 的方差在反向传播中如何变化。在反向传播中,我们乘以权重矩阵的转置 ΩT(方程 7.25),因此等价的表达式变为:

(7.33)σΩ2=2Dh,

其中 Dh 是权重馈入的目标层的维度。

7.5.3 同时满足前向和反向传播的初始化

如果权重矩阵 Ω 不是方阵(即相邻两层的隐藏单元数不同,DhDh 不同),则无法同时满足方程 7.32 和 7.33。一种可行的折中方案是使用均值 (Dh+Dh)/2 作为项数的代理,由此得到:

(7.34)σΩ2=4Dh+Dh.

图 7.7 展示了经验上,当参数被适当初始化时,前向传播中隐藏单元的方差和反向传播中梯度的方差都保持稳定。

7.6 训练代码示例

本书的主要侧重点是科学性的;这不是一本实现深度学习模型的指南。不过,在图 7.8 中,我们展示了实现本书到目前为止所探讨的思想的 PyTorch 代码。该代码定义了一个神经网络并初始化权重。它创建了随机的输入和输出数据集,并定义了最小二乘损失函数。模型使用带动量的 SGD 在数据上训练,批次大小为 10,共训练 100 个 epoch。学习率初始为 0.01,每 10 个 epoch 减半。

要点在于,虽然深度学习背后的思想相当复杂,但实现却相对简单。例如,反向传播的所有细节都隐藏在一行代码中:loss.backward()

图 7.8 在随机数据上训练两层网络的示例代码。

7.7 总结

前一章介绍了随机梯度下降(SGD),一种旨在求函数最小值的迭代优化算法。在神经网络的场景下,该算法寻找使损失函数最小化的参数。SGD 依赖于损失函数关于参数的梯度,而这些参数必须在优化开始前被初始化。本章针对深度神经网络解决了这两个问题。

梯度必须为大量参数、批次中的每个成员以及 SGD 的每次迭代进行评估。因此,梯度计算的效率至关重要,为此引入了反向传播算法。仔细的参数初始化同样重要。前向传播中隐藏单元激活值的幅度可能随网络层数呈指数级增长或衰减。反向传播中梯度的幅度也是如此,这些现象分别被称为梯度消失和梯度爆炸问题。两者都会阻碍训练,但可以通过适当的初始化来避免。

至此,我们已经定义了模型和损失函数,也能训练模型了。下一章讨论如何度量模型性能。

基于 CC-BY-NC-ND 许可协议