《深度学习》花书 - 第六章 深度前馈网络

mac2024-05-22  39

Deep Learning - Chapter 6

6 深度前馈网络6.1 实例:学习XOR6.2 基于梯度的学习6.2.2 输出单元6.2.2.1 用于高斯输出分布的线性单元6.2.2.2 用于 Bernoulli 输出分布的 sigmoid 单元6.2.2.3 用于 Multinoulli 输出分布的 softmax 单元6.2.2.4 其他的输出类型 6.3 隐藏单元6.3.1 整流线性单元及其扩展6.3.2 logistic sigmoid与双曲正切函数6.3.3 其他隐藏单元 6.4 架构设计6.5 反向传播和其他的微分算法6.5.7 实例:用于MLP训练的反向传播6.5.8 复杂化6.5.9 微分6.5.10 高阶微分 6.6 历史

6 深度前馈网络

6.1 实例:学习XOR

6.2 基于梯度的学习

6.2.2 输出单元

输出单元即网络最终层得到的结果。输出单元的选择影响了代价函数的选择。 原则上用作输出单元的神经网络单元也可以用作隐藏层的单元。 在本节中,我们假设前馈网络提供了一组定义为 h = f ( x ; θ ) h = f(x; θ) h=f(x;θ) 的隐藏特征。输出层的作用是随后对这些特征进行一些额外的变换来完成整个网络必须完成的任务。

6.2.2.1 用于高斯输出分布的线性单元

给定特征 h \boldsymbol{h} h,线性输出单元层产生向量 y ^ = W ⊤ h + b \hat{\boldsymbol{y}}=\boldsymbol{W}^{\top}\boldsymbol{h}+\boldsymbol{b} y^=Wh+b 线性输出层经常被用来产生条件高斯分布的均值: p ( y ∣ x ) = N ( y ; y ^ , I ) p(\boldsymbol{y} | \boldsymbol{x})=\mathcal{N}(\boldsymbol{y} ; \hat{\boldsymbol{y}}, \boldsymbol{I}) p(yx)=N(y;y^,I) 最大化条件高斯分布均值的对数似然等价于最小化均方误差。 因为线性模型不会饱和,所以它们易于采用基于梯度的优化算法,甚至可以使用其他多种优化算法。

6.2.2.2 用于 Bernoulli 输出分布的 sigmoid 单元

许多任务需要预测二值型变量,比如两个类别的分类问题。 此时最大似然的定义是 y y y x \boldsymbol{x} x下的Bernoulli分布 神经网络只需要预测 P ( y = 1 ∣ x ) P(y = 1 | x) P(y=1x) 即可。 为了使这个数是有效的概率,它必须处在区间 [0, 1] 中。 假设采用: P ( y = 1 ∣ x ) = max ⁡ { 0 , min ⁡ { 1 , w ⊤ h + b } } P(y=1 | x)=\max \left\{0, \min \left\{1, \boldsymbol{w}^{\top} \boldsymbol{h}+b\right\}\right\} P(y=1x)=max{0,min{1,wh+b}} 它是一个有效的条件概率分布,但我们无法使用梯度下降来高效地训练它。当 w ⊤ h + b \boldsymbol{w}^{\top} \boldsymbol{h}+b wh+b属于单位区间外时,梯度为0。我们想要的是无论模型给出了什么错误答案,总能有一个较大的梯度。

s i g m o i d sigmoid sigmoid输出单元: y ^ = σ ( w ⊤ h + b ) \hat{y}=\sigma( \boldsymbol{w}^{\top}\boldsymbol{h}+b) y^=σ(wh+b) 其中 σ \sigma σ σ ( x ) = 1 1 + exp ⁡ ( − x ) \sigma(x)=\frac{1}{1+\exp (-x)} σ(x)=1+exp(x)1 因此这个输出单元由两部分组成:一个线性层计算 z = w ⊤ h + b z=\boldsymbol{w}^{\top} \boldsymbol{h}+b z=wh+b,一个激活函数层将 z z z转化成概率。

z z z的值定义 y y y的分布: 假定非归一化的对数概率对y和z是线性的 log ⁡ P ~ ( y ) = y z \log\tilde{P}(y) =y z logP~(y)=yz 对它们取对数得到非归一化的概率 P ~ ( y ) = exp ⁡ ( y z ) \tilde{P}(y) =\exp (y z) P~(y)=exp(yz) 对它归一化,除以一个合适的常数 P ( y ) = exp ⁡ ( y z ) ∑ y ′ = 0 1 exp ⁡ ( y ′ z ) P(y) =\frac{\exp (y z)}{\sum_{y^{\prime}=0}^{1} \exp \left(y^{\prime} z\right)} P(y)=y=01exp(yz)exp(yz) 发现这服从 Bernoulli 分布,该分布受 z 的 sigmoid 变换控制 P ( y ) = σ ( ( 2 y − 1 ) z ) P(y) =\sigma((2 y-1) z) P(y)=σ((2y1)z)

损失函数 这种在对数空间里预测概率的方法可以很自然地使用最大似然学习。因为用于最大似然的代价函数是 − l o g P ( y ∣ x ) − log P (y | x) logP(yx),代价函数中的 log 抵消了 sigmoid 中的 exp。如果没有这个效果, sigmoid 的饱和性会阻止基于梯度的学习做出好的改进。我们使用最大似然来学习一个由 sigmoid 参数化的 Bernoulli 分布,它的损失函数为: J ( θ ) = − log ⁡ P ( y ∣ x ) = − log ⁡ σ ( ( 2 y − 1 ) z ) = ζ ( ( 1 − 2 y ) z ) \begin{aligned} J(\boldsymbol{\theta}) &=-\log P(y | \boldsymbol{x}) \\ &=-\log \sigma((2 y-1) z) \\ &=\zeta((1-2 y) z) \end{aligned} J(θ)=logP(yx)=logσ((2y1)z)=ζ((12y)z) ζ ( x ) = log ⁡ ( 1 + exp ⁡ ( x ) ) \zeta(x)=\log(1+\exp(x)) ζ(x)=log(1+exp(x))是softplus函数。

我们可以看到它仅仅在 ( 1 − 2 y ) z (1 − 2y)z (12y)z 取绝对值非常大的负值时才会饱和。因此饱和只会出现在模型已经得到正确答案时——当 y = 1 y = 1 y=1 z z z 取非常大的正值时,或者 y = 0 y = 0 y=0 z z z 取非常小的负值时。当 z z z 的符号错误时, 变量 ( 1 − 2 y ) z (1 − 2y)z (12y)z可以简化为 ∣ z ∣ |z| z。当 ∣ z ∣ |z| z 变得很大并且 z z z 的符号错误时, softplus 函数渐近地趋向于它的变量 ∣ z ∣ |z| z。对 z z z 求导则渐近地趋向于 s i g n ( z ) sign(z) sign(z)。所以基于梯度的学习可以很快修正错误的 z z z

其他损失 当我们使用其他的损失函数,例如均方误差之类的,损失函数会在 σ ( z ) σ(z) σ(z) 饱和时饱和。 sigmoid 激活函数在 z z z 取非常小的负值时会饱和到 0,当 z z z 取非常大的正值时会饱和到 1。这种情况一旦发生,梯度会变得非常小以至于不能用来学习,无论此时模型给出的是正确还是错误的答案。

6.2.2.3 用于 Multinoulli 输出分布的 softmax 单元

任何时候当我们想要表示一个具有 n 个可能取值的离散型随机变量的分布时,我们都可以使用 softmax 函数。它可以看作是 sigmoid 函数的扩展。softmax 函数最常用作分类器的输出,来表示 n 个不同类上的概率分布。

为了推广到具有 n 个值的离散型变量的情况,我们现在需要创造一个向量 y ^ \hat{y} y^,它的每个元素是 y i ^ = P ( y = i ∣ x ) \hat{y_i} = P(y = i | x) yi^=P(y=ix)。我们不仅要求每个 y i ^ \hat{y_i} yi^元素介于 0 和 1 之间,还要使得整个向量的和为 1,使得它表示一个有效的概率分布。用于 Bernoulli 分布的方法同样可以推广到 Multinoulli 分布。 首先,线性层预测了未归一化的对数概率: z = w ⊤ h + b z=\boldsymbol{w}^{\top} \boldsymbol{h}+b z=wh+b 其中 z i = log ⁡ P ^ ( y = i ∣ x ) z_{i}=\log \hat{P}(y=i | \boldsymbol{x}) zi=logP^(y=ix)。softmax 函数然后可以对 z 指数化和归一化来获得需要的 y i ^ \hat{y_i} yi^。最终, softmax 函数的形式为 softmax ⁡ ( z ) i = exp ⁡ ( z i ) ∑ j exp ⁡ ( z j ) \operatorname{softmax}(\boldsymbol{z})_{i}=\frac{\exp \left(z_{i}\right)}{\sum_{j} \exp \left(z_{j}\right)} softmax(z)i=jexp(zj)exp(zi)

损失函数 最大化 l o g P ( y = i ; z ) = log P(y = i; z)= logP(y=i;z)= log ⁡ softmax ⁡ ( z ) i = z i − log ⁡ ∑ j exp ⁡ ( z j ) \log \operatorname{softmax}(z)_{i}=z_{i}-\log \sum_{j} \exp \left(z_{j}\right) logsoftmax(z)i=zilogjexp(zj) 上式中当最大化对数似然时,第一项鼓励 z i z_i zi 被推高,而第二项则鼓励所有的 z z z 被压低。第二项 log ⁡ ∑ j exp ⁡ ( z j ) \log\sum_j \exp(z_j) logjexp(zj)可以大致近似为 max ⁡ j z j \max_j z_j maxjzj。因为对任何明显小于 max ⁡ j z j \max_j z_j maxjzj z k z_k zk exp ⁡ ( z k ) \exp(z_k) exp(zk) 都是不重要的。

因此我们可以感觉到,负对数似然代价函数总是强烈地惩罚最活跃的不正确预测。

而当正确答案已经具有了 softmax 的最大输入,那么 − z i −z_i zi 项和 log ⁡ ∑ j exp ⁡ ( z j ) ≈ max ⁡ j z j = z i \log\sum_j \exp(z_j) ≈ \max_j z_j = z_i logjexp(zj)maxjzj=zi项将大致抵消。这个样本对于整体训练代价贡献很小,这个代价主要由其他未被正确分类的样本产生。

失败的损失函数 除了对数似然之外的许多目标函数对 softmax 函数不起作用。具体来说,那些不使用对数来抵消 softmax 中的指数的目标函数,当指数函数的变量取非常小的负值时会造成梯度消失,从而无法学习。特别是,平方误差对于 softmax 单元来说是一个很差的损失函数,即使模型做出高度可信的不正确预测,也不能训练模型改变其输出。

softmax的饱和 当其中一个输入是最大( z i = max ⁡ i z i z_i = \max_i z_i zi=maxizi)并且 z i z_i zi 远大于其他的输入时,相应的输出 softmax ⁡ ( z ) i \operatorname{softmax}(z)_i softmax(z)i 会饱和到 1。当 z i z_i zi 不是最大值并且最大值非常大时,相应的输出 softmax ⁡ ( z ) i \operatorname{softmax}(z)_i softmax(z)i 也会饱和到 0。

6.2.2.4 其他的输出类型

之前描述的线性、 sigmoid 和 softmax 输出单元是最常见的。神经网络可以推广到我们希望的几乎任何种类的输出层。最大似然原则给如何为几乎任何种类的输出层设计一个好的代价函数提供了指导。

一般的,如果我们定义了一个条件分布 p ( y ∣ x ; θ ) p(y | x; θ) p(yx;θ),最大似然原则建议我们使用 − log ⁡ p ( y ∣ x ; θ ) − \log p(y | x; θ) logp(yx;θ) 作为代价函数。

一般来说,我们可以认为神经网络表示函数 f ( x ; θ ) f(x; θ) f(x;θ)。这个函数的输出不是对 y值的直接预测。相反, f ( x ; θ ) = ω f(x; θ) = \omega f(x;θ)=ω 提供了 y 分布的参数。我们的损失函数就可以表示成 − log ⁡ p ( y ; ω ( x ) ) − \log p(y; \omega(x)) logp(y;ω(x))

学习在给定 x 时, y 的条件高斯分布的方差 例如,我们想要学习在给定 x x x 时, y y y 的条件高斯分布的方差。简单情况下,方差 σ 2 σ^2 σ2 是一个常数,此时有一个解析表达式,这是因为方差的最大似然估计量仅仅是观测值 y 与它们的期望值的差值的平方平均。一种计算上代价更加高但是不需要写特殊情况代码的方法是简单地将方差作为分布 p ( y ∣ x ) p(y | x) p(yx) 的其中一个属性,这个分布由 ω = f ( x ; θ ) f (x; θ) f(x;θ) 控制。负对数似然 − log ⁡ p ( y ; ω ( x ) ) − \log p(y; ω(x)) logp(y;ω(x)) 将为代价函数提供一个必要的合适项来使我们的优化过程可以逐渐地学到方差。在标准差不依赖于输入的简单情况下,我们可以在网络中创建一个直接复制到 ω 中的新参数。这个新参数可以是 σ σ σ 本身,或者可以是表示 σ 2 σ^2 σ2 的参数 v v v,或者可以是表示 1 / ( σ 2 ) 1/(\sigma^2) 1/(σ2) 的参数 β β β,取决于我们怎样 σ 2 σ^2 σ2对分布参数化。我们可能希望模型对不同的 x x x 值预测出 y y y 不同的方差。这被称为异方差(heteroscedastic)模型。

多峰回归 即预测条件分布 p ( y ∣ x ) p(y | x) p(yx)的实值,该条件分布对于相同的 x x x 值在 y y y 空间中有多个不同的峰值。 在这种情况下,使用高斯混合输出,条件分布定义为: p ( y ∣ x ) = ∑ i = 1 n p ( c = i ∣ x ) N ( y ; μ ( i ) ( x ) , Σ ( i ) ( x ) ) p(\boldsymbol{y} | \boldsymbol{x})=\sum_{i=1}^{n} p(\mathrm{c}=i | \boldsymbol{x}) \mathcal{N}\left(\boldsymbol{y} ; \boldsymbol{\mu}^{(i)}(\boldsymbol{x}), \boldsymbol{\Sigma}^{(i)}(\boldsymbol{x})\right) p(yx)=i=1np(c=ix)N(y;μ(i)(x),Σ(i)(x)) 使用高斯混合输出的神经网络被称为混合密度网络。 从上式中看到,神经网络必须有三个输出:

(1)定义 p ( c = i ∣ x ) p(c = i | x) p(c=ix) 的向量:它们由潜变量 c c c 关联着,在 n n n 个不同组件上形成 Multinoulli 分布。

(2)对所有的 i i i 给出 µ ( i ) ( x ) µ^{(i)}(x) µ(i)(x) 的矩阵:它们指明了与第 i i i 个高斯组件相关联的中心或者均值。

(3)以及对所有的 i i i 给出 Σ ( i ) ( x ) Σ^{(i)}(x) Σ(i)(x) 的张量:它们指明了每个组件 i i i 的协方差矩阵。

6.3 隐藏单元

隐藏单元的设计是一个非常活跃的研究领域,并且还没有许多明确的指导性理论原则。

ReLu是隐藏单元极好的默认选择。许多其他类型的隐藏单元也是可用的。决定何时使用哪种类型的隐藏单元是困难的事,通常不可能预先预测出哪种隐藏单元工作得最好。设计过程充满了试验和错误,先直觉认为某种隐藏单元可能表现良好,然后用它组成神经网络进行训练,最后用验证集来评估它的性能。

不可微性 例如, ReLU g ( z ) = m a x { 0 , z } g(z) = max\{0, z\} g(z)=max{0,z} 在 z = 0 处不可微。这似乎使得 g 对于基于梯度的学习算法无效。在实践中,梯度下降对这些机器学习模型仍然表现得足够好。部分原因是神经网络训练算法通常不会达到代价函数的局部最小值,而是仅仅显著地减小它的值。因为我们不再期望训练能够实际到达梯度为 0 的点,所以代价函数的最小值对应于梯度未定义的点是可以接受的。不可微的隐藏单元通常只在少数点上不可微。一般来说,函数 g(z) 具有左导数和右导数,左导数定义为紧邻在 z 左边的函数的斜率,右导数定义为紧邻在 z 右边的函数的斜率。神经网络训练的软件实现通常返回左导数或右导数的其中一个,而不是报告导数未定义或产生一个错误。当一个函数被要求计算 g(0) 时,底层值真正为 0 是不太可能的。相对的,它可能是被舍入为 0 的一个小量 ϵ。在实践中,我们可以忽略隐藏单元激活函数的不可微性。

形式 大多数的隐藏单元都可以描述为接受输入向量 x x x,计算仿射变换 z = W ⊤ x + b z = W^⊤x + b z=Wx+b,然后使用一个逐元素的非线性函数 g ( z ) g(z) g(z)。大多数隐藏单元的区别仅仅在于激活函数 g ( z ) g(z) g(z) 的形式。

6.3.1 整流线性单元及其扩展

ReLU使用激活函数 g ( z ) = m a x { 0 , z } g(z) = max\{0, z\} g(z)=max{0,z}

整流线性单元易于优化,因为它们和线性单元非常类似。唯一区别在于整流线性单元在其一半的定义域上输出为零。这使得只要整流线性单元处于激活状态,它的导数都能保持较大。它的梯度不仅大而且一致。整流操作的二阶导数几乎处处为 0,并且在整流线性单元处于激活状态时,它的一阶导数处处为 1。这意味着相比于引入二阶效应的激活函数来说,它的梯度方向对于学习来说更加有用。

ReLU扩展 整流线性单元的三个扩展基于当 z i < 0 z_i < 0 zi<0 时使用一个非零的斜率 α i α_i αi h i = g ( z ; α ) i = m a x ( 0 ; z i ) + α i m i n ( 0 ; z i ) h_i = g(z; α)_i = max(0; z_i) + α_i min(0; z_i) hi=g(z;α)i=max(0;zi)+αimin(0;zi)

absolute value rectification g ( z ) = ∣ z ∣ g(z) = |z| g(z)=zLeaky ReLU 将 α i α_i αi 固定成一个类似 0.01 的小值。parametric ReLU 或者 PReLU 将 α i α_i αi 作为一个学习的参数。

maxout 进一步扩展了整流线性单元。 maxout 单元将 z 划分为每组具有 k 个值的组,而不是使用作用于每个元素的函数 g(z)。每个maxout 单元则输出每组中的最大元素: g ( z ) i = max ⁡ j ∈ G ( i ) z j g(\boldsymbol{z})_{i}=\max _{j \in \mathbb{G}^{(i)}} z_{j} g(z)i=jG(i)maxzj 这提供了一种方法来学习对输入 x 空间中多个方向响应的分段线性函数。

maxout 单元可以学习具有多达 k 段的分段线性的凸函数。 maxout 单元因此可以视为学习激活函数本身而不仅仅是单元之间的关系。使用足够大的 k, maxout 单元可以以任意的精确度来近似任何凸函数。特别地,k=2 的 maxout 层可以学习实现和传统层相同的输入 x 的函数,这些传统层可以使用ReLU、 absolute value rectification、 Leaky ReLU 或 parametric ReLU,或者可以学习实现与这些都不同的函数。

每个 maxout 单元现在由 k 个权重向量来参数化,而不仅仅是一个,所以 maxout单元通常比整流线性单元需要更多的正则化。

maxout 单元在某些情况下,要求更少的参数,可以获得一些统计和计算上的优势。如果由 n 个不同的线性过滤器描述的特征可以在不损失信息的情况下,用每一组 k 个特征的最大值来概括的话,那么下一层的权重数可以减少为1/k。

因为每个单元由多个过滤器驱动, maxout 单元具有一些冗余来帮助它们抵抗一种被称为 灾难遗忘(catastrophic forgetting)的现象,这个现象是说神经网络忘记了如何执行它们过去训练的任务 。

整流线性单元和它们的这些扩展都是基于一个原则,那就是如果它们的行为更接近线性,那么模型更容易优化。

6.3.2 logistic sigmoid与双曲正切函数

logistic sigmoid 激活函数 g ( z ) = σ ( z ) = 1 1 + exp ⁡ ( − z ) g(z)=\sigma(z)=\frac{1}{1+\exp (-z)} g(z)=σ(z)=1+exp(z)1 双曲正切激活函数 g ( z ) = t a n h ( z ) g(z)=tanh(z) g(z)=tanh(z) 关系 t a n h ( z ) = 2 σ ( 2 z ) − 1 tanh(z)=2\sigma(2z)-1 tanh(z)=2σ(2z)1

与分段线性单元不同, sigmoid 单元在其大部分定义域内都饱和——当 z 取绝对值很大的正值时,它们饱和到一个高值,当 z 取绝对值很大的负值时,它们饱和到一个低值,并且仅仅当 z 接近 0 时它们才对输入强烈敏感。 sigmoid 单元的广泛饱和性会使得基于梯度的学习变得非常困难。因为这个原因,现在不鼓励将它们用作前馈网络中的隐藏单元。当使用一个合适的代价函数来抵消 sigmoid 的饱和性时,它们作为输出单元可以与基于梯度的学习相兼容。

当必须要使用 sigmoid 激活函数时,双曲正切激活函数通常要比 logistic sigmoid 函数表现更好。 在 t a n h ( 0 ) = 0 tanh(0) = 0 tanh(0)=0 σ ( 0 ) = 0.5 σ(0) = 0.5 σ(0)=0.5 的意义上,它更像是单位函数。因为 t a n h tanh tanh 在 0 附近与单位函数类似,训练深层神经网络 y ^ = w ⊤ t a n h ( U ⊤ t a n h ( V ⊤ x ) ) \hat{y} = \boldsymbol{w}^⊤tanh( \boldsymbol{U}^⊤tanh( \boldsymbol{V}^⊤x)) y^=wtanh(Utanh(Vx))类似于训练一个线性模型 y ^ = w ⊤ U ⊤ V ⊤ x \hat{y} = \boldsymbol{w}^{⊤} \boldsymbol{U}^{⊤} \boldsymbol{V}^{⊤}x y^=wUVx,只要网络的激活能够被保持地很小。这使得训练 tanh 网络更加容易。

sigmoid 激活函数在除了前馈网络以外的情景中更为常见。循环网络、许多概率模型以及一些自编码器有一些额外的要求使得它们不能使用分段线性激活函数,并且使得 sigmoid 单元更具有吸引力,尽管它存在饱和性的问题。

6.3.3 其他隐藏单元

也存在许多其他种类的隐藏单元,但它们并不常用。

一般来说,很多种类的可微函数都表现得很好。许多未发布的激活函数与流行的激活函数表现得一样好。为了提供一个具体的例子,作者在 MNIST 数据集上使用 h = cos(Wx + b) 测试了一个前馈网络,并获得了小于 1% 的误差率,这可以与更为传统的激活函数获得的结果相媲美。在新技术的研究和开发期间,通常会测试许多不同的激活函数,并且会发现许多标准方法的变体表现非常好。这意味着,通常新的隐藏单元类型只有在被明确证明能够提供显著改进时才会被发布。新的隐藏单元类型如果与已有的隐藏单元表现大致相当的话,那么它们是非常常见的,不会引起别人的兴趣。

不使用激活函数(或 g ( z ) = z g(z)=z g(z)=z) 我们已经看过线性单元可以用作神经网络的输出。它也可以用作隐藏单元。如果神经网络的每一层都仅由线性变换组成,那么网络作为一个整体也将是线性的。然而,神经网络的一些层是纯线性也是可以接受的。考虑具有 n n n 个输入和 p p p个输出的神经网络层 h = g ( W ⊤ x + b ) h = g(W^⊤x + b) h=g(Wx+b)。我们可以用两层来代替它,一层使用权重矩阵 U U U,另一层使用权重矩阵 V V V。如果第一层没有激活函数,那么我们对基于 W W W 的原始层的权重矩阵进行因式分解。分解方法是计算 h = g ( V ⊤ U ⊤ x + b ) h = g(V^⊤U^⊤x + b) h=g(VUx+b)。如果 U U U 产生了 q q q 个输出,那么 U U U V V V 一起仅包含 ( n + p ) q (n + p)q (n+p)q 个参数,而 W W W 包含 n p np np 个参数。

如果 q q q 很小,这可以在很大程度上节省参数。这是以将线性变换约束为低秩的代价来实现的,但这些低秩关系往往是足够的。线性隐藏单元因此提供了一种减少网络中参数数量的有效方法。

softmax单元 softmax是另外一种经常用作输出的单元(如第 6.2.2.3 节中所描述的),但有时也可以用作隐藏单元。 softmax 单元很自然地表示具有 k 个可能值的离散型随机变量的概率分布,所以它们可以用作一种开关。这些类型的隐藏单元通常仅用于明确地学习操作内存的高级结构中。

其他一些常见的隐藏单元类型包括:

径向基函数(radial basis function, RBF) h i = exp ⁡ ( − 1 σ i 2 ∥ W : , i − x ∥ 2 ) h_{i}=\exp \left(-\frac{1}{\sigma_{i}^{2}}\left\|\boldsymbol{W}_{:, i}-\boldsymbol{x}\right\|^{2}\right) hi=exp(σi21W:,ix2) 这个函数在 x 接近模板 W : , i W_{:,i} W:,i 时更加活跃。因为它对大部分 x 都饱和到 0,因此很难优化。softplus函数: g ( a ) = ζ ( a ) = l o g ( 1 + e a ) g(a) = ζ(a) = log(1 + e^a) g(a)=ζ(a)=log(1+ea)。这是ReLU单元的平滑版本,由 Dugas et al. (2001) 引入用于函数近似,由 Nair and Hinton (2010a) 引入用于无向概率模型的条件分布。 Glorot et al. (2011a) 比较了 softplus 和ReLU单元,发现后者的结果更好。通常不鼓励使用 softplus 函数。 softplus 表明隐藏单元类型的性能可能和直觉相反——因为它处处可导、不完全饱和,人们可能希望它具有优于整流线性单元的点,但根据经验来看,它并没有。硬双曲正切函数(hard tanh) g ( a ) = m a x ( − 1 , m i n ( 1 ; a ) ) g(a) = max(−1, min(1; a)) g(a)=max(1,min(1;a)) 它的形状和 tanh 以及ReLU类似,但是不同于后者,它是有界的 。

6.4 架构设计

6.5 反向传播和其他的微分算法

6.5.7 实例:用于MLP训练的反向传播

目的:利用反向传播算法来训练多层感知机。网络:一个具有单个隐藏层的非常简单的多层感知机。更新权重方法:小批量随机梯度下降算法。反向传播算法:用于计算单个小批量上的代价的梯度。

我们使用训练集上的一小批量实例,将其规范化为一个设计矩阵 X X X 以及标签向量 y y y

第一层 隐藏特征层 H = m a x { 0 , X W ( 1 ) } H = max\{0, XW^{(1)}\} H=max{0,XW(1)}。不使用偏置。 (包含 r e l u relu relu 操作)

第二层 类的非归一化对数概率的预测将随后由 H W ( 2 ) HW^{(2)} HW(2) 给出。

损失的定义: 假设我们的图语言包含 c r o s s _ e n t r o p y cross\_entropy cross_entropy 操作,用以计算目标 y y y 和由这些未归一化对数概率定义的概率分布间的交叉熵。所得到的交叉熵定义了代价函数 J M L E J_{MLE} JMLE。最小化这个交叉熵将执行对分类器的最大似然估计。然而,为了使得这个例子更加真实,我们也包含一个正则项。总的代价函数为 J = J M L E + λ ( ∑ i , j ( W i , j ( 1 ) ) 2 + ∑ i , j ( W i , j ( 2 ) ) 2 ) J=J_{\mathrm{MLE}}+\lambda\left(\sum_{i, j}\left(W_{i, j}^{(1)}\right)^{2}+\sum_{i, j}\left(W_{i, j}^{(2)}\right)^{2}\right) J=JMLE+λ(i,j(Wi,j(1))2+i,j(Wi,j(2))2)

下图 : 用于计算代价函数的计算图,这个代价函数是使用交叉熵损失以及权重衰减训练我们的 单层 MLP 示例所产生的。

我们可以通过正向传播图来粗略地描述反向传播算法的行为。计算 ∇ W ( 1 ) J ∇_{W^{(1)}}J W(1)J ∇ W ( 2 ) J ∇_{W^{(2)}}J W(2)J。有两种不同的路径从 J J J 后退到权重:一条通过交叉熵代价,另一条通过权重衰减代价。

权重衰减代价相对简单,它总是对 W ( i ) W^{(i)} W(i) 上的梯度贡献 2 λ W ( i ) 2λW^{(i)} 2λW(i)

另一部分通过交叉熵代价的路径稍微复杂一些。令 G G G 是由 c r o s s _ e n t r o p y cross\_entropy cross_entropy 操作提供的对未归一化对数概率 U ( 2 ) U^{(2)} U(2) 的梯度。

W ( 2 ) W^{(2)} W(2) 它使用对矩阵乘法的第二个变量的反向传播规则,将 H ⊤ G H^⊤G HG 加到 W ( 2 ) W^{(2)} W(2) 的梯度上。

W ( 1 ) W^{(1)} W(1) 首先,反向传播算法使用对矩阵乘法的第一个变量的反向传播规则,计算 ∇ H J = G W ( 2 ) ⊤ ∇_HJ = GW^{(2)⊤} HJ=GW(2)。接下来, r e l u relu relu操作使用其反向传播规则对先前梯度的部分位置清零,这些位置对应着 U ( 1 ) U^{(1)} U(1) 中所有小于 0 的元素。记上述结果为 G ′ G^′ G。反向传播算法的最后一步是使用对 m a t m u l matmul matmul 操作的第二个变量的反向传播规则,将 X ⊤ G ′ X^⊤G^′ XG 加到 W ( 1 ) W^{(1)} W(1) 的梯度上。

在计算了这些梯度以后,梯度下降算法或者其他优化算法所要做的就是使用这些梯度来更新参数。

时间和空间成本 对于 M L P MLP MLP,计算成本主要来源于矩阵乘法。在前向传播阶段,我们乘以每个权重矩阵,得到了 O ( w ) O(w) O(w) 数量的乘-加,其中 w w w 是权重的数量。在反向传播阶段,我们乘以每个权重矩阵的转置,这具有相同的计算成本。算法主要的存储成本是我们需要将输入存储到隐藏层的非线性中去。这些值从被计算时开始存储,直到反向过程回到了同一点。因此存储成本是 O ( m n h ) O(mn_h) O(mnh),其中 m m m 是小批量中样本的数目, n h n_h nh 是隐藏单元的数量。

6.5.8 复杂化

我们这里描述的反向传播算法要比实践中实际使用的实现要简单。

正如前面提到的,我们将操作的定义限制为返回单个张量的函数。大多数软件实现需要支持可以返回多个张量的操作。例如,如果我们希望计算张量中的最大值和该值的索引,则最好在单次运算中计算两者,因此将该过程实现为具有两个输出的操作效率更高。

我们还没有描述如何控制反向传播的内存消耗。反向传播经常涉及将许多张量加在一起。在朴素方法中,将分别计算这些张量中的每一个,然后在第二步中对所有这些张量求和。朴素方法具有过高的存储瓶颈,可以通过保持一个缓冲器,并且在计算时将每个值加到该缓冲器中来避免该瓶颈。

反向传播的现实实现还需要处理各种数据类型,例如 32 位浮点数、 64 位浮点数和整型。处理这些类型的策略需要特别的设计考虑。

一些操作具有未定义的梯度,并且重要的是跟踪这些情况并且确定用户请求的梯度是否是未定义的。

各种其他技术的特性使现实世界的微分更加复杂。

6.5.9 微分

深度学习界在在很大程度上发展了自己关于如何进行微分的文化。自动微分(automatic differentiation)领域关心如何以算法方式计算导数。上述的反向传播算法只是自动微分的一种方法。它是一种称为 反向模式累加(reverse mode accumulation)技术的特殊情况。其他方法以不同的顺序来计算链式法则的子表达式。

减小计算开销 确定一种计算的顺序使得计算开销最小,比如找到计算梯度的最优操作序列是 NP 完全问题 (Naumann, 2008),因此,我们可能需要将代数表达式简化为它们最廉价的形式。

假设我们有变量 p 1 , p 2 . . . , p n p_1, p_2..., p_n p1,p2...,pn 表示概率,以及变量 z 1 z 2 . . . , z n z_1 z_2..., z_n z1z2...,zn 表示未归一化的对数概率。假设我们定义 q i = exp ⁡ ( z i ) ∑ i exp ⁡ ( z i ) q_{i}=\frac{\exp \left(z_{i}\right)}{\sum_{i} \exp \left(z_{i}\right)} qi=iexp(zi)exp(zi) 其中我们通过指数化、求和与除法运算构建 s o f t m a x softmax softmax 函数,并构造交叉熵损失函数 J = − ∑ i p i l o g q i J = − ∑_i p_i log q_i J=ipilogqi。 可以观察到 J J J z i z_i zi 的导数有一个非常简单的形式: q i − p i qi − pi qipi 。 但是反向传播算法不能够以这种方式来简化梯度,而是会通过原始图中的所有对数和指数操作显式地传播梯度。

复杂度 当前向图 G G G 具有单个输出节点,并且每个偏导数 ∂ u ( i ) ∂ u ( j ) \frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i) 都可以用恒定的计算量来计算时,反向传播保证梯度计算的计算数目和前向计算的计算数目是同一个量级:这可以在算法 6.2 中看出,因为每个局部偏导数 ∂ u ( i ) ∂ u ( j ) \frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i) 以及递归链式公式(式 (6.49) )中相关的乘和加都只需计算一次。因此,总的计算量是 O(#edges)。可能通过对反向传播算法构建的计算图进行简化来减少这些计算量,是 NP 完全问题。诸如 T h e a n o Theano Theano T e n s o r F l o w TensorFlow TensorFlow 的实现使用基于匹配已知简化模式的试探法,以便重复地尝试去简化图。

前向模式与后向模式 我们定义反向传播仅用于计算标量输出的梯度,但是反向传播可以扩展到计算 J a c o b i a n Jacobian Jacobian 矩阵(该 J a c o b i a n Jacobian Jacobian 矩阵或者来源于图中的 k k k 个不同标量节点,或者来源于包含 k k k 个值的张量值节点)。普通的实现可能需要 k k k 倍的计算:对于原始前向图中的每个内部标量节点,计算 k k k 个梯度而不是单个梯度。当图的输出数目大于输入的数目时,有时更偏向于使用另外一种形式的自动微分,称为 前向模式累加(forward mode accumulation)。前向模式计算已经被提出用于循环神经网络梯度的实时计算,例如 (Williams and Zipser, 1989)。这也避免了存储整个图的值和梯度的需要,是计算效率和内存使用的折中。

前向模式和后向模式的关系类似于左乘和右乘一系列矩阵之间的关系,例如 A B C D ABCD ABCD 其中的矩阵可以认为是 J a c o b i a n Jacobian Jacobian 矩阵。例如,如果 D D D 是列向量,而 A A A 有很多行,那么这对应于一幅具有单个输出和多个输入的图,并且从最后开始乘,反向进行,只需要矩阵-向量的乘积。这对应着反向模式。相反,从左边开始乘将涉及一系列的矩阵-矩阵乘积,这使得总的计算变得更加“昂贵”。然而,如果 A A A 的行数小于 D D D 的列数,则从左到右乘计算量更小,这就对应着前向模式。

反向传播不是计算梯度的唯一方式或最佳方式,但它是一个非常实用的方法,继续为深度学习领域服务。在未来,深度网络的微分技术可能会提高,因为深度学习的从业者更加了解了广泛的自动微分领域。

6.5.10 高阶微分

一些框架支持使用高阶导数,包括 T h e a n o Theano Theano T e n s o r F l o w TensorFlow TensorFlow

在深度学习的相关领域,很少会计算标量函数的单个二阶导数。相反,我们通常对 H e s s i a n Hessian Hessian 矩阵( R n → R R^n→R RnR的函数的二阶导数。)的性质比较感兴趣。如果我们有函数 f : R n → R f : R^n → R f:RnR,那么 H e s s i a n Hessian Hessian 矩阵的大小是 n × n n × n n×n。在典型的深度学习应用中, n n n 将是模型的参数数量,可能很容易达到数十亿。因此,完整的 H e s s i a n Hessian Hessian 矩阵甚至不能表示。

典型的深度学习方法是使用 K r y l o v Krylov Krylov 方法,而不是显式地计算 H e s s i a n Hessian Hessian 矩阵。 K r y l o v Krylov Krylov 方法是用于执行各种操作的一组迭代技术,这些操作包括像近似求解矩阵的逆、或者近似矩阵的特征值或特征向量等,而不使用矩阵/向量乘法以外的任何操作。 K r y l o v Krylov Krylov方法是一种 “降维打击” 手段,有利有弊。其特点一是牺牲了精度换取了速度,二是在没有办法求解大型稀疏矩阵时,他给出了一种办法,虽然不精确。

为了在 H e s s s i a n Hesssian Hesssian 矩阵上使用 K r y l o v Krylov Krylov 方法,我们只需要计算 H e s s i a n Hessian Hessian 矩阵 H H H 和一个任意向量 v v v 间的乘积即可。实现这一目标的一种直观方法是 H v = ∇ x [ ( ∇ x f ( x ) ) ⊤ v ] \boldsymbol{H} \boldsymbol{v}=\nabla_{\boldsymbol{x}}\left[\left(\nabla_{x} f(x)\right)^{\top} \boldsymbol{v}\right] Hv=x[(xf(x))v] 该表达式中两个梯度的计算都可以由适当的软件库自动完成。其中外部梯度表达式是内部梯度表达式的函数的梯度。

6.6 历史

前馈网络可以被视为一种高效的非线性函数近似器,它以使用梯度下降来最小化函数近似误差为基础。现代前馈网络是一般函数近似任务的几个世纪进步的结晶。

反向传播算法底层的链式法则是 17 世纪发明的 (Leibniz, 1676; L’Hôpital, 1696)。但梯度下降直到 19 世纪才作为优化问题的一种迭代近似的求解方法被引入 (Cauchy, 1847)。

抵制 从 20 世纪 40 年代开始,这些函数近似技术被用于导出诸如感知机的机器学习模型。然而,最早的模型都是基于线性模型。来自包括 Marvin Minsky 的批评指出 了线性模型族的几个缺陷,例如它无法学习 XOR 函数,这导致了对整个神经网络方法的抵制。

活跃 学习非线性函数需要多层感知机的发展和计算该模型梯度的方法。基于动态规划的链式法则的高效应用开始出现在 20 世纪 60 年代和 70 年代,主要用于控制领域 (Kelley, 1960; Bryson and Denham, 1961; Dreyfus, 1962; Bryson and Ho, 1969; Dreyfus, 1973),也用于灵敏度分析 (Linnainmaa, 1976)。Werbos (1981) 提出应用这些技术来训练人工神经网络。这个想法以不同的方式被独立地重新发现后 (LeCun, 1985; Parker, 1985; Rumelhart et al., 1986a),最终在实践中得以发展。 并行分布式处理(Parallel Distributed Processing) 一书在其中一章提供了第一次成功使用反向传播的一些实验的结果 (Rumelhart et al., 1986b),这对反向传播的普及做出了巨大的贡献,并且开启了一个研究多层神经网络非常活跃的时期。

在反向传播的成功之后,神经网络研究获得了普及,并在 20 世纪 90 年代初达到高峰。随后,其他机器学习技术变得更受欢迎,直到 2006 年开始的现代深度学习复兴。

争议 当 2006 年深度学习开始现代复兴时,前馈网络仍然有不良的声誉。从 2006 年 至 2012 年,人们普遍认为,前馈网络不会表现良好,除非它们得到其他模型的辅助, 例如概率模型。现在已经知道,只要具备适当的资源和工程实践,前馈网络表现得非常好。今天,前馈网络中基于梯度的学习被用作发展概率模型的工具,例如第二十章中描述的变分自编码器和生成式对抗网络。前馈网络中基于梯度的学习自 2012 年以来一直被视为一种强大的技术,并应用于许多其他机器学习任务,而不是被视为必须由其他技术支持的不可靠技术。在 2006 年,业内使用无监督学习来支持监督学习,现在更讽刺的是,更常见的是使用监督学习来支持无监督学习。

近三十年的改进 现代前馈网络的核心思想自 20 世纪 80 年代以来没有发生重大变化。仍然使用相同的反向传播算法和相同的梯度下降方法。1986 年至 2015 年神经网络性能的大部分改进可归因于两个因素。首先,较大的数据集减少了统计泛化对神经网络的挑战的程度。第二,神经网络由于更强大的计算机和更好的软件基础设施已经变得更大。然而,少量算法上的变化也显著改善了神经网络的性能。

算法上的变化 (1) 其中一个算法上的变化是用交叉熵族损失函数替代均方误差损失函数。均方误差在 20 世纪 80 年代和 90 年代流行,但逐渐被交叉熵损失替代,并且最大似然原理的想法在统计学界和机器学习界之间广泛传播。使用交叉熵损失大大提高了具有 sigmoid 和 softmax 输出的模型的性能,而当使用均方误差损失时会存在饱和和学习缓慢的问题。 (2) 另一个显著改善前馈网络性能的算法上的主要变化是使用分段线性隐藏单元来替代 sigmoid 隐藏单元,例如用整流线性单元ReLU。

使用 max{0,z} 函数的整流在早期神经网络中已经被引入,并且至少可以追溯到认知机(Cognitron)和神经认知机 (Neocognitron)(Fukushima, 1975, 1980)。这些早期的模型没有使用整流线性单元, 而是将整流用于非线性函数。尽管整流在早期很普及,在 20 世纪 80 年代,整流很大程度上被 sigmoid 所取代,也许是因为当神经网络非常小时,sigmoid 表现更好。 到 21 世纪初,由于有些迷信的观念,认为必须避免具有不可导点的激活函数,所以避免了整流线性单元。这在 2009 年开始发生改变。Jarrett et al. (2009b) 观察到, 在神经网络结构设计的几个不同因素中 ‘‘使用整流非线性是提高识别系统性能的最重要的唯一因素’’。对于小的数据集,Jarrett et al. (2009b) 观察到,使用整流非线性甚至比学习隐藏层的权重值更加重要。随机的权重足以通过整流网络传播有用的信息,允许在顶部的分类器层学习如何将不同的特征向量映射到类标识。ReLU单元还具有历史意义,因为它们表明神经科学继续对深度学习算法的发展产生影响。Glorot et al. (2011a) 从生物学考虑整流线性单元的导出。半整流非线性旨在描述生物神经元的这些性质:(1) 对于某些输入,生物神经元是完全不活跃的。(2) 对于某些输入,生物神经元的输出和它的输入成比例。(3) 大多数时间, 生物神经元是在它们不活跃的状态下进行操作(即它们应该具有稀疏激活(sparse activation))。

前馈网络还有许多未实现的潜力。未来,我们期望它们用于更多的任务,优化算法和模型设计的进步将进一步提高它们的性能。本章主要描述了神经网络模型族。 在接下来的章节中,我们将讨论如何使用这些模型——如何对它们进行正则化和训练。

最新回复(0)