如何理解Keras中的TimeDistributed层并在LSTM中使用

    老规矩,主要框架译自How to Use the TimeDistributed Layer for Long Short-Term Memory Networks in Python~,中间加了一点点自己的理解。


    长短时记忆网络(LSTMs)是一种流行且功能强大的循环神经网络(RNN)。它们很难配置和应用于任意序列预测问题,即使使用定义良好且“易于使用”的接口(如Python中的Keras深度学习库中提供的接口)也是如此。Keras中出现这种困难的一个原因是使用了TimeDistributed包装器层,并且需要一些LSTM层返回序列而不是单个值。

    在本教程中,您将发现为序列预测配置LSTM网络的不同方法、TimeDistributed层所扮演的角色以及如何正确使用它。

    完成本教程后,您将知道:

  •     如何设计一个用于序列预测的一对一LSTM。
  •     如何在没有TimeDistributed层的情况下设计多对一LSTM进行序列预测。
  •     如何利用TimeDistributed层设计多对多LSTM进行序列预测。

    让我们开始吧。

教程概述

    本教程分为五个部分;它们是:

  1. TimeDistributed层
  2. 序列学习问题
  3. 用于序列预测的一对一LSTM
  4. 用于序列预测的多对一LSTM(没有TimeDistributed)
  5. 用于序列预测的多对多LSTM (TimeDistributed)

TimeDistributed层

    LSTMs功能强大,但是很难使用和配置,尤其是对于初学者。附加的复杂性是TimeDistributed层(和前TimedistributedDense层),它被神秘地描述为一个层包装器:

    这个包装器允许我们对输入的每个时间片应用一个层。

     您应该如何以及何时在LSTMs中使用这个包装器?

    当您搜索关于Keras GitHub问题和StackOverflow上的包装器层的讨论时,这种混淆就更加复杂了。

    例如,在“When and How to use TimeDistributedDense”一文中,fchollet (Keras的作者)解释道:

    TimeDistributedDese对三维张量的每个时间步长应用相同的Dense(全连接)操作。

    如果您已经了解TimeDistributed层的用途以及何时使用它,那么这是非常有意义的,但是对初学者毫无帮助。

    本教程的目的是通过一些工作示例来澄清使用带有LSTMs的TimeDistributed包装器的困惑,您可以查看、运行和使用这些示例来帮助您具体理解。

序列学习问题

    我们将使用一个简单的序列学习问题来演示TimeDistributed层。

    在这个问题中,序列[0.0,0.2,0.4,0.6,0.8]一次作为一个输入,然后必须作为输出返回,一次作为一个项。把它看作是学习一个简单的回声程序。我们给出0.0作为输入,我们希望看到0.0作为输出,对序列中的每一项重复执行。我们可以直接生成这个序列如下:

from numpy import array
length = 5
seq = array([i/float(length) for i in range(length)])
print(seq)

     运行此示例将打印生成的序列:

    该示例是可配置的,如果您愿意,稍后还可以自己处理较长/较短的序列。请在评论中告诉我你的结果。

用于序列预测的一对一LSTM

    在我们深入研究之前,重要的是证明这个序列学习问题可以分段学习。也就是说,我们可以将问题重新构造为序列中每个项的输入-输出对的数据集。给定0,网络应该输出0,给定0.2,网络必须输出0.2,以此类推。

    这是该问题最简单的公式,它要求将序列分解为输入-输出对,并对序列进行一次一步预测,然后在网络外部收集序列。输入-输出对如下:

    LSTMs的输入必须是三维的(三维的结构是[样本批大小,滑窗大小,特征数量],详细介绍可以参考博客lstm数据格式与老鼠屎的旧博文Keras实战:基于LSTM的股价预测方法)。

可以使用Keras的Attention来在LSTM加入注意力机制,具体实现可以参考以下代码: ```python from keras.layers import Input, LSTM, Dense, Dropout, TimeDistributed, Bidirectional, Concatenate, Dot, Activation from keras.layers import RepeatVector, Embedding, Flatten, Lambda, Permute, Multiply from keras.models import Model from keras.activations import softmax import keras.backend as K # 定义注意力机制的函数 def attention(a, b): a_reshape = Permute((2, 1))(a) score = Dot(axes=[2, 1])([b, a_reshape]) alignment = Activation('softmax')(score) context = Dot(axes=[2, 1])([alignment, a]) return context # 定义输入和输出的形状和维度 input_shape = (None,) output_shape = (None,) # 定义输入和嵌入 input_layer = Input(shape=input_shape) embedding_layer = Embedding(input_dim=vocab_size, output_dim=embedding_dim)(input_layer) # 定义双向LSTM lstm_layer = Bidirectional(LSTM(units=lstm_units, return_sequences=True))(embedding_layer) # 定义注意力 attention_layer = attention(lstm_layer, lstm_layer) # 将LSTM和注意力连接起来 concat_layer = Concatenate(axis=2)([lstm_layer, attention_layer]) # 定义全连接输出 dense_layer = TimeDistributed(Dense(units=dense_units, activation='relu'))(concat_layer) output_layer = TimeDistributed(Dense(units=output_vocab_size, activation='softmax'))(dense_layer) # 构建模型 model = Model(inputs=[input_layer], outputs=[output_layer]) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) ``` 注意,上述代码的函数`attention`就是实现注意力机制的关键。在模型,我们先将输入通过嵌入映射成词向量,然后经过双向LSTM,得到前向和后向的隐状态。接着,我们将这两个隐状态作为注意力机制的输入,计算得到注意力权重,然后根据这个权重计算出每个词对应的上下文向量。最后,我们将原始的LSTM输出和上下文向量拼接起来,再通过全连接输出进行预测。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值