作者:Tobin
日期:2019/04/12
缘起:最近在做时间序列分析的实验,FCN网络做时序数据分类的效果还可以,由于时间的依赖性,自然地想到是否可以利用LSTM网络进行时序数据的分类。我对CNN比较了解,但是对LSTM,感觉很多文章都介绍得太笼统,大部分都是介绍cell,而忽略了它和CNN的联系。

LSTM叫长短期记忆网络(Long short term memory),是RNN循环神经网络(Recurrent Neural Network)的一个变形。我们先讲讲RNN。

RNN

每个绿色的部分叫做cell,看起来它们好像是不同的cell,但实际上它们只是同一个cell在不同时刻的样子!中间的这个cell清晰地画出了数据经过它到底进行了怎样的操作~输入是上一次cell输出的状态值和此时刻的输入,组合后,乘以权重和偏置,经过一次tanh就得到了这个cell的输出。

普通的RNN对于处理短的序列数据还行,当数据很长时,就会出现梯度消失和梯度爆炸的问题。所以又提出了改进版RNN,LSTM。

LSTM

LSTM多了什么呢?
看下面的图,很复杂对嘛,我们细细讲解。LSTM多了一个表示cell记忆的值。也就是我们不仅要更新当前cell的输出,我们还要思考,哪些东西可以记在我们的cell里呢,记忆的话,记多少又如何确定呢?既然有了记忆,那么我们的输入不仅仅有上一时刻的输出,此刻的输入,还有cell本身存储的那部分信息。所以LSTM的构造看起来很复杂,其实是围绕着记忆做操作的。

下图的C就表示记忆。

为了实现我们引入的记忆的思想,构造了三个门,遗忘门,输入门,输出门。

遗忘门

遗忘门能决定应丢弃或保留哪些信息。来自先前隐藏状态的信息和当前输入的信息同时输入到Sigmoid函数,输出值处于0和1之间,越接近0意味着越应该忘记,越接近1意味着越应该保留。这个f就可以用来操控遗忘哪些数据。

输入门

f是forget的意思,i是input的意思。
输入门用来更新单元状态。先将先前隐藏状态的信息和当前输入的信息输入到Sigmoid函数,在0和1之间调整输出值来决定更新哪些信息,0表示不重要,1表示重要。也可将隐藏状态和当前输入传输给Tanh函数,并在-1和1之间压缩数值以调节网络,然后把Tanh输出和Sigmoid输出相乘,Sigmoid输出将决定在Tanh输出中哪些信息是重要的且需要进行保留。

下面这张图显示了,两个门是如何控制遗忘和记忆的。

输出门

我们确定了当前的状态,那么当前状态的多少可以进行输出呢?控制Ct输出的门叫输出门,用Ot表示。
输出门能决定下个隐藏状态的值,隐藏状态中包含了先前输入的相关信息。当然,隐藏状态也可用于预测。首先把先前的隐藏状态和当前输入传递给Sigmoid函数;接着把新得到的单元状态传递给Tanh函数;然后把Tanh输出和Sigmoid输出相乘,以确定隐藏状态应携带的信息;最后把隐藏状态作为当前单元输出,把新的单元状态和新的隐藏状态传输给下个时间步。

代码实现

def LSTMCELL(prev_ct, prev_ht, input)
    combine = prev_ht + input
    ft = forget_layer(combine)
    it = input_layer(combine)
    ot = ouput_layer(combine)
    candidate = candidate_layer(combine)
    Ct = prev_ct*ft+candidate*it
    ht = ot*tanh(Ct)
    return ht, Ct
    
ct = [0, 0, 0]
ht = [0, 0, 0]

for input in inputs:
    ct, ht = LSTMCELL(ct, ht, input)

ht和xt结合后(拼接),构造出三个门控单元。再进行此cell在t时刻状态Ct的更新,利用Ct输出ht。inputs是一个输入的时间序列,可以看出,LSTM在不同时刻输入,只是在不断地循环输入而已。整个代码由几个张量操作和一个for循环组成,循环神经网络名字的来源一看便知哈。

多层LSTM

多层LSTM只是将单个cell进行堆叠。LSTM比为啥比CNN难理解呢?因为它把神经元的个数都藏到cell里面啦。假设大家都了解过CNN,看下面的图是不是有点感觉呢?我来解释一下,一个cell其实就是一层神经元,只是LSTM和CNN不同的是,它的每一层t时刻的输出和t-1时刻的状态有关。也就是说当前cell的输出ht不仅仅影响到下一cell(图中右边的那列),还影响本cell下一时刻的状态和输出(图中按时间顺序堆叠的三个绿色的cell)。
理解到这一点了,我们也自然地理解到,xt可以是多维的。然后每个cell的hidden_size都可以进行设置。

多层LSTM的代码

代码暂时没写,未完待续~
参考资料:
https://zhuanlan.zhihu.com/p/46981722
https://blog.csdn.net/gzj_1101/article/details/79376798

版权声明:本文为zuotongbin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zuotongbin/p/10698843.html