h t = σ ( W ( h h ) h t − 1 + W ( h x ) x [ t ] ) (5) h_t=\sigma(W^{(hh)}h_{t-1}+W^{(hx)}x_{[t]}) \tag{5} ht=σ(W(hh)ht−1+W(hx)x[t])(5)
y ^ t = s o f t m a x ( W ( S ) h t ) (6) \hat{y}_t=softmax(W^{(S)}h_t) \tag{6} y^t=softmax(W(S)ht)(6)
其中:
x 1 , . . x T x_1,..x_T x1,..xT: 表示总共T个词汇的预料中各个词语的词向量。
h t h_t ht是每次迭代的隐层输出。
x t ∈ R d x_t \in R^d xt∈Rd: 第t步的输入,词向量维度d。
$W^{hx} \in R^{D_h \times d } $: 输入x的权重矩阵。
W h h ∈ R D h × D h W^{hh} \in R^{D_h \times D_h} Whh∈RDh×Dh: 前一轮 h t − 1 h_{t-1} ht−1的权重矩阵。
h t − 1 ∈ R D h h_{t-1} \in R^{D_h} ht−1∈RDh: 前一轮迭代的非线性函数输出。
σ ( ) \sigma() σ(): 非线性激活函数,例如sigmoid。
y ^ t ∈ R ∣ V ∣ \hat{y}_t \in R^{|V|} y^t∈R∣V∣: 每一轮迭代t针对全部词汇的输出概率分布。|V|是其label的维度,如果是分类就是类的个数。W s ∈ R ∣ V ∣ × D h W^{s} \in R^{|V| \times D_h} Ws∈R∣V∣×Dh
通常是交叉熵,迭代t中,交叉熵如下(其中 y t , j y_{t,j} yt,j是真实标签):
J ( t ) ( θ ) = − ∑ j = 1 ∣ V ∣ y t , j × log ( y ^ t , j ) (7) J^{(t)}(\theta)=-\sum_{j=1}^{|V|}y_{t,j}\times \log(\hat{y}_{t,j}) \tag{7} J(t)(θ)=−j=1∑∣V∣yt,j×log(y^t,j)(7)
在规模为T的语料(相当于样本个数)上,交叉熵错误的计算:
J = − 1 T ∑ t = 1 T J ( t ) ( θ ) = − 1 T ∑ t = 1 T ∑ j = 1 ∣ V ∣ y t , j × log ( y ^ t , j ) (8) J=-\frac{1}{T}\sum_{t=1}^{T}J^{(t)}(\theta)=-\frac{1}{T}\sum_{t=1}^{T}\sum_{j=1}^{|V|}y_{t,j}\times \log{(\hat{y}_{t,j})} \tag{8} J=−T1t=1∑TJ(t)(θ)=−T1t=1∑Tj=1∑∣V∣yt,j×log(y^t,j)(8)
在某轮迭代tt中考虑公式5、6,用于计算RNN错误 d E / d W dE/dW dE/dW,我们对每一步迭代计算错误率总和。那么每一步tt的错误率 d E t / d W dE_t/dW dEt/dW均可通过前面所列的计算出来。
∂ E ∂ W = ∑ t = 1 T ∂ E t ∂ W (10) \frac{\partial{E}}{\partial{W}}=\sum_{t=1}^T\frac{\partial E_{t}}{\partial{W}}\tag{10} ∂W∂E=t=1∑T∂W∂Et(10)
链式法则求导得到每一个迭代步长错误率, d h t / d h k dh_t/dh_k dht/dhk为对之前kk次迭代的偏导数。
∂ E t ∂ W = ∑ k = 1 t ∂ E t ∂ y t ∂ y t ∂ h t ∂ h t ∂ h k ∂ h k ∂ W (11) \frac{\partial E_{t}}{\partial W}=\sum_{k=1}^t \frac{\partial E_{t}}{\partial y_{t}} \frac{\partial y_{t}}{\partial h_{t}}\frac{\partial h_{t}}{\partial h_{k}} \frac{\partial h_{k}}{\partial W} \tag{11} ∂W∂Et=k=1∑t∂yt∂Et∂ht∂yt∂hk∂ht∂W∂hk(11)
问题在于 ∂ h t ∂ h k \frac{ \partial h_{t} }{ \partial h_{k}} ∂hk∂ht。
∂ h t ∂ h k = ∏ j = k + 1 t ∂ h j ∂ h j − 1 = ∏ j = k + 1 t W h h T × σ ′ (12) \frac{\partial h_{t}}{\partial h_{k}}=\prod_{j=k+1}^t \frac{\partial h_{j}}{\partial h_{j-1}}=\prod_{j=k+1}^t W_{hh}^T \times \sigma' \tag{12} ∂hk∂ht=j=k+1∏t∂hj−1∂hj=j=k+1∏tWhhT×σ′(12)
对于每个元素求导 W D n × D n W^{D_n \times D_n} WDn×Dn,其Jacobian矩阵:
∂ h j ∂ h j − 1 = [ ∂ h j ∂ h j − 1 , 1 … ∂ h j ∂ h j − 1 , D n ] = [ ∂ h j , 1 ∂ h j − 1 , 1 … ∂ h j , 1 ∂ h j − 1 , D n ⋮ ⋱ ⋮ ∂ h j , D n ∂ h j − 1 , 1 … ∂ h j , D n ∂ h j − 1 , D n ] (13) \frac{\partial h_{j}}{\partial h_{j-1}}=[\frac{\partial h_{j}}{\partial h_{j-1,1}} \dots \frac{\partial h_{j}}{\partial h_{j-1,D_n}}]=\begin{bmatrix}\frac{\partial h_{j,1}}{\partial h_{j-1,1}} & \dots & \frac{\partial h_{j,1}}{\partial h_{j-1,D_n}} \\ \vdots & \ddots & \vdots \\ \frac{\partial h_{j,D_n}}{\partial h_{j-1,1}} & \dots & \frac{\partial h_{j,D_n}}{\partial h_{j-1,D_n}} \end{bmatrix} \tag{13} ∂hj−1∂hj=[∂hj−1,1∂hj…∂hj−1,Dn∂hj]=⎣⎢⎢⎡∂hj−1,1∂hj,1⋮∂hj−1,1∂hj,Dn…⋱…∂hj−1,Dn∂hj,1⋮∂hj−1,Dn∂hj,Dn⎦⎥⎥⎤(13)
结合10,11,12,得到:
∂ E ∂ W = ∑ t = 1 T ∑ k = 1 t ∂ E t ∂ y t ∂ y t ∂ h t ( ∏ j = k + 1 t ∂ h j ∂ h j − 1 ) ∂ h k ∂ W (14) \frac{\partial E}{\partial W}=\sum_{t=1}^T\sum_{k=1}^t \frac{\partial E_{t}}{\partial y_{t}} \frac{\partial y_{t}}{\partial h_{t}}(\prod_{j=k+1}^t \frac{\partial h_{j}}{\partial h_{j-1}}) \frac{\partial h_{k}}{\partial W} \tag{14} ∂W∂E=t=1∑Tk=1∑t∂yt∂Et∂ht∂yt(j=k+1∏t∂hj−1∂hj)∂W∂hk(14)
梯度爆炸:如果Jacobian矩阵的值非常大,参照激活函数及网络参数可能会出现梯度爆炸,即所谓的梯度爆炸问题。
https://zhuanlan.zhihu.com/p/28687529
sigmoid:
f ( z ) = 1 / ( 1 + e x p ( − z ) ) f ( z ) ′ = f ( z ) ( 1 − f ( z ) ) f(z) = 1 / (1 + exp( − z)) \\ f(z)' = f(z)(1 − f(z)) f(z)=1/(1+exp(−z))f(z)′=f(z)(1−f(z))
sigmoid函数在两端的导数均为0,近乎呈直线状(导数为0,函数图像为直线),此种情况下可称相应的神经元已经饱和。两函数的梯度为0,使前层的其它梯度也趋近于0。由于矩阵元素数值较小,且矩阵相乘数次(t - k次)后,梯度值迅速以指数形式收缩(意思相近于,小数相乘,数值收缩,越来越小),最终在几个时间步长后完全消失。“较远”的时间步长贡献的梯度变为0,这些时间段的状态不会对你的学习有所贡献:你最终还是无法学习长期依赖。梯度消失不仅存在于循环神经网络,也出现在深度前馈神经网络中。区别在于,循环神经网络非常深(本例中,深度与句长相同),因此梯度消失问题更为常见。
解决梯度爆炸问题,Thomas Mikolov首先提出了一个简单的启发性的解决方案,就是当梯度大于一定阈值的的时候,将它截断为一个较小的数。
解决梯度弥散的问题,两种方法。第一种方法是将随机初始化 W ( h h ) W^{(hh)} W(hh)改为一个有关联的矩阵初始化。第二种方法是使用ReLU(Rectified Linear Units)代替sigmoid函数。ReLU的导数不是0就是1.因此不太可能会出现梯度消失的情况。
当间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。Bengio, et al. (1994)
借助LSTM架构。LSTM只有状态 C t C_t Ct传递。
展开为:
C t = f t C t − 1 + i t x t = σ ( W f X t + b f ) C t − 1 + σ ( W i X t + b i ) X t h t = t a n h ( C t ) ∗ o i C_t = f_t C_{t-1}+i_tx_t =\sigma(W_f X_t+b_f)C_{t-1} + \sigma(W_iX_t+b_i)X_t \\ h_t = tanh(C_t)*o_i Ct=ftCt−1+itxt=σ(WfXt+bf)Ct−1+σ(WiXt+bi)Xtht=tanh(Ct)∗oi
求导:
∏ j = k + 1 t ∂ h j ∂ C j − 1 = ∏ j = k + 1 t t a n h ′ σ ( W f X t + b f ) \prod_{j=k+1}^t \frac{\partial h_{j}}{\partial C_{j-1}} = \prod_{j=k+1}^t tanh' \sigma(W_f X_t+b_f) j=k+1∏t∂Cj−1∂hj=j=k+1∏ttanh′σ(WfXt+bf)
其函数图像为:基本不是0就是1。
现代的LSTM使用的是累加的形式计算状态。这种形式导致导数也是累加形式,因此避免了梯度消失。
细胞状态在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。
如何利用上下文信息做预测。
Irsoy等人设计了一个双向深度神经网络,在每一个时间节点t,这个网络有两层神经元,一层从左向右传播,另一层从右向左传播。为了保证任何时刻t都有两层隐层,这个网络需要消耗两倍的存储量来存储权重和偏置等参数。最终的分类结果是由两层RNN隐层组合来产生最终的结果。
h → t = f ( W → x t + V → h → t − 1 + b → ) h ← t = f ( W ← x t + V ← h ← t + 1 + b ← ) y ^ t = g ( U h t + c ) = g ( U [ h → t ; h ← t ] + c ) \overset{\rightarrow }{h}_t = f \left ( \overset{\rightarrow }{W}x_t + \overset{\rightarrow }{V}\overset{\rightarrow }{h}_{t-1}+\overset{\rightarrow }{b} \right ) \\ \overset{\leftarrow }{h}_t = f \left ( \overset{\leftarrow }{W}x_t + \overset{\leftarrow }{V}\overset{\leftarrow }{h}_{t+1}+\overset{\leftarrow }{b} \right ) \\ \hat{y}_t=g\left ( Uh_t+c \right )=g\left ( U\left[\overset{\rightarrow }{h}_t;\overset{\leftarrow }{h}_t\right] +c\right ) h→t=f(W→xt+V→h→t−1+b→)h←t=f(W←xt+V←h←t+1+b←)y^t=g(Uht+c)=g(U[h→t;h←t]+c)
对过去记忆单元是否对当前记忆单元的计算有用做出评估。例如出现了新的主语,希望忘记旧的主语。
f t = σ ( W ( f ) x t + U ( f ) h t − 1 ) (Forget gate) f_t = \sigma \left( W^{\left( f\right)}x_t+U^{\left(f \right)}h_{t-1}\right) \tag{Forget gate} ft=σ(W(f)xt+U(f)ht−1)(Forget gate)
在产生新记忆之前,我们需要判定一下我们当前看到的新词到底重不重要,这就是输入门的作用。
输入门根据输入词和过去隐层状态共同判定输入值是否值得保留,从而判定它以何种程度参与生成新的记忆(或者说对新的记忆做一个约束)。因此,它可以作为输入信息更新的一个指标。
sigmoid
层称 “输入门层” 决定什么值我们将要更新。然后,一个 tanh
层创建一个新的候选值向量,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M3mitoKF-1602239926120)(https://math.jianshu.com/math?formula=%5Ctilde%7BC%7D_t)],会被加入到状态中。下一步,我们会讲这两个信息来产生对状态的更新。
在我们语言模型的例子中,我们希望增加新的主语的性别到细胞状态中,来替代旧的需要忘记的主语,使用输入词 x t x_t xt和过去隐层状态 h t − 1 ht−1 ht−1来产生新的记忆 c ~ t \tilde{c}_t c~t.
产生新的记忆之后,就涉及更新细胞状态C。
决定输出什么值,输出主要是依赖于 cell 的状态 C t C_t Ct,但是又不仅仅依赖于 C t C_t Ct。
- 使用一个sigmoid层来(计算出)决定 C t C_t Ct权重,决定哪些信息会被输出;
- 把 C t C_t Ct通过一个 tanh 层([-1, 1]),然后把 tanh 层的输出和 sigmoid 层计算出来的权重相乘,这样就得到了最后输出的结果。
参数量: W i , U i , W f , U f , W o , U o , W c , U c W_i, U_i, W_f, U_f, W_o, U_o, W_c, U_c Wi,Ui,Wf,Uf,Wo,Uo,Wc,Uc
使用门限激活函数改进RNN的一种方法。
GRU有两种门:
z t = σ ( W ( z ) x t + U ( z ) h t − 1 ) (Update gate) z_t = \sigma \left( W^{\left(z \right)}x_t + U^{\left ( z \right )}h_{t-1}\right) \tag{Update gate} zt=σ(W(z)xt+U(z)ht−1)(Update gate)
r t = σ ( W ( r ) x t + U ( r ) h t − 1 ) (Reset gate) r_t = \sigma \left ( W^{\left ( r \right )}x_t + U^{\left ( r \right )}h_{t-1} \tag{Reset gate}\right ) rt=σ(W(r)xt+U(r)ht−1)(Reset gate)
h ~ t = tanh ( r t ∘ U h t − 1 + W x t ) (New memory) \tilde{h}_t = \tanh \left ( r_t \circ Uh_{t-1}+Wx_t \right ) \tag{New memory} h~t=tanh(rt∘Uht−1+Wxt)(New memory)
h t = ( 1 − z t ) ∘ h ~ t + z t ∘ h t − 1 (Hidden state) h_t = \left ( 1-z_t \right )\circ \tilde{h}_t +z_t \circ h_{t-1} \tag{Hidden state} ht=(1−zt)∘h~t+zt∘ht−1(Hidden state)
x t ∈ R d x_t \in R^d xt∈Rd: 第t步的输入,词向量维度d。
$W, W^{z}, W^{r} \in R^{D_h \times d } $: 输入x的权重矩阵。
U , U r , U z ∈ R D h × D h U, U^{r}, U^{z} \in R^{D_h \times D_h} U,Ur,Uz∈RDh×Dh: 前一轮 h t − 1 h_{t-1} ht−1的权重矩阵。
h t − 1 ∈ R D h h_{t-1} \in R^{D_h} ht−1∈RDh: 前一轮迭代的非线性函数输出。
σ ( ) \sigma() σ(): 非线性激活函数,例如sigmoid。
y ^ t ∈ R ∣ V ∣ \hat{y}_t \in R^{|V|} y^t∈R∣V∣: 每一轮迭代t针对全部词汇的输出概率分布。|V|是其label的维度,如果是分类就是类的个数。
W s ∈ R ∣ V ∣ × D h W^{s} \in R^{|V| \times D_h} Ws∈R∣V∣×Dh
参数有 W , W r , W z , U , U r , U z W, W^r,W^z,U, U^r, U^z W,Wr,Wz,U,Ur,Uz
RNN核心在于对向量的序列进行操作:输入可以是序列,输出也可以是序列,在最一般化的情况下输入输出都可以是序列。
每个正方形代表一个向量,箭头代表函数(比如矩阵乘法)。输入向量是红色,输出向量是蓝色,绿色向量装的是RNN的状态(马上具体介绍)。从左至右为:
- 非RNN的普通过程,从固定尺寸的输入到固定尺寸的输出(比如图像分类)。
- 输出是序列(例如图像标注:输入是一张图像,输出是单词的序列)。
- 输入是序列(例如情绪分析:输入是一个句子,输出是对句子属于正面还是负面情绪的分类)。
- 输入输出都是序列(比如机器翻译:RNN输入一个英文句子输出一个法文句子)。
- 同步的输入输出序列(比如视频分类中,我们将对视频的每一帧都打标签)。