【问题标题】:In Keras, how to get 3D input and 3D output for LSTM layers在 Keras 中,如何获取 LSTM 层的 3D 输入和 3D 输出
【发布时间】:2019-10-08 20:56:27
【问题描述】:

在我原来的设置中,我得到了

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 数组。你能帮我看看如何修改设置吗?谢谢。

【问题讨论】:

    标签: python keras neural-network lstm


    【解决方案1】:

    可以使用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))))
    

    【讨论】:

    • 它会使其更加动态,但它与 @nam 的 input_shape 完全相同
    【解决方案2】:

    我假设您为数组报告的形状中某处存在错误。我猜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 张量。 从输入输出的角度来看,这应该像您指定的那样。

    【讨论】:

      【解决方案3】:

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

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

      • 如果您堆叠完全不同的示例,那么您将不会使用 3D 数组,而只会像往常一样将它们附加到末尾。

      解决方案

      为了解决这个问题,我会利用TimeDistributed wrapper from Keras

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

      快速旁注:

      我认为注意这些方法之间的区别很重要。在特征维度上堆叠为您提供了相同时间步长的多个特征。在这种情况下,你会想要使用相同的 LSTM 层而不是走这条路。因为你想要一个 3D 输入和一个 3D 输出,所以我建议你创建一个新的维度来堆叠,这样你就可以独立地应用相同的 LSTM 层。

      时间分布:

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

      实施步骤:

      • 第一步是将(40, 2)的输入reshape成(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
      _________________________________________________________________
      

      应用 TimeDistributed Wrapper

      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
      _________________________________________________________________
      

      【讨论】:

        【解决方案4】:

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

        作为一个上层结构,RNN(包括 LSTM)是顺序的,它们的构建是为了寻找类时间的相关性,而 CNN 是空间的,它们是为了寻找类空间的相关性

        然后在 一对一、一对多、多对一和多对多中进一步区分 LSTM,如 @987654321 所示@

        这里需要的网络类型是Many to one and many to many LSTM examples in Keras 中的第 5 点,上面写着:

        当步数与输入/输出长度不同时的多对多:这在 Keras 中非常困难。没有简单的代码 sn-ps 来编写代码。

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

        如果您可以设法拥有相同数量的输入和输出时间步,您可以像 keras LSTM feeding input with the right shape 那样重塑输入和输出数据 (numpy.reshape)(注意 的排列[] 在数组中)。这并不意味着重塑为 2D(即展平)。 在https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/ 中是一个完整的示例,用于使用TimeDistributed 层构建具有相等输入和输出时间步长的多对多 LSTM

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

        如果您有一个 3D 量,即随时间变化的体积分布并且想要了解这一点,那么您必须使用 CNN-LSTM 网络。在这种方法中,3D 信息和时间信息都被保留了。保留 3D 信息意味着不丢弃空间信息。通常在像 LSTM 这样的类时间学习器中,这种空间信息经常被丢弃,即在 LSTM 中处理图像之前展平图像。 如何在 keras 中构建(时空)CNN-LSTM 的完整教程在 https://machinelearningmastery.com/cnn-long-short-term-memory-networks/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-20
          • 1970-01-01
          • 2020-02-18
          • 2020-11-30
          • 2020-04-17
          • 2020-02-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多