赞
踩
目录
前言:其实之前就已经用过 LSTM 了,是在深度学习框架 keras 上直接用的,但是到现在对LSTM详细的网络结构还是不了解,心里牵挂着难受呀!今天看了 tensorflow 文档上面推荐的这篇博文,看完这后,焕然大悟,对 LSTM 的结构理解基本上没有太大问题。此博文写得真真真好!!!为了帮助大家理解,也是怕日后自己对这些有遗忘的话可以迅速回想起来,所以打算对原文写个翻译。首先声明,由于本人水平有限,如有翻译不好或理解有误的多多指出!此外,本译文也不是和原文一字一句对应的,为了方便理解可能会做一些调整和修改。)
人们思考问题往往不是从零开始的。就好像你现在阅读这篇文章一样,你对每个词的理解都会依赖于你前面看到的一些词,而不是把你前面看的内容全部抛弃了,忘记了,再去理解这个单词。也就是说,人们的思维总是会有延续性的。
传统的神经网络是做不到这样的延续性(它们没办法保留对前文的理解),这似乎成了它们一个巨大的缺陷。举个例子,在观看影片中,你想办法去对每一帧画面上正在发生的事情做一个分类理解。目前还没有明确的办法利用传统的网络把对影片中前面发生的事件添加进来帮助理解后面的画面。
但是,循环神经网络可以做到。在RNNs的网络中,有一个循环的操作,使得它们能够保留之前学习到的内容。
Fig1. RNNs 网络结构
在上图网络结构中,对于矩形块 A 的那部分,通过输入$ x_t (t时刻的特征向量),它会输出一个结果(t时刻的特征向量),它会输出一个结果(t时刻的特征向量),它会输出一个结果 h_t $(t时刻的状态或者输出)。网络中的循环结构使得某个时刻的状态能够传到下一个时刻。(译者注:因为当前时刻的状态会作为下一时刻输入的一部分)
这些循环的结构让 RNNs 看起来有些难以理解。但是,你稍微想一下就会发现,这似乎和普通的神经网络有不少相似之处呀。我们可以把 RNNs 看成是一个普通的网络做了多次复制后叠加在一起组成的。每一网络会把它的输出传递到下一个网络中。我们可以把 RNNs 在时间步上进行展开,就得到下图这样:
fig2. RNNs 展开网络结构
从 RNNs 链状的结构很容易理解到它是和序列信息相关的。这种结构似乎生来就是为了解决序列相关问题的。
而且,它们的的确确非常管用!在最近的几年中,人们利用 RNNs 不可思议地解决了各种各样的问题:语音识别,语言模型,翻译,图像(添加)字幕,等等。关于RNNs在这些方面取得的惊人成功,我们可以看 Andrej Karpathy 的博客: The Unreasonable Effectiveness of Recurrent Neural Networks.
RNNs 能够取得这样的成功,主要还是 LSTMs 的使用。这是一种比较特殊的 RNNs,而且对于很多任务,它比普通的 RNNs 效果要好很多很多!基本上现在所使用的循环神经网络用的都是 LSTMs,这也正是本文后面所要解释的网络。
RNNs 的出现,主要是因为它们能够把以前的信息联系到现在,从而解决现在的问题。比如,利用前面的画面,能够帮助我们理解当前画面的内容。如果 RNNs 真的可以做到这个,那么它肯定是对我们的任务有帮助的。但是它真的可以 做到吗,恐怕还得看实际情况呀!
有时候,我们在处理当前任务的时候,只需要看一下比较近的一些信息。比如在一个语言模型中,我们要通过上文来预测一下个词可能会是什么,那么当我们看到“ the clouds are in the ?”时,不需要更多的信息,我们就能够自然而然的想到下一个词应该是“sky”。在这样的情况下,我们所要预测的内容和相关信息之间的间隔很小,这种情况下 RNNs 就能够利用过去的信息, 很容易的实现。
fig2. 短期依赖
但是,有些情况是需要更多的上下文信息。比如我们要预测“I grew up in France … (此处省略1万字)… I speak ?”这个预测的词应该是 Franch,但是我们是要通过很长很长之前提到的信息,才能做出这个正确的预测的呀,普通的 RNNs 很难做到这个。
随着预测信息和相关信息间的间隔增大, RNNs 很难去把它们关联起来了。
fig3. 长期依赖
从理论上来讲,通过选择合适的参数,RNNs 确实是可以把这种长时期的依赖关系(“long-term dependencies”) 联系起来,并解决这类问题的。但遗憾的是在实际中, RNNs 无法解决这个问题。 Hochreiter (1991) [German] 和 Bengio, et al. (1994) 曾经对这个问题进行过深入的研究,发现 RNNs 的确很难解决这个问题。
但是非常幸运,LSTMs 能够帮我们解决这个问题。
长短期记忆网络(Long Short Term Memory networks) - 通常叫做 “LSTMs” —— 是 RNN 中一个特殊的类型。由Hochreiter & Schmidhuber (1997)提出,广受欢迎,之后也得到了很多人们的改进调整。LSTMs 被广泛地用于解决各类问题,并都取得了非常棒的效果。
明确来说,设计 LSTMs 主要是为了避免前面提到的 长时期依赖 (long-term dependency )的问题。它们的本质就是能够记住很长时期内的信息,而且非常轻松就能做到。
所有循环神经网络结构都是由完全相同结构的(神经网络)模块进行复制而成的。在普通的RNNs 中,这个模块结构非常简单,比如仅是一个单一的 tanh 层。
fig4. 普通 RNNs 内部结构
LSTMs 也有类似的结构(译者注:唯一的区别就是中间部分)。但是它们不再只是用一个单一的 tanh 层,而是用了四个相互作用的层。
fig5. LSTM 内部结构
别担心,别让这个结构给吓着了,下面根据这个结构,我们把它解剖开,一步一步地来理解它(耐心看下去,你一定可以理解的)。现在,我们先来定义一下用到的符号:
fig6. 符号说明
在网络结构图中,每条线都传递着一个向量,从一个节点中输出,然后输入到另一个节点中。粉红色的圆圈表示逐点操作,比如向量相加;黄色的矩形框表示的是一个神经网络层(就是很多个神经节点);合并的线表示把两条线上所携带的向量进行合并(比如一个带 ht−1h_{t-1}ht−1,另一个带 xtx_txt , 那么合并后的输出就是$[h_{t-1}, x_t] $); 分开的线表示将线上传递的向量复制一份,传给两个地方。
LSTMs 最关键的地方在于 cell(整个绿色的框就是一个 cell) 的状态 和 结构图上面的那条横穿的水平线。
cell 状态的传输就像一条传送带,向量从整个 cell 中穿过,只是做了少量的线性操作。这种结构能够很轻松地实现信息从整个 cell 中穿过而不做改变。(译者注:这样我们就可以实现了长时期的记忆保留了)
fig7. 传送带结构
若只有上面的那条水平线是没办法实现添加或者删除信息的。而是通过一种叫做 门(gates) 的结构来实现的。
门 可以实现选择性地让信息通过,主要是通过一个 sigmoid 的神经层 和一个逐点相乘的操作来实现的。
sigmoid 层输出(是一个向量)的每个元素都是一个在 0 和 1 之间的实数,表示让对应信息通过的权重(或者占比)。比如, 0 表示“不让任何信息通过”, 1 表示“让所有信息通过”。
每个 LSTM 有三个这样的门结构,来实现保护和控制信息。(译者注:分别是 “forget gate layer”, 遗忘门; “input gate layer”,传入门; “output gate layer”, 输出门)
(好了,终于来到最激动的时刻了)
首先是 LSTM 要决定让那些信息继续通过这个 cell,这是通过一个叫做“forget gate layer ”的sigmoid 神经层来实现的。它的输入是$ h_{t-1} 和和和 x_t $,输出是一个数值都在 0,1 之间的向量(向量长度和 cell 的状态 $ C_{t-1} $ 一样),表示让 $C_{t-1} $ 的各部分信息通过的比重。 0 表示“不让任何信息通过”, 1 表示“让所有信息通过”。
回到我们上面提到的语言模型中,我们要根据所有的上文信息来预测下一个词。这种情况下,每个 cell 的状态中都应该包含了当前主语的性别信息(保留信息),这样接下来我们才能够正确地使用代词。但是当我们又开始描述一个新的主语时,就应该把上文中的主语性别给忘了才对(忘记信息)。
fig9. 遗忘门 (forget gates)
下一步是决定让多少新的信息加入到 cell 状态 中来。实现这个需要包括两个 步骤:首先,一个叫做“input gate layer ”的 sigmoid 层决定哪些信息需要更新;一个 tanh 层生成一个向量,也就是备选的用来更新的内容,Ct˜\tilde{C_t}Ct~ 。在下一步,我们把这两部分联合起来,对 cell 的状态进行一个更新。
fig10. 传入门 (input gates)
在我们的语言模型的例子中,我们想把新的主语性别信息添加到 cell 状态中,来替换掉老的状态信息。
有了上述的结构,我们就能够更新 cell 状态了, 即把$ C_{t-1} $更新为 $C_{t} $。 从结构图中应该能一目了然, 首先我们把旧的状态 $C_{t-1} 和和和 f_t 相乘,把一些不想保留的信息忘掉。然后加上相乘, 把一些不想保留的信息忘掉。然后加上相乘,把一些不想保留的信息忘掉。然后加上 i_t * \tilde{C_{t}} $。这部分信息就是我们要添加的新内容。
fig11. 更新 cell 状态
最后,我们需要来决定输出什么值了。这个输出主要是依赖于 cell 的状态$ C_t$,但是又不仅仅依赖于 $C_t ,而是需要经过一个过滤的处理。首先,我们还是使用一个sigmoid层来(计算出)决定,而是需要经过一个过滤的处理。首先,我们还是使用一个 sigmoid 层来(计算出)决定,而是需要经过一个过滤的处理。首先,我们还是使用一个sigmoid层来(计算出)决定 C_t 中的哪部分信息会被输出。接着,我们把中的哪部分信息会被输出。接着,我们把中的哪部分信息会被输出。接着,我们把 C_t $通过一个 tanh 层(把数值都归到 -1 和 1 之间),然后把 tanh 层的输出和 sigmoid 层计算出来的权重相乘,这样就得到了最后输出的结果。
在语言模型例子中,假设我们的模型刚刚接触了一个代词,接下来可能要输出一个动词,这个输出可能就和代词的信息相关了。比如说,这个动词应该采用单数形式还是复数的形式,那么我们就得把刚学到的和代词相关的信息都加入到 cell 状态中来,才能够进行正确的预测。
fig12. cell 输出
1.GRU简单介绍
GRU是LSTM网络的一种效果很好的变体,这是由 Cho, et al. (2014) 提出。它较LSTM网络的结构更加简单,而且效果也很好,因此也是当前非常流形的一种网络。GRU既然是LSTM的变体,因此也是可以解决RNN网络中的长依赖问题。
在LSTM中引入了三个门函数:输入门、遗忘门和输出门来控制输入值、记忆值和输出值。GRU作为LSTM的一种变体,将忘记门和输入门合成了一个单一的更新门,同样还混合了细胞状态和隐藏状态。在GRU模型中只有两个门:分别是更新门和重置门。具体结构如下图所示:
其中, rtr_trt 表示重置门,ztz_tzt 表示更新门。**重置门决定是否将之前的状态忘记。当 rtr_trt 趋于 0 的时候,前一个时刻的状态信息 ht−1h_{t-1}ht−1 会被忘掉,隐藏状态 ht˜\tilde{h_t}ht~ 会被重置为当前输入的信息。更新门决定是否要将隐藏状态更新为新的状态$ \tilde{h_t}$ (作用相当于合并了 LSTM 中的遗忘门和传入门)。
图中的zt和rt分别表示更新门和重置门。更新门用于控制前一时刻的状态信息被带入到当前状态中的程度,更新门的值越大说明前一时刻的状态信息带入越多。重置门控制前一状态有多少信息被写入到当前的候选集 h~th~t 上,重置门越小,前一状态的信息被写入的越少。
和 LSTM 比较一下:
2、GRU前向传播
根据上面的GRU的模型图,我们来看看网络的前向传播公式:
其中[]表示两个向量相连,*表示矩阵的乘积。
3、GRU的训练过程
从前向传播过程中的公式可以看出要学习的参数有Wr、Wz、Wh、Wo。其中前三个参数都是拼接的(因为后先的向量也是拼接的),所以在训练的过程中需要将他们分割出来:
输出层的输入:
输出层的输出:
在得到最终的输出后,就可以写出网络传递的损失,单个样本某时刻的损失为:
则单个样本的在所有时刻的损失为:
采用后向误差传播算法来学习网络,所以先得求损失函数对各参数的偏导(总共有7个):
其中各中间参数为:
在算出了对各参数的偏导之后,就可以更新参数,依次迭代知道损失收敛。
概括来说,LSTM和CRU都是通过各种门函数来将重要特征保留下来,这样就保证了在long-term传播的时候也不会丢失。此外GRU相对于LSTM少了一个门函数,因此在参数的数量上也是要少于LSTM的,所以整体上GRU的训练速度要快于LSTM的。不过对于两个网络的好坏还是得看具体的应用场景。
概括的来说,LSTM和GRU都能通过各种Gate将重要特征保留,保证其在long-term 传播的时候也不会被丢失。
可以看出,标准LSTM和GRU的差别并不大,但是都比tanh要明显好很多,所以在选择标准LSTM或者GRU的时候还要看具体的任务是什么。
使用LSTM的原因之一是解决RNN Deep Network的Gradient错误累积太多,以至于Gradient归零或者成为无穷大,所以无法继续进行优化的问题。GRU的构造更简单:比LSTM少一个gate,这样就少几个矩阵乘法。在训练数据很大的情况下GRU能节省很多时间。
样例:预测当前词。每个时刻的输入都是一个embedding向量,它的长度是输入层神经元的个数,与时间步的个数(即句子的长度)没有关系。
每个时刻的输出是一个概率分布向量,其中最大值的下标决定了输出哪个词。
RNN&LSTM实际应用:
1. Language ModelThe Unreasonable Effectiveness of Recurrent Neural Networks http://karpathy.github.io/2015/05/21/rnn-effectiveness/
2. Image Captioning[CVPR15]]Long-term Recurrent Convolutional Networks for Visual Recognition and DescriptionDeep Visual-Semantic Alignments for Generating Image Descriptions http://cs.stanford.edu/people/karpathy/deepimagesent/
3. Speech Recognition
4. Machine Translation[NIPS15]Sequence to Sequence Learning
with Neural Networks. http://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf
7.
以如下网络结构为例:
import keras
keras.utils.layer_utils.print_summary(model)
模型概况如上,现在我们来看一下以上参数个数是如何计算的。
第一层:embedding_3:字典词汇30000*每一个词映射为100维度向量=300000
第二层:lstm_3:这一层的计算比较复杂。输出向量维度为256,总共有365568个参数。
时间步长为50,每一个词向量100维度,每一个门的输出向量均为256维度。
我们首先来看一下遗忘门,如图:
最后,我们看一下输出门:
X1,x2,x3,x4为全连接层的输入, y1,y2,y3为全连接层的输出b1,b2,b3为偏置向量。由 全连接层中数据的计算规则,我们可以得到:
y1=w11*x1+w12*x2+w13*x3+w14*x4+b1
Y2=w21*x1+w22*x2+w23*x3+w24*x4+b2
Y3=w31*x1+w32*x2+w33*x3+w34*x4+b3
我们可以得到该全连接层所需的权值矩阵为[3,4],偏执向量为[3], 有计算规则可知:权值矩阵为[输出向量维度,输入向量维度],偏置向量为[输出向量维度,1].
通过如上计算,我们可以得到,全连接层的参数计算公示为:输入向量维度n*输出向量维度m+输出层向量维度n。
结合全连接层的公式,对于dence_3层,输入维度为256,输出维度为64,可得
该层所需参数个数为256*64+64=16448.
同理可计算出最后一层的参数各位为64*6+6=390,与keras网络输出结果相同。
相关参考:
主要是参考了[译] 理解 LSTM 网络这篇文章
https://blog.csdn.net/Jerr__y/article/details/58598296
https://blog.csdn.net/lreaderl/article/details/78022724
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。