1.递归神经网络
当运用前馈神经网络时,神经网络会以为咱们t时刻输入的内容与t-1时刻输入的内容完全无关,关于许多情况,例如图片分类识别,这是毫无问题的,可是关于一些情景,例如自然语言处理 (NLP, Natural Language Processing) 或许咱们需求剖析相似于连拍照片这样的数据时,合理运用t或之前的输入来处理t+n时刻明显能够愈加合理的运用输入的信息。为了运用到时刻维度上信息,人们设计了递归神经网络 (RNN, Recurssion Neural Network),一个简单的递归神经网络能够用这种方法表明。
U是输入层到躲藏层的权重矩阵,O也是一个向量,它表明输出层的值;V是躲藏层到输出层的权重矩阵。循环神经网络的躲藏层的值S不仅仅取决于当前这次的输入x,还取决于上一次躲藏层的值s。权重矩阵W就是躲藏层上一次的值作为这一次的输入的权重。
2. LSTM简介
LSTM(Long Short-Term Memory)是一种循环神经网络(RNN)的变体,用于处理和猜测时刻序列数据。它在处理长时刻依靠联系(长距离依靠)时比传统的RNN更有用。
LSTM经过引进称为“细胞状况”(cell state)的概念来处理传统RNN中的梯度消失和梯度爆破问题。细胞状况能够沿着时刻步长坚持不变,而且能够挑选性地添加或删除信息。这样,LSTM能够更好地捕捉长时刻依靠联系,由于它能够挑选性地忘记或保留曩昔的信息。
it=(Wiixt+bii+Whiht−1+bhi)ft=(Wijxt+bif+Whfht−1+bhf)gt=tanh(Wigxt+big+Whght−1+bhg)gt=(Wioxt+bio+Whoht−1+bho)ct=ft⊙ct−1+it⊙gtht=ot⊙tanh(ct)\begin{array}{l}i_t=\sigma(W_{ii}x_t+b_{ii}+W_{hi}h_{t-1}+b_{hi})\\ f_t=\sigma(W_{ij}x_t+b_{if}+W_{hf}h_{t-1}+b_{hf})\\ g_t=\tanh(W_{ig}x_t+b_{ig}+W_{hg}h_{t-1}+b_{hg})\\ g_t=\sigma(W_{io}x_t+b_{io}+W_{ho}h_{t-1}+b_{ho})\\ c_t=f_t\odot c_{t-1}+i_t\odot g_t\\ h_t=o_t\odot\tanh(c_t)\end{array}it=(Wiixt+bii+Whiht−1+bhi)ft=(Wijxt+bif+Whfht−1+bhf)gt=tanh(Wigxt+big+Whght−1+bhg)gt=(Wioxt+bio+Whoht−1+bho)ct=ft⊙ct−1+it⊙gtht=ot⊙tanh(ct)
LSTM由三个门控单元组成:输入门(input gate)、忘记门(forget gate)和输出门(output gate)。输入门操控是否更新细胞状况,忘记门操控是否删除曩昔的信息,输出门操控将细胞状况转化为输出。
LSTM的作业原理是经过学习门控单元的权重来确定是否更新细胞状况和输出。这些权重是经过反向传达算法和梯度下降来练习的。在练习过程中,LSTM能够主动学习到时刻序列中的模式和规矩,然后进行猜测和分类任务。
由于LSTM的能力和作用,在自然语言处理、语音识别、机器翻译等领域得到了广泛应用。它在处理长文本、长句子和长时刻序列数据方面体现出色,成为深度学习中非常重要的一种模型。
3.RNN梯度消失和梯度爆破原因
在一般RNN中,躲藏向量和输出的核算如下:
St=tanh(U⋅Xt+W⋅St−1)Ot=V⋅St\begin{matrix}S_t=tanh(U\cdot X_t+W\cdot S_{t-1})\\ O_t=V\cdot S_t\quad\\ \end{matrix}St=tanh(U⋅Xt+W⋅St−1)Ot=V⋅St
为了经过时刻进行反向传达来练习RNN,咱们需求核算E相关于W的梯度。总差错梯度等于每个时刻步长的差错梯度之和。关于步骤t,咱们能够运用多元链式规矩来导出差错梯度,如下所示:
∂Et∂W=∑i=0t∂Et∂yt∂yt∂St∂St∂Si∂Si∂W\frac{\partial E_t}{\partial W}=\sum_{i=0}^t\frac{\partial E_t}{\partial y_t}\frac{\partial y_t}{\partial S_t}\frac{\partial S_t}{\partial S_i}\frac{\partial S_i}{\partial W}∂W∂Et=i=0∑t∂yt∂Et∂St∂yt∂Si∂St∂W∂Si
现在这儿除了∂St/∂Si都能够很容易地核算出来,∂St/∂Si详细核算公式如下(diag将向量转化为对角矩阵):
∂St∂Si=∂St∂St−1∂St−1∂St−2…∂Si+1∂Si=∏k=1t−1∂Sk+1∂Sk\frac{\partial S_t}{\partial S_i}=\frac{\partial S_t}{\partial S_{t-1}}\frac{\partial S_{t-1}}{\partial S_{t-2}}…\frac{\partial S_{i+1}}{\partial S_i}=\prod_{k=1}^{t-1}\frac{\partial S_{k+1}}{\partial S_{k}}∂Si∂St=∂St−1∂St∂St−2∂St−1…∂Si∂Si+1=k=1∏t−1∂Sk∂Sk+1
∂Sk+1∂Sk=diag(f′(Uxi+Whi−1))W\frac{\partial S_{k+1}}{\partial S_k}=diag(f'(Ux_i+Wh_{i-1}))W∂Sk∂Sk+1=diag(f′(Uxi+Whi−1))W
因而,假如咱们想经过k个时刻步长进行反向传达,则该梯度将为
∂Sk∂S1=∏kdiag(f′(Uxi+WSi−1))W\frac{\partial S_k}{\partial S_1}=\prod^{k}diag(f'(Ux_i+WS_{i-1}))W∂S1∂Sk=∏kdiag(f′(Uxi+WSi−1))W
如本文所示,假如矩阵W的主特征值大于1,则梯度爆破。假如小于1,则渐变消失。值得留意的是f′(x)f'(x)f′(x)的值将始终小于1,因而,假如W值太小,那么导数必然会变为0。小于1值的重复相乘将远远小于W的重复相乘。相反,使W过大,导数将变为无穷大,由于W的幂运算将超过小于1的值的重复乘法。在实践中,消失梯度更为常见,因而咱们将主要重视这一点。假如梯度消失,就意味着前期的躲藏状况对后期的躲藏状况没有真正的影响,这意味着没有学到长时刻的依靠联系。
4.LSTM可避免梯度消失原因
导致梯度消失的最大罪魁祸首是咱们需求核算的递归导数:∂St/∂Si∂S_t/∂S_i∂St/∂Si。假如这个导数是“体现杰出的”(也就是说,当咱们经过层反向传达时,它不会变为0或无穷大),那么咱们就能够学习长时刻依靠联系。
开始的LSTM处理方案,LSTM引进了一个单独的单元状况CtC_tCt。在开始的1997 LSTM中,Ct的值取决于单元状况的先前值和由输入门值加权的更新项:
Ct=Ct−1+iC~tC_t=C_{t-1}+i\tilde{C}_tCt=Ct−1+iC~t
这种结构作用欠安,由于细胞状况往往无法操控地成长。为了避免这种无限增长,添加了一个忘记门来缩放之前的细胞状况,然后产生了更现代的公式:
Ct=fCt−1+iCt~C_t=fC_{t-1}+i\tilde{C_t}Ct=fCt−1+iCt~
∂Ct/∂Ct-1展开式:
∂Ct∂Ct−1=∂Ct∂ft∂ft∂ht−1∂ht−1∂Ct−1+∂Ct∂it∂it∂ht−1∂ht−1∂Ct−1+∂Ct∂C~t∂C~t∂ht−1∂ht−1∂Ct−1+∂Ct∂Ct−1\begin{aligned}\frac{\partial C_t}{\partial C_{t-1}}=\frac{\partial C_t}{\partial f_t}\frac{\partial f_t}{\partial h_{t-1}}\frac{\partial h_{t-1}}{\partial C_{t-1}}+\frac{\partial C_t}{\partial i_t}\frac{\partial i_t}{\partial h_{t-1}}\frac{\partial h_{t-1}}{\partial C_{t-1}}\\ +\frac{\partial C_t}{\partial\tilde C_{t}}\frac{\partial\tilde C_t}{\partial h_{t-1}}\frac{\partial h_{t-1}}{\partial C_{t-1}}+\frac{\partial C_t}{\partial C_{t-1}}\end{aligned}∂Ct−1∂Ct=∂ft∂Ct∂ht−1∂ft∂Ct−1∂ht−1+∂it∂Ct∂ht−1∂it∂Ct−1∂ht−1+∂C~t∂Ct∂ht−1∂C~t∂Ct−1∂ht−1+∂Ct−1∂Ct
清晰写出:
∂Ct∂Ct−1=Ct−1′(⋅)Wf∗ot−1tanh′(Ct−1)+C~t′(⋅)Wi∗ot−1tanh′(Ct−1)+ittanh′(⋅)WC∗ot−1tanh′(Ct−1)+ft\begin{aligned}\frac{\partial C_t}{\partial C_{t-1}}=C_{t-1}\sigma'(\cdot)W_f*o_{t-1}tanh'(C_{t-1})\\ +\tilde C_t\sigma'(\cdot)W_i*o_{t-1}tanh'(C_{t-1})\\ +i_t\tanh'(\cdot)W_C*o_{t-1}tanh'(C_{t-1}) +f_t\end{aligned}∂Ct−1∂Ct=Ct−1′(⋅)Wf∗ot−1tanh′(Ct−1)+C~t′(⋅)Wi∗ot−1tanh′(Ct−1)+ittanh′(⋅)WC∗ot−1tanh′(Ct−1)+ft
现在,假如咱们想反向传达k个时刻步长,咱们只需乘以k倍以上的项。请留意这个递归梯度与一般RNN的递归梯度之间的巨大差异。在一般RNN中,项∂St/∂Si∂S_t/∂S_i∂St/∂Si终究将取一个总是高于1或总是在[0,1]范围内的值,这本质上是导致消失/爆破梯度问题的原因。
在任何时刻步长,这儿的项∂Ct/∂Ct−1∂C_t/∂C_{t-1}∂Ct/∂Ct−1能够取大于1的值,也能够取[0,1]范围内的值。因而,假如咱们扩展到无限数量的时刻步长,就不能保证咱们终究会收敛到0或无穷大(与一般RNN不同)。假如咱们开始收敛到零,咱们总是能够将ftf_tft(和其他门值)的值设置得更高,以使∂Ct/∂Ct−1∂C_t/∂C_{t-1}∂Ct/∂Ct−1的值更接近1,然后避免梯度消失(或许至少避免它们消失得太快)。需求留意的一件重要事情是,值ftf_tft、oto_tot、C~t\tilde{C}_t C~t( 以当前输入和躲藏状况为条件)。因而,经过这种方法,网络学会了经过相应地设置门值来决定何时让梯度消失,何时坚持梯度!
这一切看起来可能很神奇,但实际上只是两件主要事情的成果:
- 细胞状况的加法更新函数给出了一个更“体现杰出”的导数。
- 门控函数答应网络决定梯度消失的程度,而且能够在每个时刻步长取用不同的值。它们所取的值是当前输入和躲藏状况的学习函数。
5.LSTM参数
关于输入序列中的每个元素,每个层核算以下函数:
it=(Wiixt+bii+Whiht−1+bhi)ft=(Wijxt+bif+Whfht−1+bhf)gt=tanh(Wigxt+big+Whght−1+bhg)gt=(Wioxt+bio+Whoht−1+bho)ct=ft⊙ct−1+it⊙gtht=ot⊙tanh(ct)\begin{array}{l}i_t=\sigma(W_{ii}x_t+b_{ii}+W_{hi}h_{t-1}+b_{hi})\\ f_t=\sigma(W_{ij}x_t+b_{if}+W_{hf}h_{t-1}+b_{hf})\\ g_t=\tanh(W_{ig}x_t+b_{ig}+W_{hg}h_{t-1}+b_{hg})\\ g_t=\sigma(W_{io}x_t+b_{io}+W_{ho}h_{t-1}+b_{ho})\\ c_t=f_t\odot c_{t-1}+i_t\odot g_t\\ h_t=o_t\odot\tanh(c_t)\end{array}it=(Wiixt+bii+Whiht−1+bhi)ft=(Wijxt+bif+Whfht−1+bhf)gt=tanh(Wigxt+big+Whght−1+bhg)gt=(Wioxt+bio+Whoht−1+bho)ct=ft⊙ct−1+it⊙gtht=ot⊙tanh(ct)
hth_tht、ctc_tct、xtx_txt分别是时刻t的躲藏状况、单元格状况和输入,ht−1h_{t-1}ht−1是在时刻t-1的层的躲藏状况或在时刻0的初始躲藏状况。
iti_tit、ftf_tft、gtg_tgt、oto_tot分别为输入门、忘记门、神经单元、输出门。是sigmoid函数,⊙是Hadamard乘积。
参数:
- input_size-输入x中预期的特征数
- hidden_size-躲藏状况h的特征数量
- num_size-重复呈现的层数。例如,设置num_layers=2意味着将两个LSTM堆叠在一起以形成堆叠的LSTM,第二个LSTM接收第一个LSTM的输出并核算终究成果。默认值:1
- bias-假如为False,则层不运用偏移权重bihb_{ih}bih和bhhb_{hh}bhh。默认值:True
- batch_first-假如为True,输入张量:(batch,seq,feature),否则为(seq,batch,feature)。默认值:False
- dropout-假如非零,则在除最终一层之外的每个LSTM层的输出上引进丢掉层,丢掉概率等于丢掉。
- bidirectional-假如为True,则变为双向LSTM。默认值:False
- proj_size-LSTM网络的变体,即LSTMP,削减LSTM的参数和核算量,进行h_t进行紧缩,功能损失不大运用。默认值:0
输入:
- input-当batch_first=False时:(L,N,Hin)(L,N,H_{in})(L,N,Hin),batch_first=Ture时:(N,L,Hin)(N,L,H_{in})(N,L,Hin)。
- h_0-(D∗numlayers,N,Hout)(D*\operatorname{num} \operatorname{layers},N,H_{out})(D∗numlayers,N,Hout)
- c_0-(D∗numlayers,N,Hcell)(D*\operatorname{num}\operatorname{layers},N,H_{cell})(D∗numlayers,N,Hcell)
N=batchsizeL=sequencelengthD=2ifbiirectional=Trueotherwise1Hin=input-sizeHdet=hideHdet=pair-sizeHdet=pair-sizeifproj-size>0otherwisehidden-size\begin{aligned}N&=\text{batch size}\\L&=\text{sequence length}\\ D&=2\text{ if biirectional=True otherwise}1\\ H_{in}&=\text{input-size}\\ H_{det}&=\text{hide}\\ H_{det}&=\text{pair-size}\\ H_{det}&=\text{pair-size if proj-size}>0\text{otherwise hidden-size}\\ \end{aligned}NLDHinHdetHdetHdet=batchsize=sequencelength=2ifbiirectional=Trueotherwise1=input-size=hide=pair-size=pair-sizeifproj-size>0otherwisehidden-size
输出:
- output-当batch_first=False时:(L,N,D∗Hout)(L,N,D*H_{out})(L,N,D∗Hout),batch_first=Ture时:(N,L,D∗Hout)(N,L,D*H_{out})(N,L,D∗Hout)。
- h_n-(D∗numlayers,N,Hout)(D*\operatorname{num} \operatorname{layers},N,H_{out})(D∗numlayers,N,Hout)
- c_n-(D∗numlayers,N,Hcell)(D*\operatorname{num}\operatorname{layers},N,H_{cell})(D∗numlayers,N,Hcell)
变量:
图解:
6.LSTM模型代码(Pytorch)
参考资料:
[1.](一文搞懂RNN(循环神经网络)根底篇 – 知乎 (zhihu.com))
[2.](Why LSTMs Stop Your Gradients From Vanishing: A View from the Backwards Pass (weberna.github.io))
[3.](LSTM — PyTorch 2.0 documentation)
[4.]((28条音讯) PyTorch笔记 – LSTM(Long Short Term Memory) 和 LSTMP(Projection) 网络结构_pytorch lstm many2many_SpikeKing的博客-CSDN博客)