Convolutional LSTM Network: A Machine Learning Approach for Precipitation Nowcasting

文章介绍了卷积LSTM(ConvLSTM)网络,它是FC-LSTM的扩展,旨在解决传统LSTM忽视空间相关性的问题。ConvLSTM在网络的输入到状态和状态到状态的转换中引入卷积结构,以捕捉空间信息,适用于如降水预报这类时空序列预测任务。代码示例展示了ConvLSTMCell的实现,用于处理输入的卷积操作和状态更新过程。
摘要由CSDN通过智能技术生成

卷积LSTM网络:降水临近预报的机器学习方法

Abstract

扩展全连接LSTM(FC-LSTM),使其再输入到状态和状态的转换中都具有卷积结构,我们提出了卷积LSTM(ConvLSTM)

Introduction

在这里插入图片描述
由于LSTM只考虑了时序,没有考虑空间之间的相关性,于是对LSTM再做变体,同时加入了窥探机制,每一个门的输入由三部分决定,即本层的输入,上一层的输出以及记忆线C上的信息,同时让原先输入的时间序列向量换成矩阵,以表示空间上的连接关系,矩阵相乘表示着全连接,所以这里叫做full-connection LSTM。
————————————————
版权声明:本文为CSDN博主「RegulusF」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44699689/article/details/115179825

在这里插入图片描述

在这里插入图片描述

如果是FC-LSTM就是说,我还要输入的是我的C
在这里插入图片描述
在这里插入图片描述

FC-LSTM层已经被证明是用于处理时间相关性的强大,但是它包含过多的空间数据冗余
FC-LSTM的一种扩展,

时空序列预测问题就是再给定之前J个观测值,包括当前观测值得情况下,预测未来最有可能得长度k序列

FC-LSTM在处理时空数据方面的主要缺点是它在输入到状态和状态到状态的转换中使用了完全连接,其中没有对空间信息进行编码。

gates it, ft, ot of the ConvLSTM are 3D tensors whose
last two dimensions are spatial dimensions (rows and columns).

时空序列预测问题不同于一步事件序列预测问题

降低维度,尽可能地简单

在这里插入图片描述

  self.Wxi = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whi = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxf = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whf = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxc = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whc = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxo = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Who = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)

        self.Wci = None
        self.Wcf = None
        self.Wco = None

在这里插入图片描述

    def forward(self, x, h, c):
        ci = torch.sigmoid(self.Wxi(x) + self.Whi(h) + c * self.Wci)
        cf = torch.sigmoid(self.Wxf(x) + self.Whf(h) + c * self.Wcf)
        cc = cf * c + ci * torch.tanh(self.Wxc(x) + self.Whc(h))
        co = torch.sigmoid(self.Wxo(x) + self.Who(h) + cc * self.Wco)
        ch = co * torch.tanh(cc)
        return ch, cc

代码

import torch
import torch.nn as nn
from torch.autograd import Variable


class ConvLSTMCell(nn.Module):
    # input_channel = 512 hidden_channel = 128 kernel_size = 3
    def __init__(self, input_channels, hidden_channels, kernel_size):
        super(ConvLSTMCell, self).__init__()

        assert hidden_channels % 2 == 0 # 判断,如果不能整除2就异常

        self.input_channels = input_channels
        self.hidden_channels = hidden_channels
        self.kernel_size = kernel_size
        self.num_features = 4
        # padding = 1
        self.padding = int((kernel_size - 1) / 2)
        # whf Conv2d(512, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.Wxi = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whi = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxf = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whf = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxc = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Whc = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)
        self.Wxo = nn.Conv2d(self.input_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=True)
        self.Who = nn.Conv2d(self.hidden_channels, self.hidden_channels, self.kernel_size, 1, self.padding, bias=False)

        self.Wci = None
        self.Wcf = None
        self.Wco = None

    def forward(self, x, h, c):
        ci = torch.sigmoid(self.Wxi(x) + self.Whi(h) + c * self.Wci)
        cf = torch.sigmoid(self.Wxf(x) + self.Whf(h) + c * self.Wcf)
        cc = cf * c + ci * torch.tanh(self.Wxc(x) + self.Whc(h))
        co = torch.sigmoid(self.Wxo(x) + self.Who(h) + cc * self.Wco)
        ch = co * torch.tanh(cc)
        return ch, cc
    # 初始化隐藏层 shape为什么等于64,32
    def init_hidden(self, batch_size, hidden, shape):
        if self.Wci is None:
            self.Wci = nn.Parameter(torch.zeros(1, hidden, shape[0], shape[1]))
            self.Wcf = nn.Parameter(torch.zeros(1, hidden, shape[0], shape[1]))
            self.Wco = nn.Parameter(torch.zeros(1, hidden, shape[0], shape[1]))
        else:
            assert shape[0] == self.Wci.size()[2], 'Input Height Mismatched!'
            assert shape[1] == self.Wci.size()[3], 'Input Width Mismatched!'
        # 为什么返回的是两个维度呢?刚开hi进来的时候咋就是64,32
        return (Variable(torch.zeros(batch_size, hidden, shape[0], shape[1])),
                Variable(torch.zeros(batch_size, hidden, shape[0], shape[1])))


class ConvLSTM(nn.Module):
    # input_channels corresponds to the first input feature map
    # hidden state is a list of succeeding lstm layers.
    # kernel_size = 3, input_channels = 512, hidden_channel是一个数组,step=1 , effective_step=4,为什么就等于4了呢?传进来地
    def __init__(self, input_channels, hidden_channels, kernel_size, step=1, effective_step=[1]):
        super(ConvLSTM, self).__init__()
        self.input_channels = [input_channels] + hidden_channels # 就是在第一个前面加上了512,拼接了?
        self.hidden_channels = hidden_channels
        self.kernel_size = kernel_size
        self.num_layers = len(hidden_channels)# hidden_channels地长度
        self.step = step
        self.effective_step = effective_step
        self._all_layers = []
        for i in range(self.num_layers):
            name = 'cell{}'.format(i)
            cell = ConvLSTMCell(self.input_channels[i], self.hidden_channels[i], self.kernel_size)
            setattr(self, name, cell)# 返回name,如果不存在就是属性值celL
            self._all_layers.append(cell)

    def forward(self, input):
        internal_state = []
        outputs = []
        for step in range(self.step):
            x = input
            for i in range(self.num_layers):
                # all cells are initialized in the first step
                name = 'cell{}'.format(i)
                if step == 0:
                    bsize, _, height, width = x.size()
                    (h, c) = getattr(self, name).init_hidden(batch_size=bsize, hidden=self.hidden_channels[i],
                                                             shape=(height, width))
                    internal_state.append((h, c))

                # do forward
                (h, c) = internal_state[i]
                x, new_c = getattr(self, name)(x, h, c)
                internal_state[i] = (x, new_c)
            # only record effective steps
            if step in self.effective_step:
                outputs.append(x)

        return outputs, (x, new_c)


if __name__ == '__main__':
    # gradient check 输入宽度,隐藏宽度,卷积数量,步数5
    convlstm = ConvLSTM(input_channels=512, hidden_channels=[128, 64, 64, 32, 32], kernel_size=3, step=5,
                        effective_step=[4])
    loss_fn = torch.nn.MSELoss()

    input = Variable(torch.randn(1, 512, 64, 32))
    target = Variable(torch.randn(1, 32, 64, 32)).double()
    # output = turter 2
    output = convlstm(input)
    output = output[0][0].double()# 1,32 ,65,32
    res = torch.autograd.gradcheck(loss_fn, (output, target), eps=1e-6, raise_exception=True)
    print(res)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向上Claire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值