陈子豪作者 墨迹天气TechInfo来源

基于长短期记忆网络的短时雷达外推算法

本文由机器之心经授权转载自墨迹天气TechInfo(ID:moji_techinfo),未经授权禁止二次转载。

本文主要介绍的是利用现有的pytorch框架,实现ConvLSTM和ConvGRU内核,并实现一个多层RNN的封装结构层,方便使用者快速的堆叠多层的RNNCell。得益于pytorch的便利,我们只需要按照公式写出forward的过程,后续的backward将由框架本身给我们完成。同时,作者还基于这些网络结构,搭建了一个简单的图像时序预测模型,方便读者理解每一结构之间的作用和联系。

首先是ConvLSTM,其单元结构如下图所示:

在公式中可以明显看出i,f,g,o,中的计算过程大多一致,因此我们利用一个卷积层,多个卷积核的方式来完成计算。对于每个门内部的计算我们也进行合并。如下图所示:

拼接输入数据X,h:

combined =torch.cat((input, hidden), 1)

计算每一个门的输出:


A = self.conv(combined)
(ai, af,ao, ag)= torch.split(A, self.num_features, dim=1)  # it should return 4 tensors

      这样,我们就完成了LSTM中所有门的计算,在利用pytorch的支持下,我们只使用三行代码就完成了基础的门运算操作。

然后我们参照原始公式,给每个门的输出数据加上激活函数和dropout层:

i =torch.sigmoid(ai)
i = self.dropout(i)
f = torch.sigmoid(af)
f = self.dropout(f)
o = torch.sigmoid(ao)
o = self.dropout(o)
g = torch.tanh(ag)
g = self.dropout(g)

    得到f,g,i,o之后可以继续计算Ct,Ht:

next_c = f * c+ i * g
next_h = o * torch.tanh(next_c)
next_h = self.dropout(next_h)

     得到Ct,Ht之后整个LSTM单元的计算过程变结束了,LSTM的主要创新之处在于存储单元Ct,Ct在整个神经元中充当了状态信息的累加器,神经元通过各种参数化学习而来的控制门对信息进行保存和削减。

     为了配合后面的多层RNN封装结构,我们将神经元的输出封装为如下格式:

return next_h, (next_h,next_c)

     至此,一个完整的LSTM单元计算过程就实现完成了。

     GRU单元的实现过程和LSTM类似,这里只给出计算公式和对应的代码实现:

def forward(self, input, hidden):
    c1 = self.ConvGates(torch.cat((input, hidden), 1))
    (rt, ut)= c1.chunk(2, 1)
    reset_gate = self.dropout(f.sigmoid(rt))
    update_gate = self.dropout(f.sigmoid(ut))
    gated_hidden = torch.mul(reset_gate, hidden)
    p1 = self.Conv_ct(torch.cat((input, gated_hidden), 1))
    ct = f.tanh(p1)
    next_h = torch.mul(update_gate, hidden)+ (1 - update_gate) * ct
    return next_h

    ConvGRUCell的具体定义过程可以查考文末的GitHub源码地址。

    接下来我们继续承接上面的输入,实现一个多层RNN的封装结构层

     其单元示意图如下所示:

MultiRNNCell层中封装了两个RNN单元Cell1和Cell2,数据x1首先传送给Cell1,Cell1有其初始化的状态信息h1(本文的LSTM结构状态信息有两个,分别为h&c,下文中不再赘述),经过Cell1神经元的处理,得到新的状态信息h1,并传给下一个单元Cell2,经过处理得到新的h2。两个cell的状态信息将会被保留,在序列中的下一个时次数据x2到来之后,继续参与计算。

forward的处理过程如下:

def forward(self, input, hidden_state):
    cur_inp = input
    new_states = []

      new_states用来保存每个cell计算得来的新状态信息,hidden_state保存的是上一时次的状态信息,t为0时,hidden_state为初始化的状态信息。

for i,cell in enumerate(self._cells):
    cur_state = hidden_state[i]

    cur_inp, new_state= cell(cur_inp, cur_state)

    new_states.append(new_state)

      MultiRNNCell对象的self._cells中保存了多层封装结构中的所有Cell,具体初始化方式和类成员可以在文末的github源码地址中找到。计算过程中我们取每个cell对应的状态信息h,和输入数据x,当前Cell计算后,下一个Cell的输入x使用上一个单元的输出h。 

      在源码中我提供了一个简单的图像时序预测模型,在这里简单讲解一下它的数据流:

def forward(self, data):
    new_state = self.stacked_lstm.init_hidden(data.size()[1])
     data的shape为(num_seqs,batch_size,channels_img,size_H,size_W)

new_state为初始化的状态信息

self.stacked_lstm是多层RNN封装单元,其内部提供了一个初始化参数的方法。

x_unwrap = []
for i inxrange(self.input_num_seqs + self.output_num_seqs):
    # print i
    if i< self.input_num_seqs:
        y_1, new_state= self.stacked_lstm(data[i], new_state)
    else:
        y_1, new_state= self.stacked_lstm(x_1, new_state)
    # print y_1.size()
    x_1 = self.deconv1(y_1)
    # print x_1.size()
    if i>= self.input_num_seqs:
        x_unwrap.append(x_1)

return x_unwrap

      input_num_seqs是模型的序列输入长度,output_num_seqs是模型的序列输出长度,在输入的过程中每个多层RNN结构体的输入是我们的data,在输出过程中每个多层RNN结构体的输入是我们前一个时次的输出。

在后续的loss计算过程中,我们计算的是实际的输出序列和我们预测出的x_unwarp序列之间的误差。其数据流如下图所示:

至此,整个基于pytorch实现的ConvLSTM和ConvGRU内核,多层封装结构层,时序预测网络已经完成了,受限于作者本身的水平,如有不妥之处可以在下方留言提出。

本文中涉及的网络结构代码地址为:https://github.com/chencodeX/RNN_Pytorch

在源码中还有一些基于上述结构实现的编码预测网络(encoder-forecaster),加权均方误差等,在本文中不再赘述,也欢迎大家fork。

本文作者简介:

陈子豪

墨迹风云科技股份有限公司算法工程师,专注于气象与深度学习领域融合应用。

本文由机器之心经授权转载自墨迹天气TechInfo(ID:moji_techinfo)

原文链接:https://mp.weixin.qq.com/s/TeXtXc9snP05LqrjLHzJvg

工程PyTorch代码
2
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

激活函数技术

在 计算网络中, 一个节点的激活函数定义了该节点在给定的输入或输入的集合下的输出。标准的计算机芯片电路可以看作是根据输入得到"开"(1)或"关"(0)输出的数字网络激活函数。这与神经网络中的线性感知机的行为类似。 一种函数(例如 ReLU 或 S 型函数),用于对上一层的所有输入求加权和,然后生成一个输出值(通常为非线性值),并将其传递给下一层。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

神经元技术

(人工)神经元是一个类比于生物神经元的数学计算模型,是神经网络的基本组成单元。 对于生物神经网络,每个神经元与其他神经元相连,当它“兴奋”时会向相连的神经元发送化学物质,从而改变这些神经元的电位;神经元的“兴奋”由其电位决定,当它的电位超过一个“阈值”(threshold)便会被激活,亦即“兴奋”。 目前最常见的神经元模型是基于1943年 Warren McCulloch 和 Walter Pitts提出的“M-P 神经元模型”。 在这个模型中,神经元通过带权重的连接接处理来自n个其他神经元的输入信号,其总输入值将与神经元的阈值进行比较,最后通过“激活函数”(activation function)产生神经元的输出。

长短期记忆网络技术

长短期记忆(Long Short-Term Memory) 是具有长期记忆能力的一种时间递归神经网络(Recurrent Neural Network)。 其网络结构含有一个或多个具有可遗忘和记忆功能的单元组成。它在1997年被提出用于解决传统RNN(Recurrent Neural Network) 的随时间反向传播中权重消失的问题(vanishing gradient problem over backpropagation-through-time),重要组成部分包括Forget Gate, Input Gate, 和 Output Gate, 分别负责决定当前输入是否被采纳,是否被长期记忆以及决定在记忆中的输入是否在当前被输出。Gated Recurrent Unit 是 LSTM 众多版本中典型的一个。因为它具有记忆性的功能,LSTM经常被用在具有时间序列特性的数据和场景中。

堆叠技术

堆叠泛化是一种用于最小化一个或多个泛化器的泛化误差率的方法。它通过推导泛化器相对于所提供的学习集的偏差来发挥其作用。这个推导的过程包括:在第二层中将第一层的原始泛化器对部分学习集的猜测进行泛化,以及尝试对学习集的剩余部分进行猜测,并且输出正确的结果。当与多个泛化器一起使用时,堆叠泛化可以被看作是一个交叉验证的复杂版本,利用比交叉验证更为复杂的策略来组合各个泛化器。当与单个泛化器一起使用时,堆叠泛化是一种用于估计(然后纠正)泛化器的错误的方法,该泛化器已经在特定学习集上进行了训练并被询问了特定问题。

推荐文章
暂无评论
暂无评论~