一般来说对于一些时空序列模型,都是普遍的三种结构。
当然结构可能有很多,我这里结合我之前写过的文章,总结下主要的三种。
普通的RNN堆叠,即stacking
ED结构即Encoding-Decoding
EF结构即Encoding-Forcasting
这个其实就是RNN的一种传统多层layer的形式
比如最基本的LSTM:
随着时间步(time step)的推移,输入数据(包括x和上一time step的hidden state),输出预测数据
当然这种结构一定要记住一点,就是说你看到的并非真正的结构,真正的结构只是下面的这个结构。
模型其实只是紫色框的部分,只是输出灰色的部分在随着时间的推移在变化,经过模型得到当时这个时刻的下一个时刻的预测数据,本质上RNN的模型参数是共享的,如果这点不能深刻的理解,那自己的复现肯定会出现问题。
比如predrnn论文中所给的结构就是典型的这种结构(只是有多出的橘黄色的折线,这个只是尤其cell所决定的)
可以看到是输入Xt得到预测的Xt+1
这种代码一般怎么来编写呢
答案是首先需要对单个的cell来编写代码,比如predrnn就是需要先对ST-LSTM来编写对应的cell代码,这种代码一般对着公式来写就好了,那stacking结构呢,那就是把cell嵌入进去,之后把对应的时间步(steps)和stacking层数(layer_num)比较简单的方式就是用两个循环写一下,并把每次的输出预测append到一个list中。
大概的代码如下。(你可以尝试着这么写下,其实就是把这种结构写成很多list以及for循环,之后通过循环index的变化不断的平移hidden state,最终输出所有的预测)
for t in range(input_length):
input_data = frames[:, t]
h_t[0], c_t[0], memory = self.cell_list[0](input_data, h_t[0], c_t[0], memory)
for i in range(1, self.num_layers):
h_t[i], c_t[i], memory = self.cell_list[i](h_t[i - 1], h_t[i], c_t[i], memory)
x_gen = self.conv_last(h_t[self.num_layers-1])
predict_frames.append(x_gen)
因为输出的prediction是下一步的,比如xt预测的是xt+1,那举个例子,比如input为10,output也为10,那其实模型最终预测的是19张,所以这里的loss是只算output predictions的loss,还是算all predictions的loss,这里值得思考
还是上面那个问题,在经过所有的输入之后得到了第一个我们需要的预测结果,之后我们要去预测第二个预测结果的时候,这个时候我们的输入其实是第一个预测结果,这个部分就像是seq2seq的decoding部分,这里面在预测部分没话讲基本上是这样操作,但是训练的时候呢,如果第一个预测结果很烂,直接会影响后面的九个预测数据的品质下降,那这时候就会出现一个问题错误爆炸,也就是算的loss是否会与之前的loss偏差很大,造成波动很大不利于训练的进行,那这个问题如何解决,可以采用一种训练trick,也是论文中常常提到的Scheduled Sampling
这种结果因为其中没有上下采样,所以一般来说比较占用训练资源,如果训练资源丰富那当我没说,但是不丰富,这里也可以通过patchsize的方式来降低显存的使用
这个结构其实就是seq2seq中提出的端到端结构,在时空序列中同样适用。
结构大概如下图所示
紫色部分为encoding,主要的目的是把前序的一段序列的信息提取出来得到一个尽量包含这段序列的信息state,之后传给decoding。
decoding这里的输出预测的方式和我上面在1.4阶段讲的差不多,也是同样最好有Scheduled Sampling训练方式。
这里的进化方式就很普遍了,其实就是应用到attention,这个操作讲的太多了,这里也不赘述了,看以下两个图直接明白attention的作用了,说白了就是为了解决信息过长导致的信息丢失的问题。加入attention之后当然这里的RNN的参数依然是共享的,只不过严格来说有两个RNN,一个encoderRNN,一个decoderRNN。
这里代码请具体参考seq2seq的代码,之后需要把里面cell部分改成时空的cell即可。
大致说一下思路。encoding尽量独立写,这回需要保存的是最后的一个step的所有layer的hidden states,如果使用attention的话,需要保存所有步的所有层的hidden states。之后将这个作为decoding的输入的一部分,decoding页独立写,之后不断地循环预测,最终把预测的结果全部append输出。
tf code:https://github.com/google/seq2seq
keras code:https://github.com/farizrahman4u/seq2seq
torch code:https://github.com/bentrevett/pytorch-seq2seq
这里的结构我个人觉得是对coding的一种变形,主要是施博士的工作。
这个结构我其实在直接解读论文的时候已经讲过了,具体可以见我之前的文章。
这里再稍微强调一下,EF和ED的区别主要在于三点。
EF引入上下采样结构
预测的方向也就是Forcaster结构中的数据流的方向倒置了(这里的原因可以翻看我之前的文章)
预测部分除了hiddenstate没有其他的输入了,即decoding的部分输入x为None
这里的代码可以参考:
https://github.com/Hzzone/Precipitation-Nowcasting
https://zhuanlan.zhihu.com/p/69295954
https://towardsdatascience.com/day-1-2-attention-seq2seq-models-65df3f49e263
https://www.guru99.com/seq2seq-model.html
更多精彩内容(请点击图片进行阅读)
公众号:AI蜗牛车
保持谦逊、保持自律、保持进步
个人微信
备注:昵称+学校/公司+方向
如果没有备注不拉群!
拉你进AI蜗牛车交流群
点个在看,么么哒!