Конкатенация LSTM с CNN с различными размерами тензоров в Керасе - PullRequest
0 голосов
/ 03 сентября 2018

это две нейронные сети, которые я попытался объединить с помощью операции сцепления. Сеть должна классифицировать обзоры фильмов IMDB по 1-хорошим и 0-плохим фильмам

def cnn_lstm_merged():
       embedding_vecor_length = 32
       cnn_model = Sequential()
       cnn_model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
       cnn_model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu'))
       cnn_model.add(MaxPooling1D(pool_size=2))
       cnn_model.add(Flatten())

       lstm_model = Sequential()
       lstm_model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
       lstm_model.add(LSTM(64, activation = 'relu'))
       lstm_model.add(Flatten())

       merge = concatenate([lstm_model, cnn_model])
       hidden = (Dense(1, activation = 'sigmoid'))(merge)
       #print(model.summary())
       output = hidden.fit(X_train, y_train, epochs=3, batch_size=64)
       return output

Но когда я запускаю код, появляется ошибка:

  File "/home/pythonist/Desktop/EnsemblingLSTM_CONV/train.py", line 59, in cnn_lstm_merged
    lstm_model.add(Flatten())
  File "/home/pythonist/deeplearningenv/lib/python3.6/site-packages/keras/engine/sequential.py", line 185, in add
    output_tensor = layer(self.outputs[0])
  File "/home/pythonist/deeplearningenv/lib/python3.6/site-packages/keras/engine/base_layer.py", line 414, in __call__
    self.assert_input_compatibility(inputs)
  File "/home/pythonist/deeplearningenv/lib/python3.6/site-packages/keras/engine/base_layer.py", line 327, in assert_input_compatibility
    str(K.ndim(x)))
ValueError: Input 0 is incompatible with layer flatten_2: expected min_ndim=3, found ndim=2
[Finished in 4.8s with exit code 1]

Как объединить эти два слоя? Спасибо

1 Ответ

0 голосов
/ 04 сентября 2018

Нет необходимости использовать Flatten после LSTM, поскольку LSTM (по умолчанию) возвращает только состояние last , а не последовательность, т. Е. Данные будут иметь форму (BS, n_output), но слой Flatten ожидает форму (BS, a, b), которая будет преобразована в (BS, a*b).

Итак, удалите слой Flatten и работайте только с последним состоянием или добавьте return_sequences=True к LSTM. Это заставит LSTM возвращать все выходы, а не только последний, т.е. (BS, T, n_out).

Редактировать : Кроме того, неправильный способ создания окончательной модели. Пожалуйста, посмотрите на этот пример; для вас это должно быть примерно так:

  merge = Concatenate([lstm_model, cnn_model])
  hidden = Dense(1, activation = 'sigmoid')
  conc_model = Sequential()
  conc_model.add(merge)
  conc_model.add(hidden)
  conc_model.compile(...)

  output = conc_model .fit(X_train, y_train, epochs=3, batch_size=64)

В целом, может быть лучше использовать Функциональный API .

Редактировать 2 : это окончательный код

cnn_model = Sequential()
cnn_model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
cnn_model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu'))
cnn_model.add(MaxPooling1D(pool_size=2))
cnn_model.add(Flatten())

lstm_model = Sequential()
lstm_model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
lstm_model.add(LSTM(64, activation = 'relu', return_sequences=True))
lstm_model.add(Flatten())

# instead of the last two lines you can also use
# lstm_model.add(LSTM(64, activation = 'relu'))
# then you do not have to use the Flatten layer. depends on your actual needs

merge = Concatenate([lstm_model, cnn_model])
hidden = Dense(1, activation = 'sigmoid')
conc_model = Sequential()
conc_model.add(merge)
conc_model.add(hidden)
...