【问题标题】:Variable Input Shape for Keras Sequential ModelKeras 序列模型的可变输入形状
【发布时间】:2017-12-24 03:26:38
【问题描述】:

我有一个按如下定义的顺序模型:

model = Sequential([
    BatchNormalization(axis=1,input_shape=(2,4)),
    Flatten(),
    Dense(256, activation='relu'),       
    BatchNormalization(),
    Dropout(0.1),
    Dense(2, activation='softmax')
])

我想更改此模型以获取可变形状的输入。具体来说,第一个维度需要是可变的。 阅读specifying the input shape 上的 Keras 文档,我发现您可以在 input_shape 元组中使用 None 条目,其中 None 表示可能需要任何正整数。

使用我现有的模型,如果我将 input_shape 从 (2,4) 更改为 (None,4),我会收到以下错误:

---> Dense(2, activation='softmax')
TypeError: an integer is required

我不肯定,但我不相信当模型包含 Flatten() 层时可以指定可变输入形状。我读过 Flatten() 需要知道输入形状,因此可变输入形状与 Flatten() 不兼容。 如果我删除 Flatten() 层,我会收到与上面相同的错误。我不希望这个模型在没有 Flatten() 层的情况下也能工作,因为我认为输入在传递到 Dense 层之前必须被展平。

鉴于此,谁能解释我如何能够利用可变输入形状?如果这里的问题是 Flatten() 层,那么考虑到输入应该在传递到密集层之前被展平,有什么方法可以解决这个问题?

提前感谢您的任何建议。

编辑: 举一个潜在训练集的例子—— 对于上面显示的 input_shape=(2,4) 模型,训练集可能如下所示,其中集合中的每个二维数组的形状为 (2,4):

x_train = np.array([
         [[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99]], 
         [[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99]],
         [[1.01 ,1, 1.2, 1.2], [1.3, 1.2, 0.89, 0.98]]
        ])

对于 input_shape = (None,4) 的数据,其中每个数据点的第一个维度的形状可以变化,第二个维度固定为 4,训练集可能如下所示:

x_train = np.array([
         [[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99], [1.1, 1.2, 0.91, 0.99]], 
         [[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99]],
         [[1,1,1,1], [1.3, 1.2, 0.89, 0.98], [1,1,1,1], [1,1,1,1]]
        ])

【问题讨论】:

  • 你能解释一下你的数据形状吗?为什么会有变数?您是在谈论可以变化的样本数量吗?还是功能会有所不同?
  • @VivekKumar 我说的是功能可能会有所不同。例如,在上面的模型中,我传递了形状为 (2,4) 的输入。示例:[[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99]] 但我需要模型能够接受输入可变的第一维。因此,某些输入可能具有形状 (2,4),例如,就像上面示例中所示的那样,而其他输入可能具有形状 (3,4) 或 (4,4) 或 (5,4),等形状 (3,4) 的示例输入:[[1, 1.02, 1.3, 0.9], [1.1, 1.2, 0.91, 0.99], [1.3, 1.2, 0.89, 0.98]]。
  • 是的,这就是我要问的。在二维数据数组中,第一维代表样本,而不是特征。这意味着您的样本正在发生变化并且功能是相同的。您应该指定input_shape=(4)
  • 感谢@VivekKumar,但我认为这不正确。在 input_shape=(4) 的情况下,模型期望每个数据点都是长度为 4 的单个一维数组。情况并非如此。我的整个数据集不是包含长度为 4 的子一维数组的二维数组。该集中的每个数据点都是一个二维数组,其中可能有 2,3,4,5,...,该二维数组中的 n 个长度为 4 的一维数组。 x_train = np.array([ [[1,1,1,1], [1,2,3,9], [1,1,1,1]], [[1,2,2,2], [1,1,1,7]], [[1,1,1,1],[1,1,5,2],[1,2,1,1],[1,2,2,2 ]] ])
  • 对原始帖子添加了一个编辑,以更好地显示示例训练集。

标签: python neural-network deep-learning keras theano


【解决方案1】:

x_train 具有可变维度,这将在训练阶段造成麻烦。如果我们填充额外的零,它会对您的数据产生重大影响吗?如果没有,请找出最大可变维度并相应地构建您的新数组,如下图所示在 jupyter 笔记本中:

【讨论】:

    【解决方案2】:

    Keras 中的输入形状必须先验固定,也许你应该使用 PyTorch 来解决这个问题(动态输入)。

    要在 Keras 中解决它,只需找到第一个维度的最大长度,然后使用填充(零值)来完成其他示例,直到它们达到最大长度。

    【讨论】:

      【解决方案3】:

      如果您的预期输出具有与输入相对应的变化的第一维度,则第一维度是样本数。在这种情况下,您可以省略 BatchNormalization 中的 input_shape 参数并添加具有特征数量的输入层

      model = Sequential([
        Input(4),
        BatchNormalization(axis=1),
        Flatten(),
        Dense(256, activation='relu'),       
        BatchNormalization(),
        Dropout(0.1),
        Dense(2, activation='softmax')
      ])
      

      由于您的 BatchNormalization 是在axis=1 上定义的,即在特征轴上,您不需要定义第一个维度,即批量大小。

      模型摘要

      model.summary()
      >>>
      Model: "sequential"
      _________________________________________________________________
      Layer (type)                 Output Shape              Param #   
      =================================================================
      batch_normalization (BatchNo (None, 4)                 16        
      _________________________________________________________________
      flatten (Flatten)            (None, 4)                 0         
      _________________________________________________________________
      dense (Dense)                (None, 256)               1280      
      _________________________________________________________________
      batch_normalization_1 (Batch (None, 256)               1024      
      _________________________________________________________________
      dropout (Dropout)            (None, 256)               0         
      _________________________________________________________________
      dense_1 (Dense)              (None, 2)                 514       
      =================================================================
      Total params: 2,834
      Trainable params: 2,314
      Non-trainable params: 520
      

      然后你可以在你的输入上运行它

      model.predict(x_train[0])
      >>> array([[0.36491784, 0.63508224],
         [0.3834786 , 0.61652136],
         [0.3834786 , 0.61652136]], dtype=float32)
      
      model.predict(x_train[1])
      >>> array([[0.36491784, 0.63508224],
         [0.38347858, 0.61652136]], dtype=float32)
      

      但是,如果您想为 x_train 上的每个样本生成形状为 (1,2) 的输出,那么 x_train 中的每一行都是一个样本,在这种情况下,您的 Dense层需要可变数量的参数,这对梯度下降没有意义。

      在这种情况下,您可能正在寻找一个 递归神经网络,这是一种不同的野兽,一个例子可能是这样的

      model = tf.keras.Sequential()
      model.add(Input((None, 4)))
      
      model.add(LSTM(128))
      
      model.add(Dense(2))
      

      模型总结

      model.summary()
      >>>
      Model: "sequential_5"
      _________________________________________________________________
      Layer (type)                 Output Shape              Param #   
      =================================================================
      lstm_3 (LSTM)                (None, 128)               68096     
      _________________________________________________________________
      dense_4 (Dense)              (None, 2)                 258       
      =================================================================
      Total params: 68,354
      Trainable params: 68,354
      Non-trainable params: 0
      

      要在您的数据集上运行它,只需扩展每个样本的第一个维度,即批量为 1,即单个样本。

      model.predict(np.expand_dims(x_train[0],0))
      >>>
      array([[0.19657324, 0.09764521]], dtype=float32)
      
      model.predict(np.expand_dims(x_train[1],0))
      >>>
      array([[0.15233153, 0.08189206]], dtype=float32)
      

      【讨论】:

        猜你喜欢
        • 2019-12-12
        • 1970-01-01
        • 1970-01-01
        • 2019-01-26
        • 2020-09-26
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        • 2022-10-18
        相关资源
        最近更新 更多