Keras ConvLSTM2D: ValueError на выходном слое

Я пытаюсь обучить сверточный 2D LSTM делать категориальные прогнозы на основе видеоданных. Однако мой выходной слой, похоже, столкнулся с проблемой:

"ValueError: Ошибка при проверке цели: ожидалось, что плотный_1 будет иметь 5 измерений, но получен массив с формой (1, 1939, 9)"

Моя текущая модель основана на предоставленном примере ConvLSTM2D. пользователя Keras Team. Я считаю, что указанная выше ошибка является результатом моего неправильного понимания примера и его основных принципов.

Данные

У меня есть произвольное количество видео, где каждое видео содержит произвольное количество кадров. Каждый кадр имеет размер 135x240x1 (последние цветовые каналы). Это приводит к форме ввода (None, None, 135, 240, 1), где два значения «None» - это размер пакета и временные шаги в указанном порядке. Если я тренируюсь на одном видео с 1052 кадрами, моя входная форма становится (1, 1052, 135, 240, 1).

Для каждого кадра модель должна прогнозировать значения от 0 до 1 по 9 классам. Это означает, что моя выходная форма - (Нет, Нет, 9). Если я тренируюсь на одном видео с 1052 кадрами, тогда эта форма становится (1, 1052, 9).

Модель

Layer (type)                 Output Shape              Param #
=================================================================
conv_lst_m2d_1 (ConvLSTM2D)  (None, None, 135, 240, 40 59200
_________________________________________________________________
batch_normalization_1 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_2 (ConvLSTM2D)  (None, None, 135, 240, 40 115360
_________________________________________________________________
batch_normalization_2 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_3 (ConvLSTM2D)  (None, None, 135, 240, 40 115360
_________________________________________________________________
batch_normalization_3 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
dense_1 (Dense)              (None, None, 135, 240, 9) 369
=================================================================
Total params: 290,769
Trainable params: 290,529
Non-trainable params: 240

Исходный код

model = Sequential()

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        input_shape=(None, 135, 240, 1),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(Dense(
        units=classes,
        activation='softmax'
))
model.compile(
        loss='categorical_crossentropy',
        optimizer='adadelta'
)
model.fit_generator(generator=training_sequence)

Отслеживание

Epoch 1/1
Traceback (most recent call last):
  File ".\lstm.py", line 128, in <module>
    main()
  File ".\lstm.py", line 108, in main
    model.fit_generator(generator=training_sequence)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\models.py", line 1253, in fit_generator
    initial_epoch=initial_epoch)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 2244, in fit_generator
    class_weight=class_weight)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 1884, in train_on_batch
    class_weight=class_weight)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 1487, in _standardize_user_data
    exception_prefix='target')
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 113, in _standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking target: expected dense_1 to have 5 dimensions, but got array with shape (1, 1939, 9)

Образец формы ввода, напечатанный с размером пакета, равным 1, - (1, 1389, 135, 240, 1). Эта форма соответствует требованиям, которые я описал выше, поэтому я считаю, что мой подкласс Keras Sequence (в исходном коде как «training_sequence») правильный.

Я подозреваю, что проблема вызвана моим прямым переходом от BatchNormalization () к Dense (). В конце концов, трассировка указывает на то, что проблема возникает в плотном_1 (последнем слое). Тем не менее, я не хочу никого сбивать с пути своими знаниями на начальном уровне, поэтому, пожалуйста, отнеситесь к моей оценке с долей скептицизма.

Изменить 27 марта 2018 г.

Прочитав этот поток, в котором используется аналогичная модель, я изменил свой последний слой ConvLSTM2D так, чтобы для параметра return_sequences было установлено значение False вместо True. Я также добавил слой GlobalAveragePooling2D перед слоем Dense. Обновленная модель выглядит следующим образом:

Layer (type)                 Output Shape              Param #
=================================================================
conv_lst_m2d_1 (ConvLSTM2D)  (None, None, 135, 240, 40 59200
_________________________________________________________________
batch_normalization_1 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_2 (ConvLSTM2D)  (None, None, 135, 240, 40 115360
_________________________________________________________________
batch_normalization_2 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_3 (ConvLSTM2D)  (None, 135, 240, 40)      115360
_________________________________________________________________
batch_normalization_3 (Batch (None, 135, 240, 40)      160
_________________________________________________________________
global_average_pooling2d_1 ( (None, 40)                0
_________________________________________________________________
dense_1 (Dense)              (None, 9)                 369
=================================================================
Total params: 290,769
Trainable params: 290,529
Non-trainable params: 240

Вот новая копия трассировки:

Traceback (most recent call last):
  File ".\lstm.py", line 131, in <module>
    main()
  File ".\lstm.py", line 111, in main
    model.fit_generator(generator=training_sequence)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\models.py", line 1253, in fit_generator
    initial_epoch=initial_epoch)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 2244, in fit_generator
    class_weight=class_weight)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 1884, in train_on_batch
    class_weight=class_weight)
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 1487, in _standardize_user_data
    exception_prefix='target')
  File "C:\Users\matth\Anaconda3\envs\capstone-gpu\lib\site-packages\keras\engine\training.py", line 113, in _standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking target: expected dense_1 to have 2 dimensions, but got array with shape (1, 1034, 9)

На этом прогоне я распечатал формы x и y. x был (1, 1034, 135, 240, 1), а y был (1, 1034, 9). Это может сузить проблему. Похоже, проблема связана с данными y, а не данными x. В частности, слою Dense не нравится временное затемнение. Однако я не знаю, как исправить эту проблему.

Изменить 28 марта 2018 г.

Решение Ю-Яна сработало. Для тех, кто столкнулся с подобной проблемой и хочет увидеть, как выглядела окончательная модель, вот краткое изложение:

Layer (type)                 Output Shape              Param #
=================================================================
conv_lst_m2d_1 (ConvLSTM2D)  (None, None, 135, 240, 40 59200
_________________________________________________________________
batch_normalization_1 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_2 (ConvLSTM2D)  (None, None, 135, 240, 40 115360
_________________________________________________________________
batch_normalization_2 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
conv_lst_m2d_3 (ConvLSTM2D)  (None, None, 135, 240, 40 115360
_________________________________________________________________
batch_normalization_3 (Batch (None, None, 135, 240, 40 160
_________________________________________________________________
average_pooling3d_1 (Average (None, None, 1, 1, 40)    0
_________________________________________________________________
reshape_1 (Reshape)          (None, None, 40)          0
_________________________________________________________________
dense_1 (Dense)              (None, None, 9)           369
=================================================================
Total params: 290,769
Trainable params: 290,529
Non-trainable params: 240

Также исходный код:

model = Sequential()

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        input_shape=(None, 135, 240, 1),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(
        filters=40,
        kernel_size=(3, 3),
        padding='same',
        return_sequences=True))
model.add(BatchNormalization())

model.add(AveragePooling3D((1, 135, 240)))
model.add(Reshape((-1, 40)))
model.add(Dense(
        units=9,
        activation='sigmoid'))

model.compile(
        loss='categorical_crossentropy',
        optimizer='adadelta'
)

person Matthew Harrison    schedule 28.03.2018    source источник
comment
Удачи с Keras на гитхабе? Мне тоже любопытно.   -  person jrjames83    schedule 28.03.2018
comment
Я не совсем понимаю, что вы имеете ввиду. Вы спрашиваете, открыл ли я там новый выпуск?   -  person Matthew Harrison    schedule 28.03.2018
comment
@MatthewHarrison Просто пояснение, если вы ожидаете 9 значений от 0 до 1, почему ваша активация softmax? Это ведь не классификация?   -  person user239457    schedule 28.03.2018
comment
Предполагается, что пара фрейм / метка может давать несколько классов. Пример вывода будет примерно таким: [0,2, 0,7, 0,3, 0,2, 0,9, 0,8, 0,9, 0,1, 0,2]   -  person Matthew Harrison    schedule 28.03.2018
comment
@MatthewHarrison Итак, вы передадите 9 функций для каждого кадра, и вам нужно 9 прогнозов в конце для каждого видео. Правильно?   -  person user239457    schedule 28.03.2018
comment
Я передаю 9 функций на кадр и хочу 9 прогнозов на кадр. Цель состоит в том, чтобы он следил за буфером кадров в реальном времени и делал прогнозы для каждого кадра.   -  person Matthew Harrison    schedule 28.03.2018
comment
Возможно, я неправильно понимаю терминологию, поэтому я попытаюсь объяснить, используя термины, которые мне удобнее. Для каждого кадра видео я передаю буфер 135x240 (x) вместе с 9 метками (y). Состояние меток в одном кадре может повлиять на состояние меток в следующем кадре. Таким образом, для любого заданного кадра я хочу иметь возможность предсказывать метки для этого фрейма, и я хочу, чтобы в моем предсказании учитывались состояния меток в предыдущих кадрах.   -  person Matthew Harrison    schedule 28.03.2018
comment
Теперь я понимаю вашу проблему, что вы хотите 9 выходов для каждого кадра, которые являются вероятностями того, что кадр находится в этом классе. ConvLSTM возьмет все кадры, объединит их во времени и увидит, как они меняются с течением времени. Я не думаю, что это то, что вы хотите делать. Что определяет, находится ли фрейм в классе или нет?   -  person user239457    schedule 28.03.2018
comment
Если вам нужен прогноз на каждый кадр, вам обязательно нужно установить return_sequences=True в вашем последнем ConvLSTM2D слое.   -  person Yu-Yang    schedule 28.03.2018
comment
Вы можете заменить слой GlobalAveragePooling2D() на AveragePooling3D((1, 135, 240)) плюс Reshape((-1, 40)), чтобы форма вывода была совместима с целевым массивом.   -  person Yu-Yang    schedule 28.03.2018
comment
@ user239457 Кадры захватываются графическим буфером из игры, а метки показывают, какие кнопки были нажаты во время захвата.   -  person Matthew Harrison    schedule 28.03.2018
comment
@ Yu-Yang Спасибо за предложения. Ваши изменения позволяют модели скомпилировать и начать работу, но не в TensorFlow-GPU. Я изучу свою текущую настройку и посмотрю, есть ли там проблема.   -  person Matthew Harrison    schedule 28.03.2018
comment
@ Yu-Yang По какой-то причине добавление уровня AveragePooling3D приводит к тому, что серверная часть TensorFlow выдает ошибку TypeError с сообщением, что avg_pool3d () получил неожиданный аргумент ключевого слова 'data_format'. Я передаю те же аргументы, которые вы указали. Может ли это быть дефектом Кераса или, скорее, это простая ошибка с моей стороны?   -  person Matthew Harrison    schedule 28.03.2018
comment
Похоже на несоответствие в версиях Keras и TF. Какую версию TF вы используете? Я тестировал 1.6 и 1.7, и они оба работают нормально. Может быть, вы можете попробовать обновить TF или понизить версию Keras?   -  person Yu-Yang    schedule 28.03.2018
comment
@ Yu-Yang Я использую Keras-GPU версии 2.1.5 и TensorFlow-GPU 1.1.0. Не могли бы вы уточнить, какой модуль какой версии в вашей среде?   -  person Matthew Harrison    schedule 28.03.2018
comment
Версия 1.1.0, вероятно, слишком устарела для Keras 2.1.5. Известно, что даже TF 1.4 имеет некоторую проблему с последними версиями Keras. Если вам сложно обновить TF, возможно, вы можете понизить Keras до 2.0.8 или даже более старых версий.   -  person Yu-Yang    schedule 28.03.2018
comment
У меня есть tensorflow==1.7.0rc1 (скомпилировано из исходного кода, поэтому имя пакета не содержит gpu) и Keras в последней основной ветке (установка pip из GitHub).   -  person Yu-Yang    schedule 28.03.2018
comment
Проблема заключалась в том, что я установил tenorflow-gpu и keras через conda, тогда как вместо этого я должен был использовать pip. Модель компилируется и запускается! У меня закончилась видеопамять, но проблема, для которой я открывал эту ветку, теперь решена.   -  person Matthew Harrison    schedule 28.03.2018
comment
@ Yu-Yang, пожалуйста, подумайте о том, чтобы переписать свои предложения в качестве ответа, чтобы я мог отдать вам должное за ваши усилия и чтобы любой, кто найдет эту ветку, мог увидеть решение.   -  person Matthew Harrison    schedule 28.03.2018
comment
Конечно. Я отправлю ответ.   -  person Yu-Yang    schedule 28.03.2018


Ответы (1)


Если вам нужен прогноз на каждый кадр, вам обязательно нужно установить return_sequences=True в вашем последнем ConvLSTM2D слое.

Для формы ValueError на целевой замените слой GlobalAveragePooling2D() на AveragePooling3D((1, 135, 240)) плюс Reshape((-1, 40)), чтобы сделать выходную форму совместимой с целевым массивом.

person Yu-Yang    schedule 28.03.2018
comment
Спасибо! Я пошел дальше и отредактировал свой вопрос, чтобы показать результат внедрения ваших изменений. - person Matthew Harrison; 28.03.2018