Keras序列模型的可变输入形状

时间:2017-07-19 03:56:55

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

我有一个Sequential模型定义如下:

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()层,那么在传递到Dense图层之前输入应该被展平之前,解决这个问题的方法是什么?

提前感谢任何建议。

修改 举一个潜在的训练集的例子 - 对于上面显示的带有input_shape =(2,4)的模型,训练集可能如下所示,其中集合中的每个2-d数组都具有形状(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]]
        ])

3 个答案:

答案 0 :(得分:0)

x_train具有变化维度,这将在训练阶段引起麻烦。如果wer pad额外为零,它会对您的数据产生重大影响吗?如果没有,找出不同尺寸的最大值并相应地构建新阵列,如下面的jupyter笔记本中所示:Dimension of x_train and x_train2

The way how you pad zeros

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

如果您的预期输出具有与输入对应的不同第一维,则第一维是样本数。在这种情况下,您可以从 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上定义的,也就是在特征轴上,所以你不需要定义第一个维度,也就是batch size。

模型总结

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)