Keras: remodelar para conectar lstm e conv

Esta questão existe como umquestão do github , também. Gostaria de construir uma rede neural em Keras que contenha convoluções 2D e uma camada LSTM.

A rede deve classificar MNIST. Os dados de treinamento no MNIST são 60000 imagens em escala de cinza de dígitos manuscritos de 0 a 9. Cada imagem tem 28x28 pixels.

Dividei as imagens em quatro partes (esquerda / direita, cima / baixo) e as reorganizei em quatro ordens para obter seqüências para o LSTM.

|     |      |1 | 2|
|image|  ->  -------   -> 4 sequences: |1|2|3|4|,  |4|3|2|1|, |1|3|2|4|, |4|2|3|1|
|     |      |3 | 4|

Uma das sub-imagens pequenas tem a dimensão 14 x 14. As quatro seqüências são empilhadas juntas ao longo da largura (não importa se a largura ou a altura).

Isso cria um vetor com a forma [60000, 4, 1, 56, 14] em que:

60000 é o número de amostras4 é o número de elementos em uma sequência (# de timesteps)1 é a profundidade das cores (escala de cinza)56 e 14 são largura e altura

Agora isso deve ser dado ao modelo Keras. O problema é alterar as dimensões de entrada entre a CNN e o LSTM. Pesquisei online e encontrei esta pergunta:Python keras como alterar o tamanho da entrada após a camada de convolução na camada lstm

A solução parece ser uma camada de Remodelagem, que nivela a imagem, mas mantém os timestados (em oposição a uma camada de Achatamento, que retraía tudo, exceto o tamanho do lote).

Aqui está o meu código até agora:

nb_filters=32
kernel_size=(3,3)
pool_size=(2,2)
nb_classes=10
batch_size=64

model=Sequential()

model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
    border_mode="valid", input_shape=[1,56,14]))
model.add(Activation("relu"))
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=pool_size))


model.add(Reshape((56*14,)))
model.add(Dropout(0.25))
model.add(LSTM(5))
model.add(Dense(50))
model.add(Dense(nb_classes))
model.add(Activation("softmax"))

Este código cria uma mensagem de erro:

ValueError: o tamanho total da nova matriz deve ser inalterado

Aparentemente, a entrada para a camada Remodelar está incorreta. Como alternativa, tentei passar os timesteps para a camada Remodelar também:

model.add(Reshape((4,56*14)))

Isso não parece certo e, em qualquer caso, o erro permanece o mesmo.

Estou fazendo isso da maneira certa? Uma camada Remodelar é a ferramenta adequada para conectar CNN e LSTM?

Existem abordagens bastante complexas para esse problema. Tal como este:https://github.com/fchollet/keras/pull/1456 Uma camada TimeDistributed que parece ocultar a dimensão timestep das seguintes camadas.

Ou isto:https://github.com/anayebi/keras-extra Um conjunto de camadas especiais para combinar CNNs e LSTMs.

Por que existem soluções tão complicadas (pelo menos elas me parecem complicadas), se uma simples Remodelagem faz o truque?

ATUALIZAR:

De maneira vergonhosa, esqueci que as dimensões serão alteradas pelo pool e (por falta de preenchimento) as convoluções também.kgrm me aconselhou a usarmodel.summary() para verificar as dimensões.

A saída da camada antes da camada Remodelar é(None, 32, 26, 5), Alterei a remodelagem para:model.add(Reshape((32*26*5,))).

Agora o ValueError se foi, em vez disso, o LSTM reclama:

Exceção: A entrada 0 é incompatível com a camada lstm_5: esperado ndim = 3, encontrado ndim = 2

Parece que preciso passar a dimensão timestep por toda a rede. Como eu posso fazer isso ? Se eu adicioná-lo ao input_shape da Convolução, ele também reclama:Convolution2D(nb_filters, kernel_size[0], kernel_size[1], border_mode="valid", input_shape=[4, 1, 56,14])

Exceção: A entrada 0 é incompatível com a camada convolution2d_44: esperado ndim = 4, encontrado ndim = 5

questionAnswers(1)

yourAnswerToTheQuestion