深入理解Keras LSTM的stateful | 沐雨浥尘

深入理解Keras LSTM的stateful

Keras LSTM的stateful非常容易用错,前段时间研究了一下,记记笔记~
如有错误,欢迎评论指出~

结论先行

  • 绝大多数情况下,用stateless就行了

官方FAQ

最好的学习资料永远是官方文档

使RNN具有状态意味着每批样品的状态将被重新用作下一批样品的初始状态。
当使用有状态 RNN 时,假定:

  • 所有的批次都有相同数量的样本
  • 如果x1x2是连续批次的样本,则x2[i]x1[i]的后续序列,对于每个i

要在 RNN 中使用状态,你需要:

  • 通过将batch_size参数传递给模型的第一层来显式指定你正在使用的批大小。例如,对于10个时间步长的32样本的batch,每个时间步长具有16个特征,batch_size = 32
  • 在RNN层中设置stateful = True
  • 在调用fit()时指定shuffle = False

有点绕,我给翻译翻译

  • 假设Timestep=5,batch_size=2
  • X1X2就是连续的两个批次,X2[i]是X1[i]的后续序列,也就是说,床前明月光后面是疑是地上霜
  • 的状态会传递到作为初始状态,也就是用输出的(h, c)来初始化(h, c)
  • 那就不难理解为什么“所有的批次都有相同数量的样本”,如果不同批次的样本数不同,那上一批次传过来的(h, c)将没人接手
  • 进而,Keras文档说用stateful需要指定batch_size也没毛病,不指定的话,Keras默认容忍最后一个批次样本数不同。例如,samples=9,batch_szie=2,那么默认分成5批,最后一批只有1个样本

下一个问题,shuffle

  • shuffle = True会在每个epoch开始之前打乱训练集数据顺序,使用stateful LSTM肯定要设置shuffle = False,不然可能传给不就乱套了

官方examples

还是那句话,最好的学习资料在官方,墙裂建议好好跑跑这份代码,以下只是我的笔记~

参数说明

  • input_len序列长度
  • tsteps移动平均的步长
    e.g. if tsteps=2 and input=[1, 2, 3, 4, 5], then output=[1.5, 2.5, 3.5, 4.5]
  • lahead理解成模型的timestep就行了

结论

  • When lahead < tsteps, only the stateful LSTM converges
  • When lahead >= tsteps, both the stateful and stateless LSTM converge

我再来翻译翻译

  • 任务的实质就是,用lahead个前序数据去预测步长为tsteps的平均值
  • 如果lahead=3, tsteps=2, lahead >= tsteps,预测值仅与当前时刻和上一时刻的输入有关,而我们拿三个时刻的数据建模,肯定收敛
  • 如果lahead=1, tsteps=2, lahead < tsteps,预测值仅与当前时刻和上一时刻的输入有关,而我们只拿了当前时刻数据建模,使用stateless肯定不能收敛,而使用stateful,由于能考虑上一时刻的输入,故收敛

实际效果

代码&结果

(tsteps, lahead, batch_size) Stateful RMSE Stateless RMSE
2, 1, 1 0.014813 0.031049
2, 2, 1 0.011407 0.000185
2, 2, 2 0.010075 0.000017
2, 1, 2 0.028951 0.029062
  1. tsteps=2, lahead=1, batch_size=1,理论上stateful能收敛,stateless不能收敛,RMSE(stateful) < RMSE(stateless)没问题
  2. tsteps=2, lahead=2, batch_size=1,理论上都能收敛,stateless效果很好
  3. tsteps=2, lahead=2, batch_size=2,在上次实验的基础上,batch_size调整为2,stateful似乎好了一点点
  4. tsteps=2, lahead=1, batch_size=2,与实验1对照,stateful似乎变差了很多,为什么呢?因为lahead不等于batch_size时,LSTM状态没有传递

本例中,需要保证lahead = batch_size,才能保证stateful正确传递状态,为什么呢?请看图~

明白了吧~

非官方FAQ

  • LSTM学习哪段序列的关系?
    Timestep内的序列关系
  • Jason的博文Understanding Stateful LSTM Recurrent Neural Networks in Python with Keras为什么说如果所有sample一个batch,则LSTM能很好地考虑上下文信息
    仔细看他代码,偷偷把epoch调成5000了,效果当然好(被坑过)…而且他的例子太简单了,timestep=1,还算个锤子LSTM
  • 关于Tensorflow中BATCH_SIZE,CELL_SIZE的讨论为什么说“BATCH_SIZE * TIME_STEPS 必须等于数据长度”
    个人觉得有误,只有在使用stateful时,才需要对batch_size严格指定,最好的例子就是官方examples(如果是我理解错,请指出)
  • stateful LSTM为什么要指定batch_size?
    保证每个batch的样本数相同
  • stateful LSTM训练完一个epoch为什么要手动重置网络?
    如果不重置,就会将上个epoch最后一个batch的状态传递给下个epoch的第一个batch,这明显不是我们乐意见到的
  • 需要stateful么?
    绝大多数情况下,用stateless就行了

参考目录

Buy me a cup of coffee