我需要怎么做才能为TimeDistributed图层获得正确的输入形状?

时间:2019-05-01 21:49:37

标签: python-3.x tensorflow

我建立了一个模型,该模型由提供LSTM的CNN组成。我已经将CNN包裹在TimeDistributed包装器中。我已经将训练集(x值)配置为具有5D形状(batch_size,num_steps,image_height,image_width,channels)。尝试训练模型时,出现以下错误:ValueError:检查输入时出错:预期time_distributed_input具有5个维度,但数组的形状为(4,28,28,1)。

我尝试了许多不同的模型配置,并调试了代码。我可以看到ValueError被抛出的位置,但是我看不到任何防止这种情况发生的方法。代码详细信息。

我的模型构建代码:

def build_cnn(input_shape=None):
    print('Building the CNN')
    model = tfkm.Sequential()
    if input_shape:
        model.add(tfkl.Conv2D(64, (3, 3), activation='relu', input_shape=input_shape))
    else:
        model.add(tfkl.Conv2D(64, (3, 3), activation='relu'))
    model.add(tfkl.MaxPooling2D((2, 2), strides=(1, 1)))
    model.add(tfkl.Conv2D(128, (4, 4), activation='relu'))
    model.add(tfkl.MaxPooling2D((2, 2), strides=(2, 2)))
    model.add(tfkl.Conv2D(256, (4, 4), activation='relu'))
    model.add(tfkl.MaxPooling2D((2, 2), strides=(2, 2)))

    # extract features and dropout
    model.add(tfkl.Flatten())
    return model


def build_lstm(units, return_sequences, dropout):
    print('Building the LSTM model')
    model = tfkm.Sequential()
    model.add(tfkl.LSTM(units, return_sequences=return_sequences, dropout=dropout))
    return model


def build_classification_layer(num_classes):
    print('Building the classification-layer model')
    model = tfkm.Sequential()
    # classifier with sigmoid activation for multilabel
    model.add(tfkl.Dense(num_classes, activation='sigmoid'))
    return model


cnn = build_cnn(input_shape=(28, 28, 1))
lstm = build_lstm(256, False, 0.5)
classification_layer = build_classification_layer(2)


combined_model = tfkm.Sequential()
#combined_model.add(tfkl.TimeDistributed(cnn, batch_input_shape=(20, 4, 28, 28, 1)))
#combined_model.add(tfkl.TimeDistributed(cnn, input_shape=(4, 28, 28, 1), batch_size=20))
combined_model.add(tfkl.TimeDistributed(cnn, input_shape=(4, 28, 28, 1)))
combined_model.add(lstm)
combined_model.add(classification_layer)
combined_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

.
.
.
data-set building:  creating 20 individual records, each containing a sequence of 4 28x28x1 images and the associated labels list.
.
.
.
print('train_input shape: {}  train_labels shape: {}'.format(np.array(train_input).shape, np.array(train_labels).shape))

print('Training the model')
combined_model.fit(train_input, train_labels, epochs=2)

训练尝试的输出:

train_input shape: (20, 4, 28, 28, 1)  train_labels shape: (20,)
Training the model
Traceback (most recent call last):
  File "/Users/scott/sandbox/CNN-LSTM-sandbox/build_and_train.py", line 184, in <module>
    combined_model.fit(train_input, train_labels, epochs=2)
  File "/anaconda3/envs/TF2_py36/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 806, in fit
    shuffle=shuffle)
  File "/anaconda3/envs/TF2_py36/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 2596, in _standardize_user_data
    exception_prefix='input')
  File "/anaconda3/envs/TF2_py36/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_utils.py", line 340, in standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking input: expected time_distributed_input to have 5 dimensions, but got array with shape (4, 28, 28, 1)

Process finished with exit code 1

请注意,无论我的代码中有三个combined_model.add(tfkl.TimeDistributed(cnn...版本中的哪个版本,我都会得到相同的结果。

我不期望模型提供的内容与提供的内容之间存在差异。我正在提供5D数据集,这就是它想要的,但是它声称我只提供4D数据集。

在调试时,我发现了抛出ValueError的地方。它位于training_utils.py的第336行-if len(data_shape) != len(shape):(为上下文显示了第303-350行):

lines 303-350 of training_utils.py:

  if len(data) != len(names):
    if data and hasattr(data[0], 'shape'):
      raise ValueError('Error when checking model ' + exception_prefix +
                       ': the list of Numpy arrays that you are passing to '
                       'your model is not the size the model expected. '
                       'Expected to see ' + str(len(names)) + ' array(s), '
                       'but instead got the following list of ' +
                       str(len(data)) + ' arrays: ' + str(data)[:200] + '...')
    elif len(names) > 1:
      raise ValueError('Error when checking model ' + exception_prefix +
                       ': you are passing a list as input to your model, '
                       'but the model expects a list of ' + str(len(names)) +
                       ' Numpy arrays instead. The list you passed was: ' +
                       str(data)[:200])
    elif len(data) == 1 and not hasattr(data[0], 'shape'):
      raise TypeError('Error when checking model ' + exception_prefix +
                      ': data should be a Numpy array, or list/dict of '
                      'Numpy arrays. Found: ' + str(data)[:200] + '...')
    elif len(names) == 1:
      data = [np.asarray(data)]

  # Check shapes compatibility.
  if shapes:
    for i in range(len(names)):
      if shapes[i] is not None:
        if tensor_util.is_tensor(data[i]):
          tensorshape = data[i].get_shape()
          if not tensorshape:
            continue
          data_shape = tuple(tensorshape.as_list())
        else:
          data_shape = data[i].shape
        shape = shapes[i]
        if len(data_shape) != len(shape):
          raise ValueError('Error when checking ' + exception_prefix +
                           ': expected ' + names[i] + ' to have ' +
                           str(len(shape)) + ' dimensions, but got array '
                           'with shape ' + str(data_shape))
        if not check_batch_axis:
          data_shape = data_shape[1:]
          shape = shape[1:]
        for dim, ref_dim in zip(data_shape, shape):
          if ref_dim != dim and ref_dim is not None and dim is not None:
            raise ValueError('Error when checking ' + exception_prefix +
                             ': expected ' + names[i] + ' to have shape ' +
                             str(shape) + ' but got array with shape ' +
                             str(data_shape))
  return data

调试器命中336行时的状态是:

np.array(data).shape = <class 'tuple'>: (1, 4, 28, 28, 1)
data_shape = <class 'tuple'>: (4, 28, 28, 1)
name = <class 'list'>: ['time_distributed_input']
shapes = <class 'list'>: [(None, 4, 28, 28, 1)]

由此,可以看到到达这一点的数据形状是正确的,但是代码提取了批处理中的第一条记录,并将其形状与TimeDistributed层期望的形状进行了比较。问题在于,TimeDistributed层期望以(None, 4, 28, 28, 1)的形式进行批处理表示,但在b / c中,代码只在该批处理位置data_shape = data[i].shape处提取了输入记录。

从我的角度来看,批次尺寸不应该在用于为InputLayer建立数据预期形状的元组中表示,批次长度比较需要忽略形状元组中的None,否则比较应为if len(np.array(data).shape) != len(shape):

0 个答案:

没有答案