Convlstm时空预测(keras框架、实战)

本人博客:www.erickun.com

Convlstm新手实战

   毕设临近截止,故写一篇心得以供新手学习,理论在知乎上有很多介绍的不错的文章,这里强烈推荐微信公众号:AI蜗牛车,这位东南老哥写了时空预测系列文章,能够帮助了解时空领域模型的演变,同时也向他请教了一些训练技巧。

   我的本科毕设大概是这样的:先计算某个区域的风险,计算得到一段时间的风险矩阵,这里用的是自己的模型去计算的,数据如何生成,本文不做赘述,主要讲解如果通过每个时刻下的矩阵数据去预测未来的矩阵。

回顾理论基础

   在ConvLSTM中,网络用于捕获数据集中的时空依赖性。ConvLSTM和FC-LSTM之间的区别在于,ConvLSTM将LSTM的前馈方法从Hadamard乘积变为卷积,即input-to-gate和gate-to-gate两个方向的运算均做卷积,也就是之前W和h点乘改为卷积(*)。 ConvLSTM的主要公式如下所示:
i t = σ ( W x i ∗ x t + W h i ∗ h t − 1 + b i ) f t = σ ( W x f ∗ x t + W h f ∗ h t − 1 + b f ) o t = σ ( W x o ∗ x t + W h o ∗ h t − 1 + b o ) C t = f t ∘ C t − 1 + i t ∘ tanh ⁡ ( W x c ∗ x t + W h c ∗ h t − 1 + b c ) H t = o t ∘ tanh ⁡ ( c t ) \begin{array}{c} i_{t}=\sigma\left(W_{x i}^{*} x_{t}+W_{h i}^{*} h_{t-1}+b_{i}\right) \\ f_{t}=\sigma\left(W_{x f}^{*} x_{t}+W_{h f}^{*} h_{t-1}+b_{f}\right) \\ o_{t}=\sigma\left(W_{x o}^{*} x_{t}+W_{h o}^{*} h_{t-1}+b_{o}\right) \\ C_{t}=f_{t}^{\circ} C_{t-1}+i_{t}^{\circ} \tanh \left(W_{x c}^{*} x_{t}+W_{h c}^{*} h_{t-1}+b_{c}\right) \\ H_{t}=o_{t}^{\circ} \tanh \left(c_{t}\right) \end{array} it=σ(Wxixt+Whiht1+bi)ft=σ(Wxfxt+Whfht1+bf)ot=σ(Wxoxt+Whoht1+bo)Ct=ftCt1+ittanh(Wxcxt+Whcht1+bc)Ht=ottanh(ct)
详细可参考:【时空序列预测第二篇】Convolutional LSTM Network-paper reading

官方keras案例

   实战过的朋友应该了解,关于Convlstm,可参考的案例非常少,基本上就集中在keras的官方案例(电影帧预测——视频预测官方案例知乎解说
在这里插入图片描述
官方模型核心代码:

from keras.models import Sequential
from keras.layers.convolutional import Conv3D
from keras.layers.convolutional_recurrent import ConvLSTM2D
from keras.layers.normalization import BatchNormalization
import numpy as np
import pylab as plt
 
seq = Sequential()
seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   input_shape=(None, 40, 40, 1),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())

seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())

seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())

seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())

seq.add(Conv3D(filters=1, kernel_size=(3, 3, 3),
               activation='sigmoid',
               padding='same', data_format='channels_last'))
seq.compile(loss='binary_crossentropy', optimizer='adadelta')

   模型结构可以如官方一样:用前20个预测后20个,这里先解释一下官方模型结构的维度:

    (如已熟悉,请跳过)对于新手来说,看上去似乎很复杂,其实弄清楚后会发现不过如此,请耐心听我讲完:先从第一个Convlstm说起,输入的是(None, 40, 40, 1),输出的维度(None,None,40,40,40),这里的输入维度(input_shape)其实是每个时刻下的输入,如下图:比如这里用20个预测后20个,那么整理的第一个样本就是0至19个矩阵,label(标签)就是20至39个矩阵,每一个矩阵维度为(40,40,1)最后的这个1为通道数,如果是图片,那就对应多通道了,那么整理的样本X就应该是(样本个数,20,40,40,1),对应标签Y就是(样本个数,20,40,40,1)这样每个样本和标签才能一一对应,由于reurn_sequencetrue,即每个时刻单元都有输出,也就是20个预测20个嘛,那么第一层的Convlstm输出的维度就是(None,None,40,40,40)这里第一个None是batchsize毫无疑问,第二个其实就是20,至于最后一个维度是40,和filter个数直接相关,(因为一个卷积核对样本做一次特征提取,40个就有40个特征提取)。

   接下来N层Convlstm均如此,最后为啥要接一个Conv3d,很好解释,因为你的label维度是(样本个数,20,40,40,1),这里的最后维度还得回归到1啊,所以Conv3d的filter这才设置为了1,以此类推,如果你的一个数据是三通道的图像,这里filter自然就是3了,一定要和label维度对应即可。

ConvLSTM参数介绍

  • filters: 卷积核的数目
  • kernel_size: 卷积核大小(1乘1的state-to-state kernel size很难抓住时空移动的特征,所以效果差很多,所以更大的size更能够获取时空的联系)
  • strides: (1,1)为卷积的步长,即卷积核向右和向下一次移动几格,默认步长为1
  • padding: 补0,为“valid”或 “same”。若要保证卷积核提取特征后前后维度一致,那就“same”
  • data_format: 即红绿蓝三个通道(channel)是在前面还是在后面,channels_last (默认) (width, height, channel)或 channels_first (channel, width, height) 之一, 输入中维度的顺序
  • activation: 激活函数,即下图中的RELU层,为预定义的激活函数名,如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)

模型改造

   不过我由于数据量比较少,我把模型结构改造成了20个预测1个(样本数较少的童鞋可以参考),在convlstm最后一个层的reurn_sequence参数改为flase、Conv3d改2d即可。

   其实了解了reurn_sequence这个参数后,改造就顺理成章了,在最后一个Convlstm这里将reurn_sequence改为false,那么就只在最后一个单元有输出了,第二个None维度就没了,然后再把Conv3d改为2d即可,这样就要求整理数据集的时候,样本和标签分别整理成这样:(样本数,20,40,40,1) 和(样本数,40,40,1),也就是20个预测1个。

from keras.models import Sequential
from keras.layers.convolutional import Conv3D ,Conv2D
from keras.layers.convolutional_recurrent import ConvLSTM2D
from keras.layers.normalization import BatchNormalization
from keras_contrib.losses import DSSIMObjective

import numpy as np

seq = Sequential()
seq.add(ConvLSTM2D(filters=30, kernel_size=(3, 3),
                   input_shape=(None, 60, 93, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())
 
seq.add(ConvLSTM2D(filters=30, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
seq.add(BatchNormalization())
 
seq.add(ConvLSTM2D(filters=30, kernel_size=(3, 3),
                   padding='same', return_sequences=False))
seq.add(BatchNormalization())
 
seq.add(Conv2D(filters=3, kernel_size=(3, 3),
               activation='sigmoid',
               padding='same', data_format='channels_last'))

seq.compile(loss= DSSIMObjective(kernel_size=3), optimizer='adadelta')
seq.summary()

模型经验及调参

   先看看结果图吧,随便抽一张示意一下,预测的点相对比较准确,但是模糊度还没解决掉,毕竟只训练了十几分钟,有这个效果也还算可以了:

    整个模型看上去不算复杂,但是实际效果比较差,有以下几个要稍微注意的地方:

  • 1.矩阵数据是否过于稀疏,如果0太多,建议先转成图片再做训练,否则效果会奇差无比,原因可能是求梯度的时候网络出了问题,直接崩了。
  • 2.如果输入是图片张量,需要提前做好归一化,我用的简单处理,直接元素除255.0,显示的时候再乘回来即可,可能有一丢丢颜色误差,但是不太影响。
  • 3.预测图片出现模糊大概有以下几个原因:

    (1)网络结构不够优(继续调就完事了),往往这种情况下,得到的预测点也不会太准确。

    (2)由于是多个时刻下的数据去预测一个,那么必然存在信息叠加(融合),这样导致的模糊是不可避免的,如果数据量很大,那么可以采用20帧预测20帧这样的结构,应该会有效减缓一点模糊程度。

    (3)重要: 损失函数若使用MSE则会默认模糊,如果换成SSIM(结构相似性)则会明显改观(亲测有效)

       在模糊处理方面,我也想尝试改进,但是还没有找到比较好的方式,蜗牛车老哥建议调小学习率,训练时间长一点,可以这样去尝试一下!反卷积也尝试了,但是效果不佳,后期准备使用TrajGRU来实战(预测解码模块采用了上采样层理论上应该会提高清晰度)。

   模型调参的过程其实是最无聊也最艰辛的,无非就是改改层结构,多一层少一层,改一下filter、batchsize个数,时空预测这种图像的预测和别的领域有一点不同,文本的只要acc、f1-score上去了就行,所以可以用grid search来自动化调参,但是图像预测还必须得肉眼去看效果,否则结果真可能是千差万别,loss看上去已经很低了但是效果很差的情况比比皆是,尝试多换几种loss来实验,后面也还可以尝试自定义loss看效果,整个调参过程确实是不断试错的过程,两个字:“炼丹”!

------------------------下图为2020.6.1更新,本科毕设最新效果,采用trick--------如有需要详细,可私信-------------------

------------------图错误
发现图好像画错了,
在这里插入图片描述

用20个预测下一个,应该是这样画图才对吧

  • 43
    点赞
  • 215
    收藏
    觉得还不错? 一键收藏
  • 50
    评论
Keras是一个非常流行的深度学习框架,用于实现和训练各种神经网络模型。Keras的设计旨在使深度学习变得更加简单、高效和可扩展。 在进行Keras项目实战时,首先我们需要确定一个具体的问题或任务,例如图像分类、文本生成或语音识别等。然后,我们可以按照以下步骤进行项目实施: 1. 数据准备:收集和整理与问题相关的数据集。数据集的质量和多样性对于训练模型的性能非常重要。然后,我们可以将数据集分为训练集、验证集和测试集。 2. 构建模型:使用Keras的API构建模型架构。Keras提供了一系列的层(layers),如卷积层、循环层和全连接层等,可以根据问题的需求选择合适的层来组合成模型。 3. 编译模型:为模型选择优化器(optimizer)和损失函数(loss function)。优化器用于更新模型的权重以最小化损失函数,定义了模型的训练方式。损失函数用于评估模型在给定数据上的性能。 4. 训练模型:使用训练集数据进行模型的训练。通过迭代训练集多次,模型的权重会不断地更新以最小化损失函数。 5. 评估模型:使用验证集数据评估模型在新数据上的性能。这可以帮助我们对模型的泛化能力有更全面的了解。 6. 调优模型:根据模型在验证集上的性能,调整模型的架构、超参数或优化器等,以提高模型的性能。 7. 测试模型:使用测试集数据来评估模型在未知数据上的性能。通过测试集的结果,我们可以对模型的整体表现进行合理的评估。 总结而言,Keras项目实战需要掌握深度学习的基本概念和算法,同时熟悉Keras框架及其API的使用。实际项目中,还需要对数据进行预处理和特征工程,以提高模型的性能。通过不断地实践和调优,我们可以构建出更加准确和高效的深度学习模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值