在Keras中,如何获取LSTM层的3D输入和3D输出

时间:2019-05-22 11:17:23

标签: python keras neural-network lstm

在我的原始设置下,我得到了

X1 = (1200,40,1)
y1 = (1200,10)

然后,我可以完美地使用我的代码:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 1), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense(10)))

现在,我进一步得到了另一个与X1y1相同大小的时间序列数据。即

X2 = (1200,40,1)
y2 = (1200,10)

现在,我将X1X2y1y2堆叠为3D阵列:

X_stack = (1200,40,2)
y_stack = (1200,10,2)

然后,我尝试修改keras代码,例如:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 2), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense((10,2))))

我希望我的代码直接与3D数组X_stacky_stack一起使用,而不必将它们重塑为2D数组。您能帮我修改设置吗?谢谢。

4 个答案:

答案 0 :(得分:0)

您可以使用X_stack.shape()的输出元组:

model = Sequential()
model.add(LSTM(12, input_shape=(X_stack.shape[1], X_stack.shape[2]),return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense((10,2))))

答案 1 :(得分:0)

我假设为数组报告的形状中某处有错误。我猜y_stack.shape == (1200, 10, 2),对吗?

但是,这里有一种可能性可以做您描述的事情:

model = Sequential()
model.add(LSTM(12, input_shape=(40, 2), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add(Dense(10 * 2))
model.add(Reshape((10, 2)))

通过Dense层将网络的输出创建为2D张量,然后通过Reshape将其输出重塑为3D张量。 从输入输出的角度来看,这应该像您指定的那样。

答案 2 :(得分:0)

我假设您需要为堆栈中的每个数组共享参数。

  • 如果要堆叠全新的功能,则每个功能都不会有关联的目标。

  • 如果要堆叠完全不同的示例,则不会使用3D数组,而只是像正常情况一样将它们附加到末尾。

解决方案

要解决此问题,我将利用TimeDistributed wrapper from Keras

LSTM层的形状为(j, k),其中j是时间步数,k是要素数。由于您希望将数组保持为输入和输出的3D形式,因此您希望将其堆叠在与要素维度不同的维度上。

简要说明:

我认为重要的是要注意这两种方法之间的差异。在要素维上堆叠可为您提供相同时间步长的多个要素。在那种情况下,您可能希望使用相同的LSTM层而不走这条路线。因为您需要3D输入和3D输出,所以我建议您创建一个要堆叠的新尺寸,以便您可以独立应用相同的LSTM层。

时间分配:

此包装器在1索引处将一个层应用于每个数组。 通过将X1X2数组堆叠在1索引上,并使用TimeDistributed包装器,可以将LSTM层分别应用于所堆叠的每个数组。下面请注意,原始和更新的模型摘要具有完全相同的参数数量。

实施步骤:

  • 第一步是将(40, 2)的输入重塑为(2, 40, 1)。这相当于 2 x (40, 1)个数组输入。您可以像我一样在模型中进行此操作,也可以在构建数据集并更新输入形状时进行

    • 通过在末尾添加额外的维度(..., 1),我们将数据保持为LSTM能够理解的格式(如果它只是查看一次堆叠的数组之一)。请注意您的原始input_shape例如是(40, 1)
  • 然后将每个图层包装在TimeDistributed包装器中。

  • 最后,通过将(2, 10)交换为(10, 2),调整y输出的形状以匹配您的数据。

代码

from tensorflow.python.keras import Sequential
from tensorflow.python.keras.layers import LSTM, Dense, TimeDistributed, InputLayer, Reshape
from tensorflow.python.keras import backend
import numpy as np

# Original Model
model = Sequential()
model.add(LSTM(12, input_shape=(40, 1), return_sequences=True))
model.add(LSTM(12, return_sequences=True))
model.add(LSTM(6, return_sequences=False))
model.add((Dense(10)))

model.summary()

原始模型摘要

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm (LSTM)                  (None, 40, 12)            672       
_________________________________________________________________
lstm_1 (LSTM)                (None, 40, 12)            1200      
_________________________________________________________________
lstm_2 (LSTM)                (None, 6)                 456       
_________________________________________________________________
dense (Dense)                (None, 10)                70        
=================================================================
Total params: 2,398
Trainable params: 2,398
Non-trainable params: 0
_________________________________________________________________

应用时间分布的包装器

model = Sequential()
model.add(InputLayer(input_shape=(40, 2)))
model.add(Reshape(target_shape=(2, 40, 1)))
model.add(TimeDistributed(LSTM(12, return_sequences=True)))
model.add(TimeDistributed(LSTM(12, return_sequences=True)))
model.add(TimeDistributed(LSTM(6, return_sequences=False)))
model.add(TimeDistributed(Dense(10)))
model.add(Reshape(target_shape=(10, 2)))

model.summary()

更新的模型摘要

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
reshape (Reshape)            (None, 2, 40, 1)          0         
_________________________________________________________________
time_distributed (TimeDistri (None, 2, 40, 12)         672       
_________________________________________________________________
time_distributed_1 (TimeDist (None, 2, 40, 12)         1200      
_________________________________________________________________
time_distributed_2 (TimeDist (None, 2, 6)              456       
_________________________________________________________________
time_distributed_3 (TimeDist (None, 2, 10)             70        
_________________________________________________________________
reshape_1 (Reshape)          (None, 10, 2)             0         
=================================================================
Total params: 2,398
Trainable params: 2,398
Non-trainable params: 0
_________________________________________________________________

答案 3 :(得分:0)

我不能简短地回答这个问题,但是我认为需要对LSTM的一些基本概念进行澄清(一对一,一对多,...

由于超结构RNN(包括LSTM)是顺序的,所以它们被构造为找到类似时间的相关性,而CNN是空间的,它们被构造为找到类似空间的相关性。相关性

然后,LSTM在一对一,一对多,多对一和多对多中有进一步的区别,如 {{ 3}}

此处所需的网络类型是Many to one and many to many LSTM examples in Keras中的第5点,它表示:

  

步数与输入/输出长度不同时,很多对很多:这在Keras中很难实现。没有简单的代码片段可以对此进行编码。

因为输入形状为X_stack = (1200,40,2),所以它是类型5 并且输出形状为y_stack = (1200,10,2),因此时间步数不同({40输入和10输出)

如果您可以设法使输入和输出时间步数相等,则可以像 Many to one and many to many LSTM examples in Keras 中那样调整输入和输出数据(numpy.reshape)的形状(请注意数组中的 [] )。这并不意味着要重塑为2D(即展平)。 在keras LSTM feeding input with the right shape中,是使用TimeDistributed

构建具有等于输入和输出时间步长的多对多LSTM的完整示例。

仅出于完整性考虑,对于时空数据,还存在 CNN-LSTM ,但这不适用于此处,因为两个堆叠的时间序列没有明确的空间相关性:

如果您拥有3D数量(即,随时间变化的体积分布)并想了解这一点,则必须使用 CNN-LSTM网络。在这种方法中,将同时保留3D信息和时间信息。保留3D信息意味着不丢弃空间信息。通常,在像LSTM这样的类似时间的学习者中,通常会通过在空间图像中使用展平来丢弃该空间信息,然后再在LSTM中对其进行处理。 https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/

中有一个完整的教程,介绍如何在keras中构建(时空的)CNN-LSTM。