Я пытаюсь построить сверточную нейронную сеть в Keras, которая включает в себя сверточный слой LSTM (ConvLSTM2D) в середине для обработки последовательности изображений GRAYSCALE, которые приходят из видео.Каждая форма кадра имеет вид (61,61,1), и их последовательности передаются вместе, поэтому общий ввод (num_movies, num_frames, frame_height, frame_width, 1).Сверточные слои предварительно обучаются для автоматического кодирования изображений в последовательности, поэтому остается только обучить рекуррентный слой LSTM.Когда у меня только один фильтр, сеть работает нормально.Вот сеть (все уровни, кроме уровня LSTM, распределены по времени).Цель сети состоит в том, чтобы предсказать будущие кадры в видео, учитывая текущие кадры (т.е. передать последовательность, переместить последовательность вперед на n кадров).Я обучил сверточную часть (автокодер; см. Код ниже) отдельно, чтобы автоматически кодировать отдельные кадры, и теперь пытаюсь добавить в LSTM выполнение предсказаний последовательности.
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
time_distributed_1 (ZeroPad) (None, 34, 64, 64, 1) 0
_________________________________________________________________
time_distributed_2 (Conv2D) (None, 34, 64, 64, 16) 160
_________________________________________________________________
time_distributed_3 (MaxPool) (None, 34, 32, 32, 16) 0
_________________________________________________________________
time_distributed_4 (Conv2D) (None, 34, 32, 32, 8) 1160
_________________________________________________________________
time_distributed_5 (MaxPool) (None, 34, 16, 16, 8) 0
_________________________________________________________________
time_distributed_6 (Conv2D) (None, 34, 16, 16, 8) 584
_________________________________________________________________
time_distributed_7 (MaxPool) (None, 34, 8, 8, 8) 0
_________________________________________________________________
time_distributed_8 (Conv2D) (None, 34, 8, 8, 8) 584
_________________________________________________________________
time_distributed_9 (MaxPool) (None, 34, 4, 4, 8) 0
_________________________________________________________________
time_distributed_10 (Conv2D) (None, 34, 4, 4, 1) 73
_________________________________________________________________
rnn (ConvLSTM2D) (None, 34, 4, 4, 1) 36
_________________________________________________________________
time_distributed_11 (Conv2D) (None, 34, 4, 4, 4) 40
_________________________________________________________________
time_distributed_12 (UpSample) (None, 34, 8, 8, 4) 0
_________________________________________________________________
time_distributed_13 (Conv2D) (None, 34, 8, 8, 8) 296
_________________________________________________________________
time_distributed_14 (UpSample) (None, 34, 16, 16, 8) 0
_________________________________________________________________
time_distributed_15 (Conv2D) (None, 34, 16, 16, 8) 584
_________________________________________________________________
time_distributed_16 (UpSample) (None, 34, 32, 32, 8) 0
_________________________________________________________________
time_distributed_17 (Conv2D) (None, 34, 32, 32, 16) 1168
_________________________________________________________________
time_distributed_18 (UpSample) (None, 34, 64, 64, 16) 0
_________________________________________________________________
time_distributed_19 (Conv2D) (None, 34, 64, 64, 1) 145
_________________________________________________________________
time_distributed_20 (UpSample) (None, 34, 61, 61, 1) 0
=================================================================
Total params: 4,830
Trainable params: 36
Non-trainable params: 4,794
_________________________________________________________________
Все выполняется, когда количество фильтров в ConvLSTM2Dслой один.Однако, когда я пытаюсь настроить количество фильтров в слое ConvLSTM2D, я получаю ошибку:
"ValueError: количество входных каналов не соответствует соответствующему размеру фильтра, 7! = 1"
где 7 - количество фильтров, которые я пытаюсь использовать.
Здесь я строю авто-кодер.
autoencoder = Sequential()
autoencoder.add(ZeroPadding2D(((2,1),(2,1)), input_shape = image_shape)) # (61,61, 1) --> (64,64, 1)
autoencoder.add(Conv2D(16, (3,3), activation='relu', padding='same')) # (64, 64, 1) --> (64, 64, 16)
autoencoder.add(MaxPooling2D((2,2), padding='same')) # (64, 64, 16) --> (32, 32, 16)
autoencoder.add(Conv2D(8, (3,3), activation = 'relu', padding = 'same')) # (32,32, 16) --> (32,32, 8)
autoencoder.add(MaxPooling2D((2,2), padding = 'same')) # (32, 32, 8) --> (16,16, 8)
autoencoder.add(Conv2D(8, (3,3), activation = 'relu', padding = 'same')) # (16,16,8) --> (16,16,4)
autoencoder.add(MaxPooling2D((2,2), padding = 'same')) # (16, 16, 4) --> (4, 4, 4)
autoencoder.add(Conv2D(8, (3,3), activation = 'relu', padding = 'same')) # (16,16,8) --> (16,16,4)
autoencoder.add(MaxPooling2D((2,2), padding = 'same')) # (16, 16, 4) --> (4, 4, 4)
autoencoder.add(Conv2D(1, (3,3), activation = 'relu', padding = 'same')) # (4,4,4) --> (4,4,1)
# decode the lower dimensional representation back into an image
model.add(Conv2D(4,(3,3), activation = 'relu', padding = 'same')) # (4,4,1) --> (4,4,4)
autoencoder.add(UpSampling2D((2,2))) # (4,4,4) -> (16,16,4)
autoencoder.add(Conv2D(8,(3,3), activation = 'relu', padding = 'same')) # (4,4,1) --> (4,4,4)
autoencoder.add(UpSampling2D((2,2))) # (4,4,4) -> (16,16,4)
autoencoder.add(Conv2D(8,(3,3), activation = 'relu', padding = 'same')) # (16,16,4) --> (16,16,8)
autoencoder.add(UpSampling2D((2,2))) # (16,16,8) -> (32,32,8)
autoencoder.add(Conv2D(16, (3,3), activation = 'relu', padding='same'))# (32,32,8) -> (32,32,16)
autoencoder.add(UpSampling2D((2,2))) # (32,32,16) -> (64,64,16)
# want to use sigmoid as our final activation function to make the output more
autoencoder.add(Conv2D(1, (3,3), activation='sigmoid', padding='same')) # (64,64,16) -> (64,64, 1)
autoencoder.add(Cropping2D(((2,1),(2,1)))) # (64,64,1) -> (61,61, 1)
После того, как авто-кодер собран, я обучаю его задаче авто-кодирования идобавьте в слой LSTM.
num_layers = len(autoencoder.layers)
model = Sequential()
for i in range(num_layers // 2):
model.add(TimeDistributed(autoencoder.layers[i]))
out_shape = autoencoder.layers[num_layers//2 - 1].output_shape
# Convolutional LSTM
num_filters = 7
kernel_shape = (2,2)
model.add(ConvLSTM2D(filters=num_filters,
kernel_size=kernel_shape,
activation='tanh',
padding='same',
return_sequences = True,
name='rnn'))
''' #SimpleRNN
model.add(TimeDistributed(Flatten()))
model.add(SimpleRNN(rnn_size,
return_sequences = True,
activation = 'tanh',
name='rnn'))
# NOTE: since the RNN changes size of output of the final Conv2D layer in encoding section, we somehow have
# to map the dimension back down. This is what the Dense layer below does
model.add(TimeDistributed(Dense(out_shape[1] * out_shape[2], activation = 'relu', name = 'ff')))
model.add(TimeDistributed(Reshape((out_shape[1], out_shape[2], 1))))
'''
for i in range(num_layers//2, num_layers):
model.add(TimeDistributed(autoencoder.layers[i]))
# set non-reccurent layers to untrainable; we already trained these to be autoencoders, so the RNN
# just has to learn how to move the object in the low dimensional space
for layer in model.layers:
~ if not (layer.name == 'rnn' or layer.name == 'ff'):
layer.trainable = False
Когда я заменяю количество фильтров на что-то кроме одного, я сразу получаю эту ошибку:
ValueError: количество входных каналов не соответствует соответствующему измерениюof filter, 7! = 1
Я не понимаю, почему количество фильтров должно быть привязано к количеству входных каналов?Разве у нас не может быть несколько фильтров, каждый с разными ядрами на одном входе?
Я попробовал некоторые общие исправления, такие как установка 'data_format = channel_last'