lstm整理

一开始觉得做了RNN之后做LSTM应该会很快,严格来说确实比RNN快,但是LSTM的训练参数比较多,因此不得不把几乎所有的矩阵计算都专门提取出来,否则程序可读性就太差了。按照RNN的经验,其实如果是简单序列,模型的容错性是比较高的,但过程中发现lstm的容错性更高,主要原因就是遗忘门的引入。

另外之前在RNN的时候看到有人说做clip会对结果有很好的提升,实际发现如果用了clip以后,loss下降相对是比较稳定的,如果不用clip,loss下降会有较大的波动,这也和论文所说的一致。

另外实际中发现lstm的两个隐藏状态c和h在长时间训练后会有巨大的变化,这里只举一个例子:




实际训练中还发现h中某个维度会变得非常小(10^-15以下),这些都意味着h和c不太稳定。如果对h和c做归一化,如果在BP之前归一化:




如果在BP之后归一化:




可以看出在BP之前归一化会导致h和c的一些维度消失,因为h和c的值在bp中计算梯度是用到了的。在BP之后如果对H和C进行归一化效果似乎不错,至少看起来比不做归一化要强一些。这同时也意味着如果你让状态在一个0-∞的空间里随便跑其实是很危险的。

这同时说明我们是否一开始就应该尝试在球面空间建造坐标系?这样一来带来的另外一个好处——数据的精度——能够被转化为空间本身的特征被带入计算中。

另外GRU等模型一般称为对LSTM的简化,模型如下:




其最大的改动是去掉了一个状态c,在lstm中c状态用于衔接 h[t-1] 和 h[t] 两个状态,其本质是通过两次tanh激活来隔离梯度,具体差别还有:
1、f和i两个开关矩阵变为一个z,这样做能一定程度上减轻c值理论上的快速变化,替代方案还有直接加起来再进行任何一种压缩。
2、r 直接作用于 h[t-1] 上,这样一步操作使得原本少了一组的参数立马又补上了,这是实际对上一次结果的开关,两次 tanh 少了的一次就在这里。
3、o 是相当于直接删掉了,因为没有c,o也就没用了。

本来需要训练4组参数,现在只需要训练3组,虽然删了c,但是对c所起的状态缓冲的目标由非线性tanh改为了线性。实际上上面的123最后看下来也都是为这个目标服务的。

在简单rnn的时候,我们对于序列的处理是“过往的复杂模式”,lstm下我们对于序列的处理是“更长时间段的复杂模式”。如果有明确的训练数据,那么极端情况下这样的模型可以把整个训练数据的特征都学习完毕,但问题在于这也仅仅是在语法层面实现了语言的学习,并没有深入到知识层面。序列模型能在信息层面降低熵值,但是它天然缺乏知识的复用性。但也能见到很多将知识纳入深度模型的,原理多少有一些猜测,但还是一步步看过去。

后面我将进行seq2seq的实现。