平时很少写总结性的文章,感觉还是需要阶段性总结一些可以串在一起的知识点,所以这次写了下。 因为我写的内容主要在时序、时空预测这个方向,所以主要还是把rnn,lstm,gru,convlstm,convgru以及ST-LSTM
最为原始的循环神经网络,本质就是全连接网络,只是为了考虑过去的信息,输出不仅取决于当前输入,还取决于之前的信息,也就是输出由之前的信息(也就是状态state)和此时的输入决定。
① RNN 很适合处理序列数据,因为考虑了之前的信息
② 可以和CNN一起使用得到更好的任务效果
① 梯度消失、梯度爆炸
② rnn较其他cnn和全连接要用更多的显存空间,更难训练
③ 如果采用tanh、relu为激活函数,没法处理太长的序列
为了解决梯度消失和爆炸以及更好的预测和分类序列数据等问题,rnn逐渐转变为lstm
实际应用中一般不采用单层的lstm,而是多层,在很多时序数据中双向的表现也很不错
因为LSTM的训练比较慢,而GRU在其上稍微修改,速度可以快很多,而精度基本不变,所以GRU也十分流行
可以参考
【Deep Learning】详细解读LSTM与GRU单元的各个公式和区别mp.weixin.qq.com
为了构建时空序列预测模型,同时掌握时间和空间信息,所以将LSTM中的全连接权重改为卷积。
shixingjian博士提出的ConvLSTM通过他的描述来说应该就是其中的W也就是每个权重都从普通的全连接权重改为了卷积。 所以应该从左到右转变,正常来说右处应该是不存在i,f以及o三个门只由X和Ht-1决定,而没有C。 即不存在以下的结构。
这里咱们再重新看下博士的紧接着nips2016年的文章中所提到的convGRU也是不存在C的,并且可以和gru公式一一对应。
这里我不知道是博士当时就是这么实现的并且效果很好,还是说有无C对三个门的影响对最终的实验结果没有太大的影响,还是说确实是写作失误,这里我不太好给出结论。这里可以断定的是轨迹GRU那篇文章中对于结构完全是从GRU转变为convGRU的这里绝对没问题。 我也因此查了几篇期刊和顶会。
之后我又调查了一些文章,很巧妙,顶会基本上都是没有c的形式,而期刊大多都有。 这里我做了另外一个调查,github上的实现,大多数都是从LSTM直接转变为的Convlstm的写法也就是不存在C影响三个门,因为我当时复现的时候也是先实现了LSTM,之后加以改为ConvLSTM所以说没太注意,我这回自己也做了下这个实验,没有加上的结构可以很好的作时空预测,反而加上c之后会出现梯度的问题,所以这里大家可以有一些自我的理解。
我个人还是推荐直接从LSTM转变为convLSTM的结构。
这里主要给出 ST-LSTM结构及公式。
这个模型的复现和编写我会在不久之后专门写一篇文章来讲,并且因为是这种直接stacking的结构会有一些训练的trick,比如Scheduled Sampling等。
循环神经网络,是非线性动态系统,将序列映射到序列,主要参数有五个:[Whv,Whh,Woh,bh,bo,h0]
,典型的结构图如下:
:输入层到隐含层的权重参数,Whh:隐含层到隐含层的权重参数,Woh:隐含层到输出层的权重参数,bh:隐含层的偏移量,bo输出层的偏移量,h0
给定一个损失函数 L(z,y)=∑Tt=1L(zt,yt)
RNN因为加入了时间序列,因此训练过程也是和之前的网络不一样,RNN的训练使用的是BPTT(Back Prropagation Through TIme),该方法是由Werbo等人在1990年提出来的。
上面的算法也就是求解梯度的过程,使用的也是经典的BP算法,并没有什么新鲜的。但是值得一提的是,在 t-1 时刻对 ht−1
的求导值,也需加上t时刻的求导中对ht−1
的求导值,因此BPTT也是一个链式的求导过程。
但是因为上面算法中的第10行,在训练t时刻的时候,出现了t-1的参数,因此对单个的求导就变成了对整个之前状态的求导之和。
也正是因为存在长依赖关系,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。
这篇文章很好的解释了为什么会产生梯度消失和为什么会梯度爆炸的问题,其实主要问题就是因为在BPTT算法中,以w为例,其求导过程的链太长,而太长的求导链在以tanh为激活函数(其求导值在0~1之间的BPTT中,连乘就会使得最终的求导为0,这就是梯度消失问题,也就是t时刻已经学习不到t-N时刻的参数了。当然,有很多方法去解决这个问题,如LSTMs便是专门应对这种问题的,还有一些方法,比如设计一个更好的初始参数以及更换激活函数(如换成ReLU激活函数)。
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380)) model.add(SimpleRNN(units=16)) model.add(Dense(uints=256, activation=relu)) ... model.summary() #output simple_rnn_1 (SimpleRNN) param # 784 dense_1 (Dense) param # 4352
其中:784=16+1616+1632( Whv
+ Whh + bh
)
假设我们试着去预测“I grew up in France... I speak fluent French”最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。
不幸的是,在这个间隔不断增大时,RNN会丧失学习到连接如此远的信息的能力。在理论上,RNN绝对可以处理"长期依赖"问题。人们可以仔细挑选参数来解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。Bengio, et al.等人对该问题进行了深入的研究,他们发现一些使训练 RNN 变得非常困难的根本原因。
然而,幸运的是,LSTM 并没有这个问题!
LSTM 由Hochreiter & Schmidhuber (1997)提出,并在近期被Alex Graves进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。
LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构。
LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于单一神经网络层,以一种非常特殊的方式进行交互。
LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。这个决定通过一个称为忘记门层完成。
下一步是确定什么样的新信息被存放在细胞状态中。
我们把旧状态与 ft
相乘,丢弃掉我们确定需要丢弃的信息。接着加上 it∗C~t
。这就是新的候选值,根据我们决定更新每个状态的程度进行变化。
最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。
我们到目前为止都还在介绍正常的 LSTM。但是不是所有的 LSTM 都长成一个样子的。实际上,几乎所有包含 LSTM 的论文都采用了微小的变体。
图中最上面的一条线的状态即 s(t) 代表了长时记忆,而下面的 h(t)则代表了工作记忆或短时记忆。
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380)) model.add(LSTM(32)) model.add(Dense(uints=256, activation=relu)) ... model.summary() #output lstm_1 (LSTM) param # 8320
其中:8320=(32+32)324+4*32( Wo
+ WC + Wi + Wf + bo + bC + bi + bf
)。
LSTM有很多变体,其中较大改动的是Gated Recurrent Unit (GRU),这是由 Cho, et al. (2014)提出。它将忘记门和输入门合成了一个单一的 更新门。同样还混合了细胞状态和隐藏状态,和其他一些改动。最终的模型比标准的 LSTM模型要简单。效果和LSTM差不多,但是参数少了1/3,不容易过拟合。
理解 LSTM 网络
来源: https://www.cnblogs.com/houkai/p/9706716.html