从机器学习的角度看,神经网络一般可以看做是一个非线性模型,其基本组成单元为具有非线性激活函数的神经元,通过大量神经元之间的连接,使得神经网络成为一种高度非线性的模型。神经元之间的连接权重就是要学习的参数,可以在机器学习框架下通过梯度下降法来进行学习。
典型神经元结构如下:
神经元接收D 个输入,用向量 x = [ x 1 ; x 2 ; ⋯ ; x D ] \boldsymbol{x}=\left[x_{1} ; x_{2} ; \cdots ; x_{D}\right] x=[x1;x2;⋯;xD]来表示。净输入 z ∈ R z \in \mathbb{R} z∈R表示神经元所获输入信号的加权和,
z = ∑ d = 1 D w d x d + b = w ⊤ x + b \begin{aligned} z &=\sum_{d=1}^{D} w_{d} x_{d}+b \\ &=\boldsymbol{w}^{\top} \boldsymbol{x}+b \end{aligned} z=d=1∑Dwdxd+b=w⊤x+b
其中 w = [ w 1 ; w 2 ; ⋯ ; w D ] ∈ R D \boldsymbol{w}=\left[w_{1} ; w_{2} ; \cdots ; w_{D}\right] \in \mathbb{R}^D w=[w1;w2;⋯;wD]∈RD是 D D D维输入的权重向量, b ∈ R b \in \mathbb{R} b∈R是偏置。
净输入 z z z在经过一个非线性函数 f ( ⋅ ) f(·) f(⋅)后得到神经元的活性值(Activation) a a a,
a = f ( z ) a=f(z) a=f(z)
其中 f ( ⋅ ) f(·) f(⋅)称为激活函数(Activation Function)。
激活函数
为增强网络的表示能力和学习能力,激活函数需要具备以下几点性质:
几种常用的激活函数:
一类 S 型曲线函数,为两端饱和函数。常用的 sigmoid 型函数有 Logistic 函数和 Tanh 函数。(对于函数 f ( x ) f(x) f(x),当 x → ∞ x \rightarrow\infty x→∞时 f ′ ( x ) → 0 f'(x)\rightarrow 0 f′(x)→0,则称为饱和函数)
Logistic函数
σ ( x ) = 1 1 + exp ( − x ) \sigma(x)=\frac{1}{1+\exp (-x)} σ(x)=1+exp(−x)1
Tanh函数
tanh ( x ) = exp ( x ) − exp ( − x ) exp ( x ) + exp ( − x ) = 2 σ ( 2 x ) − 1 \tanh (x)=\frac{\exp (x)-\exp (-x)}{\exp (x)+\exp (-x)}=2\sigma(2x)-1 tanh(x)=exp(x)+exp(−x)exp(x)−exp(−x)=2σ(2x)−1
Tanh 函数的输出是零中心化的(zero-centered),非零中心化的输出会使其后一层神经元的输入发生偏置偏移(bias shift),并进一步降低梯度下降的收敛速度。
ReLU (Rectified Linear Unit,修正线性单元),也叫 Rectifier 函数。ReLU 实际上是一个斜坡(ramp)函数。是目前深度神经网络中经常用的激活函数。
ReLU ( x ) = { x x ≥ 0 0 x < 0 = max ( 0 , x ) \begin{aligned} \operatorname{ReLU}(x) &=\left\{\begin{array}{ll}x & x \geq 0 \\ 0 & x<0\end{array}\right.\\ &=\max (0, x) \end{aligned} ReLU(x)={x0x≥0x<0=max(0,x)
ReLU 函数计算高效,具有很好的符合生物学特性的稀疏激活性(在生物神经网络中,同时处于兴奋状态的神经元非常稀疏)。
但输出是非零中心化的。此外还比较容易出现死亡 ReLU 问题(Dying ReLU Problem),即在训练时,如果参数在一次不恰当的更新后,隐藏层中的某个 ReLU 神经元在所有的训练数据上都不能被激活,那么这个神经元自身参数的梯度永远都会是 0,在以后的训练过程中永远不能被激活。
Leaky ReLU
LeakyReLU ( x ) = { x if x > 0 γ x if x ≤ 0 = max ( 0 , x ) + γ min ( 0 , x ) \begin{aligned} \text { LeakyReLU }(x) &=\left\{\begin{array}{ll}x & \text { if } x>0 \\ \gamma x & \text { if } x \leq 0\end{array}\right.\\ &=\max (0, x)+\gamma \min (0, x) \end{aligned} LeakyReLU (x)={xγx if x>0 if x≤0=max(0,x)+γmin(0,x)
在输入 x < 0 x<0 x<0 时,保持一个很小的梯度 γ \gamma γ.这样当神经元非激活时也能有一个非零的梯度可以更新参数,以免永远不能被激活。
此外还有 PReLU(参数化 ReLU)、ELU、softplus 等变种。
一种自门控(self-gated)激活函数.
swish ( x ) = x σ ( β x ) \operatorname{swish}(x)=x \sigma(\beta x) swish(x)=xσ(βx)
β \beta β是可学习的参数或一个固定的超参数。
通过一定的连接方式或信息传递方式进行协作的神经元可以看作一个网络,就是神经网络。网络结构有以下三种:
各神经元按接收信息的先后分为不同的层,每一层的神经元接收前一层的输出,并输出到下一层神经元。整个网络的信息朝着一个方向传播,没有反向的信息传播。前馈网络包含全连接前馈网络和卷积神经网络等。
前馈网络可以看做一个函数,通过简单非线性函数的多次复合,实现输入空间到输出空间的复杂映射。
网络中的神经元不但可以接收其他神经元的信息,也可以接收直接的历史信息。记忆网络具有记忆功能,在不同的时刻具有不同的状态。记忆神经网络的信息可以是单向或双向传递。主要包含循环神经网络、Hopfield 网络、玻尔兹曼机、受限玻尔兹曼机等。
为增强记忆网络的记忆容量,可引入外部记忆单元和读写机制用来保持一些网络的中间状态,称为记忆增强神经网络。
图网络是定义在图结构数据上的神经网络。图中每个节点都由一个或一组神经元构成。每个节点可以接收来自相邻节点或自身的信息。
图网络包含很多实现方式,如图卷积网络(Graph Convolutional Networks,GCN)、图注意力网络、消息传递神经网络等。
前馈神经网络相邻的两层神经元之间为全连接关系,也称为全连接神经网络(Full connected Neural Network,FCNN)或多层感知机。
记号 | 含义 |
---|---|
L L L | 神经网络的层数 |
M l M_l Ml | 第 l l l层神经元的个数 |
f l ( ⋅ ) f_l(·) fl(⋅) | 第 l l l层神经元的激活函数 |
W ( l ) ∈ R M l × M l − 1 \boldsymbol{W}^{(l)} \in \mathbb{R}^{M_{l} \times M_{l-1}} W(l)∈RMl×Ml−1 | 第 l − 1 l-1 l−1层到第 l l l层的权重矩阵 |
b ( l ) ∈ R M l \boldsymbol{b}^{(l)} \in \mathbb{R}^{M_{l}} b(l)∈RMl | 第 l − 1 l-1 l−1层到第 l l l层的偏置 |
z ( l ) ∈ R M l \boldsymbol{z}^{(l)} \in \mathbb{R}^{M_{l}} z(l)∈RMl | 第 l l l层神经元的净输入(净活性值) |
a ( l ) ∈ R M l \boldsymbol{a}^{(l)} \in \mathbb{R}^{M_{l}} a(l)∈RMl | 第 l l l层神经元的输出(活性值) |
令 a ( 0 ) = x \boldsymbol{a}^{(0)}=\boldsymbol{x} a(0)=x,前馈神经网络通过不断迭代下列公式逐层进行信息传播: z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) a ( l ) = f l ( z ( l ) ) \begin{aligned} \boldsymbol{z}^{(l)} &=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)} \\ \boldsymbol{a}^{(l)} &=f_{l}\left(\boldsymbol{z}^{(l)}\right) \end{aligned} z(l)a(l)=W(l)a(l−1)+b(l)=fl(z(l))
首先根据第 l − 1 l-1 l−1层神经元的活性值(Activation ) a ( l − 1 ) \boldsymbol{a}^{(l-1)} a(l−1)计算出第 l l l层神经元的净活性值(Net Activation ) z ( l ) \boldsymbol{z}^{(l)} z(l),然后经过一个激活函数得到第 l l l层神经元的活性值。因此我们可以把每个神经元看做一个仿射变换和一个非线性变换。
上述两式也可以合写为:
a ( l ) = f l ( W ( l ) a ( l − 1 ) + b ( l ) ) \boldsymbol{a}^{(l)}=f_{l}\left(\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)} \right) a(l)=fl(W(l)a(l−1)+b(l))
整个网络可以看做是一个复合函数
ϕ ( x ; W , b ) \phi(\boldsymbol{x} ; \boldsymbol{W}, \boldsymbol{b}) ϕ(x;W,b)
其中 W \boldsymbol{W} W和 , b ,\boldsymbol{b} ,b表示网络中所有层的连接权重和偏置。
前馈神经网络具有很强的拟合能力,其非线性拟合能力可以由通用近似定理来保证.常见的连续非线性函数都可以用前馈神经网络来近似。
如果采用交叉熵损失函数,对于样本 ( x , y ) (\boldsymbol{x},y) (x,y),其损失函数为:
L ( y , y ^ ) = − y ⊤ log y ^ \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})=-\boldsymbol{y}^{\top} \log \hat{\boldsymbol{y}} L(y,y^)=−y⊤logy^
其中, y ∈ { 0 , 1 } c \boldsymbol{y} \in \{0,1\}^c y∈{0,1}c为标签 y y y对应的 one-hot 向量表示。
给定训练集为 D = { ( x ( n ) , y ( n ) ) } n = 1 N \mathcal{D}=\left\{\left(\boldsymbol{x}^{(n)}, y^{(n)}\right)\right\}_{n=1}^{N} D={(x(n),y(n))}n=1N,将每个样本 x ( n ) \boldsymbol{x}^{(n)} x(n)输入给前馈神经网络,得到网络输出为 y ^ ( n ) \hat{\boldsymbol{y}}^{(n)} y^(n),其在数据集 D \mathcal{D} D上的结构化风险函数为
R ( W , b ) = 1 N ∑ n = 1 N L ( y ( n ) , y ^ ( n ) ) + 1 2 λ ∥ W ∥ F 2 \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})=\frac{1}{N} \sum_{n=1}^{N} \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)+\frac{1}{2} \lambda\|\boldsymbol{W}\|_{F}^{2} R(W,b)=N1n=1∑NL(y(n),y^(n))+21λ∥W∥F2
其中 W \boldsymbol{W} W和 b \boldsymbol{b} b分别表示网络中所有的权重矩阵和偏置向量; W ∥ F 2 \boldsymbol{W}\|_{F}^{2} W∥F2是正则化项,用来防止过拟合; λ > 0 \lambda >0 λ>0为长参数, λ > 0 \lambda >0 λ>0越大 W \boldsymbol{W} W越接近于 0。这里的 W ∥ F 2 \boldsymbol{W}\|_{F}^{2} W∥F2一般使用 Frobenius 范数:
∥ W ∥ F 2 = ∑ l = 1 L ∑ i = 1 M l ∑ j = 1 M l − 1 ( w i j ( l ) ) 2 \|W\|_{F}^{2}=\sum_{l=1}^{L} \sum_{i=1}^{M_{l}} \sum_{j=1}^{M_{l-1}}\left(w_{i j}^{(l)}\right)^{2} ∥W∥F2=l=1∑Li=1∑Mlj=1∑Ml−1(wij(l))2
有了学习准则和训练样本,网络参数可以通过梯度下降来进行学习,在梯度下降方法的每次迭代中,第 l l l层参数 W ( l ) \boldsymbol{W}^{(l)} W(l)和 b ( l ) \boldsymbol{b}^{(l)} b(l)的更新方式为:
W ( l ) ← W ( l ) − α ∂ R ( W , b ) ∂ W ( l ) = W ( l ) − α ( 1 N ∑ n = 1 N ( ∂ L ( y ( n ) , y ^ ( n ) ) ∂ W ( l ) ) + λ W ( l ) ) b ( l ) ← b ( l ) − α ∂ R ( W , b ) ∂ b ( l ) = b ( l ) − α ( 1 N ∑ n = 1 N ∂ L ( y ( n ) , y ^ ( n ) ) ∂ b ( l ) ) \begin{aligned} \boldsymbol{W}^{(l)} & \leftarrow \boldsymbol{W}^{(l)}-\alpha \frac{\partial \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})}{\partial \boldsymbol{W}^{(l)}} \\ &=\boldsymbol{W}^{(l)}-\alpha\left(\frac{1}{N} \sum_{n=1}^{N}\left(\frac{\partial \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)}{\partial \boldsymbol{W}^{(l)}}\right)+\lambda \boldsymbol{W}^{(l)}\right) \\ \boldsymbol{b}^{(l)} & \leftarrow \boldsymbol{b}^{(l)}-\alpha \frac{\partial \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})}{\partial \boldsymbol{b}^{(l)}} \\ &=\boldsymbol{b}^{(l)}-\alpha\left(\frac{1}{N} \sum_{n=1}^{N} \frac{\partial \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)}{\partial \boldsymbol{b}^{(l)}}\right) \end{aligned} W(l)b(l)←W(l)−α∂W(l)∂R(W,b)=W(l)−α⎝⎛N1n=1∑N⎝⎛∂W(l)∂L(y(n),y^(n))⎠⎞+λW(l)⎠⎞←b(l)−α∂b(l)∂R(W,b)=b(l)−α⎝⎛N1n=1∑N∂b(l)∂L(y(n),y^(n))⎠⎞
其中, α \alpha α为学习率。
梯度下降法需要计算损失函数对参数的偏导数,如果通过链式法则逐一对每个参数求偏导比较低效,在神经网络的训练中经常使用反向传播算法来高效的计算梯度。
假设采用随机梯度下降进行网络参数学习,给定一个样本 ( x , y ) (\boldsymbol{x},\boldsymbol{y}) (x,y)将其输入到神经网络模型中,得到网络输出为 y ^ \hat{\boldsymbol{y}} y^,假设损失函数为 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L(y,y^),要进行参数学习就需要计算损失函数关于美国参数的导数。
不失一般性,对第 l l l层中的参数 W ( l ) \boldsymbol{W}^{(l)} W(l)和 b ( l ) \boldsymbol{b}^{(l)} b(l)计算偏导数,因为 ∂ L ( y , y ^ ) ∂ W ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{W}^{(l)}} ∂W(l)∂L(y,y^)的计算量涉及向量对矩阵的微分,因此我们先计算 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L(y,y^)关于参数矩阵中每个元素的偏导数,根据链式法则:
∂ L ( y , y ^ ) ∂ w i j ( l ) = ∂ z ( l ) ∂ w i j ( l ) ∂ L ( y , y ^ ) ∂ z ( l ) ∂ L ( y , y ^ ) ∂ b ( l ) = ∂ z ( l ) ∂ b ( l ) ∂ L ( y , y ^ ) ∂ z ( l ) \begin{aligned} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial w_{i j}^{(l)}} &=\frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} \\ \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{b}^{(l)}} &=\frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} \end{aligned} ∂wij(l)∂L(y,y^)∂b(l)∂L(y,y^)=∂wij(l)∂z(l)∂z(l)∂L(y,y^)=∂b(l)∂z(l)∂z(l)∂L(y,y^)
上述两式中的第二项都是目标函数关于第 l l l层的神经元 z ( l ) \boldsymbol{z}^{(l)} z(l)的偏导数,称为误差项,可以一次计算得到,这样我们只需计算三个偏导数,分别为 ∂ z ( l ) ∂ w i j ( l ) , ∂ z ( l ) ∂ b ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}}, \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} ∂wij(l)∂z(l),∂b(l)∂z(l)和 ∂ L ( y , y ^ ) ∂ z ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} ∂z(l)∂L(y,y^)。
下面分别来计算这三个偏导数。
1.计算偏导数 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} ∂wij(l)∂z(l)。因 z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) \boldsymbol{z}^{(l)}=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)} z(l)=W(l)a(l−1)+b(l),偏导数
其中 W i ( l ) \boldsymbol{W}_{i}^{(l)} Wi(l)为权重矩阵 W ( l ) \boldsymbol{W}^{(l)} W(l)的第 i i i行, I i ( a j ( l − 1 ) ) \mathbb{I}_{i}\left(a_{j}^{(l-1)}\right) Ii(aj(l−1))表示第 i i i个元素为 a j ( l − 1 ) a_{j}^{(l-1)} aj(l−1),其余为 0 的行向量。
2.计算偏导数 ∂ z ( l ) ∂ b ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} ∂b(l)∂z(l),因为 z ( l ) \boldsymbol{z}^{(l)} z(l)和 b ( l ) \boldsymbol{b}^{(l)} b(l)的函数关系为 z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) \boldsymbol{z}^{(l)}=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)} z(l)=W(l)a(l−1)+b(l),因此偏导数
∂ z ( l ) ∂ b ( l ) = I M l ∈ R M l × M l \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}}=\boldsymbol{I}_{M_{l}} \in \mathbb{R}^{M_{l} \times M_{l}} ∂b(l)∂z(l)=IMl∈RMl×Ml为 M l × M l M_{l} \times M_{l} Ml×Ml的单位矩阵。
3.计算偏导数 ∂ L ( y , y ^ ) ∂ z ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} ∂z(l)∂L(y,y^),该偏导数表示第 l l l层神经元对最终损失的影响、也反映了最终损失对第 l l l层神经元的敏感程度,因此一般称为第 l l l层神经元的误差项,用 δ ( l ) \delta^{(l)} δ(l)表示。
δ ( l ) ≜ ∂ L ( y , y ^ ) ∂ z ( l ) ∈ R M l \delta^{(l)} \triangleq \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} \in \mathbb{R}^{M_{l}} δ(l)≜∂z(l)∂L(y,y^)∈RMl
δ ( l ) \delta^{(l)} δ(l)也间接反映了不同神经元对网络能力的贡献程度,从而比较好的解决了贡献度分配问题。
回顾正向传播的过程, z ( l ) \boldsymbol{z}^{(l)} z(l)被施加激活函数 f ( ⋅ ) f(·) f(⋅)得到 a ( l ) \boldsymbol{a}^{(l)} a(l), a ( l ) \boldsymbol{a}^{(l)} a(l)乘上第 l + 1 l+1 l+1 层神经元的权重 W ( l + 1 ) \boldsymbol{W}^{(l+1)} W(l+1) 再加上偏置 b ( l + 1 ) \boldsymbol{b}^{(l+1)} b(l+1)得到第 l + 1 l+1 l+1 层神经元的激活水平 z ( l + 1 ) \boldsymbol{z}^{(l+1)} z(l+1), z ( l + 1 ) \boldsymbol{z}^{(l+1)} z(l+1)再经过后面的网络得到网络输出,最终计算出 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L(y,y^)。根据链式法则,有:
∂ L ( y , y ^ ) ∂ z ( l ) = ∂ a ( l ) ∂ z ( l ) ⋅ ∂ z ( l + 1 ) ∂ a ( l ) ⋅ ∂ L ( y , y ^ ) ∂ z ( l + 1 ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} = \frac{\partial \boldsymbol{a}^{(l)}}{\partial \boldsymbol{z}^{(l)}} ·\frac{\partial \boldsymbol{z}^{(l+1)}}{\partial \boldsymbol{a}^{(l)}} ·\frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l+1)}} ∂z(l)∂L(y,y^)=∂z(l)∂a(l)⋅∂a(l)∂z(l+1)⋅∂z(l+1)∂L(y,y^)
根据 z ( l + 1 ) = W ( l + 1 ) a ( l ) + b ( l + 1 ) \boldsymbol{z}^{(l+1)}=\boldsymbol{W}^{(l+1)} \boldsymbol{a}^{(l)}+\boldsymbol{b}^{(l+1)} z(l+1)=W(l+1)a(l)+b(l+1) 有:
∂ z ( l + 1 ) ∂ a ( l ) = ( W ( l + 1 ) ) ⊤ ∈ R M l × M l + 1 \frac{\partial \boldsymbol{z}^{(l+1)}}{\partial \boldsymbol{a}^{(l)}}=\left(\boldsymbol{W}^{(l+1)}\right)^{\top} \in \mathbb{R}^{M_{l} \times M_{l+1}} ∂a(l)∂z(l+1)=(W(l+1))⊤∈RMl×Ml+1
根据 a ( l ) = f l ( z ( l ) ) \boldsymbol{a}^{(l)}=f_{l}\left(\boldsymbol{z}^{(l)}\right) a(l)=fl(z(l)),其中 f l ( ⋅ ) f_{l}(·) fl(⋅)为按位计算的函数,因此有:
∂ a ( l ) ∂ z ( l ) = ∂ f l ( z ( l ) ) ∂ z ( l ) = diag ( f l ′ ( z ( l ) ) ) ∈ R M l × M l \begin{aligned} \frac{\partial \boldsymbol{a}^{(l)}}{\partial \boldsymbol{z}^{(l)}} &=\frac{\partial f_{l}\left(\boldsymbol{z}^{(l)}\right)}{\partial \boldsymbol{z}^{(l)}} \\ &=\operatorname{diag}\left(f_{l}^{\prime}\left(\boldsymbol{z}^{(l)}\right)\right) \quad \in \mathbb{R}^{M_{l} \times M_{l}} \end{aligned} ∂z(l)∂a(l)=∂z(l)∂fl(z(l))=diag(fl′(z(l)))∈RMl×Ml
因此,根据链式法则,第 l l l层的误差项为(式4.63):
其中 ⊙ 是向量的点积运算符,表示每个元素相乘。
从上式可以看出,第 l l l层的误差项可以通过第 l + 1 l+1 l+1层的误差项计算得到,这就是误差的反向传播(BackPropagation,BP)。反向传播的含义是第 l l l 层的一个神经元的误差项(或敏感性)是所有与该神经元相连的第 l + 1 l+1 l+1 层的神经元的误差项的权重和,然后,再乘上该神经元激活函数的梯度。
计算出上面的三个偏导数后,可以得到:
∂ L ( y , y ^ ) ∂ w i j ( l ) = I i ( a j ( l − 1 ) ) δ ( l ) = [ 0 , ⋯ , a j ( l − 1 ) , ⋯ , 0 ] [ δ 1 ( l ) , ⋯ , δ i ( l ) , ⋯ , δ M l ( l ) ] ⊤ = δ i ( l ) a j ( l − 1 ) \begin{aligned} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial w_{i j}^{(l)}} &=\mathbb{I}_{i}\left(a_{j}^{(l-1)}\right) \delta^{(l)}\\ &=\left[0, \cdots, a_{j}^{(l-1)}, \cdots, 0\right]\left[\delta_{1}^{(l)}, \cdots, \delta_{i}^{(l)}, \cdots, \delta_{M_{l}}^{(l)}\right]^{\top} \\ &=\delta_{i}^{(l)} a_{j}^{(l-1)} \end{aligned} ∂wij(l)∂L(y,y^)=Ii(aj(l−1))δ(l)=[0,⋯,aj(l−1),⋯,0][δ1(l),⋯,δi(l),⋯,δMl(l)]⊤=δi(l)aj(l−1)
其中 δ i ( l ) a j ( l − 1 ) \delta_{i}^{(l)} a_{j}^{(l-1)} δi(l)aj(l−1)相当于向量 δ ( l ) \delta^{(l)} δ(l)和向量 a ( l − 1 ) \boldsymbol{a}^{(l-1)} a(l−1)的外积的第 i , j i,j i,j 个元素。上式可进一步写为:
[ ∂ L ( y , y ^ ) ∂ W ( l ) ] i j = [ δ ( l ) ( a ( l − 1 ) ) ⊤ ] i j \left[\frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{W}^{(l)}}\right]_{i j}=\left[\delta^{(l)}\left(\boldsymbol{a}^{(l-1)}\right)^{\top}\right]_{i j} [∂W(l)∂L(y,y^)]ij=[δ(l)(a(l−1))⊤]ij
因此, L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L(y,y^)关于第 l l l层权重 W ( l ) \boldsymbol{W}^{(l)} W(l)的梯度为
∂ L ( y , y ^ ) ∂ W ( l ) = δ ( l ) ( a ( l − 1 ) ) ⊤ ∈ R M l × M l − 1 (4.68) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{W}^{(l)}}=\delta^{(l)}\left(\boldsymbol{a}^{(l-1)}\right)^{\top} \in \mathbb{R}^{M_{l} \times M_{l-1}} \tag{4.68} ∂W(l)∂L(y,y^)=δ(l)(a(l−1))⊤∈RMl×Ml−1(4.68)
同理, L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L(y,y^)关于第 l l l层偏置 b ( l ) \boldsymbol{b}^{(l)} b(l)的梯度为
∂ L ( y , y ^ ) ∂ b ( l ) = δ ( l ) ∈ R M l (4.69) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{b}^{(l)}}=\delta^{(l)} \in \mathbb{R}^{M_{l}} \tag{4.69} ∂b(l)∂L(y,y^)=δ(l)∈RMl(4.69)
在计算出每一层的误差项之后,我们就可以得到每层参数的梯度。因此使用误差反向传播算法的前馈神经网络训练过程可以分为以下三步:
参考链接,一篇详细推导神经网络反向传播算法的文章。
我们可以用链式法则手动推导损失函数对每个参数的梯度公式,然后进行代码实现。但实际上参数的梯度可以让计算机来自动计算。目前主流的深度学习框架都包含了自动梯度计算的功能,即我们可以只考虑网络结构,其梯度可以自动进行计算,无须人工干预。
自动计算梯度的方法有三类:数值微分、符号微分和自动微分。下面仅介绍自动微分方法。
自动微分
automatic Differentiation,AD,是一种可以对一个(程序)函数进行计算导数的方法。
自动微分的基本原理是所有数值计算可以分解为一些基本操作(+,-,x,/)和一些初等函数 exp,log,sin,cos 等,然后利用链式法则来自动计算一个复合函数的梯度。
计算图
在进行自动微分前,首先要把复合函数分解为一系列基本操作,并构成一个计算图(computational graph)。计算图是数学运算的图像化表示,计算图中的每个非叶子节点表示一个基本操作,每个叶子节点为一个输入变量或常量。
下面给出了复合函数
f ( x ; w , b ) = 1 exp ( − ( w x + b ) ) + 1 f(x ; w, b)=\frac{1}{\exp (-(w x+b))+1} f(x;w,b)=exp(−(wx+b))+11
当输入标量 x = 1 x=1 x=1,权重和偏置参数 w = 0 , b = 0 w=0,b=0 w=0,b=0时的计算图。其中连边上的红色数字表示前向计算时,复合函数中每个变量的实际取值。
从图中可以看出,复合函数由 6 个基本函数组成。每个基本函数函数的导数都十分简单,可以通过规则实现。
按照计算导数的顺序,自动微分可以分为前向模式和反向模式。
前向模式按照计算图中的计算方向来递归的计算梯度。
反向模式是按计算图中计算方向相反的方向来递归的计算梯度。以 ∂ f ( x ; w , b ) ∂ h 6 \frac{\partial f(x ; w, b)}{\partial h_{6}} ∂h6∂f(x;w,b)为例,当 x = 1 x=1 x=1, w = 0 , b = 0 w=0,b=0 w=0,b=0 时,反向模式的累积计算顺序如下:
∂ f ( x ; w , b ) ∂ h 6 = 1 ∂ f ( x ; w , b ) ∂ h 5 = ∂ f ( x ; w , b ) ∂ h 6 ∂ h 6 ∂ h 5 = 1 × − 0.25 ∂ f ( x ; w , b ) ∂ h 4 = ∂ f ( x ; w , b ) ∂ h 5 ∂ h 5 ∂ h 4 = − 0.25 × 1 = − 0.25 ⋮ ∂ f ( x ; w , b ) ∂ w = ∂ f ( x ; w , b ) ∂ h 1 ∂ h 1 ∂ w = 0.25 × 1 = 0.25 \begin{array}{l}\frac{\partial f(x ; w, b)}{\partial h_{6}}=1 \\ \frac{\partial f(x ; w, b)}{\partial h_{5}}=\frac{\partial f(x ; w, b)}{\partial h_{6}} \frac{\partial h_{6}}{\partial h_{5}}=1 \times-0.25 \\ \frac{\partial f(x ; w, b)}{\partial h_{4}}=\frac{\partial f(x ; w, b)}{\partial h_{5}} \frac{\partial h_{5}}{\partial h_{4}}=-0.25 \times 1=-0.25 \\ \vdots \\ \frac{\partial f(x ; w, b)}{\partial w}=\frac{\partial f(x ; w, b)}{\partial h_{1}} \frac{\partial h_{1}}{\partial w}=0.25 \times 1=0.25\end{array} ∂h6∂f(x;w,b)=1∂h5∂f(x;w,b)=∂h6∂f(x;w,b)∂h5∂h6=1×−0.25∂h4∂f(x;w,b)=∂h5∂f(x;w,b)∂h4∂h5=−0.25×1=−0.25⋮∂w∂f(x;w,b)=∂h1∂f(x;w,b)∂w∂h1=0.25×1=0.25
反向模式和反向传播的计算梯度的方式相同。而且反向模式相比正向模式更高效。
静态计算图和动态计算图
静态计算图是在编译时构建计算图,计算图构建好之后在程序运行时不能变更。动态计算图是在程序运行时动态构建。
静态计算图在构建时可以进行优化,并行能力强,但灵活性较差。动态计算图不容易优化,当不同输入的网络结构不一致时难以并行计算,但灵活性较高。
目前的深度学习框架里,Tensorflow和Theano采用的静态计算图,PyTorch,DyNet 、Chainer 是动态计算图。TensorFlow2.0 也支持了动态计算图。
神经网络的优化问题是一个非凸优化问题。
误差反向传播的迭代公式为:
δ ( l ) = f l ′ ( z ( l ) ) ⊙ ( W ( l + 1 ) ) ⊤ δ ( l + 1 ) \delta^{(l)}=f_{l}^{\prime}\left(z^{(l)}\right) \odot\left(W^{(l+1)}\right)^{\top} \delta^{(l+1)} δ(l)=fl′(z(l))⊙(W(l+1))⊤δ(l+1)
误差从输出层反向传播时,每层都要乘以该层的激活函数的导数,当我们使用 Sigmoid型函数(Logistic、Tanh)时,其导数的值域都小于或等于 1。这样误差经过每层的传递都会不断衰减,甚至消失,使得网络难以训练。这就是梯度消失问题(Vanishing Gradient Problem)。