Укладка сверточной сети и рекуррентный уровень - PullRequest
0 голосов
/ 31 мая 2018

Я работаю над классификатором видео последовательностей.При вводе и выводе метки должно потребоваться несколько видеокадров, либо 0, либо 1. Итак, это сеть «многие к одному».

У меня уже есть классификатор для отдельных кадров.Этот классификатор делает несколько сверток с Conv2D, затем применяет GlobalAveragePooling2D.В результате получается 1D-вектор длиной 64. Тогда оригинальный классификатор для каждого кадра имеет слой Dence с активацией softmax.

Теперь я хотел бы расширить этот классификатор для работы с последовательностями.В идеале последовательности должны быть разной длины, но сейчас я фиксирую длину 4.

Чтобы расширить мой классификатор, я собираюсь заменить Dense слоем LSTM с 1 единицей.Итак, моя цель состоит в том, чтобы слой LSTM брал несколько одномерных векторов длины 64, один за другим, и выводил метку.

Схематично, что у меня сейчас:

input(99, 99, 3) - [convolutions] - features(1, 64) - [Dense] - [softmax] - label(1, 2)

Желаемая архитектура:

4x { input(99, 99, 3) - [convolutions] - features(1, 64) } - [LSTM] - label(1, 2)

Не могу понять, как это сделать с Keras.

Вот мой код для сверток

from keras.layers import Conv2D, BatchNormalization, GlobalAveragePooling2D, \
LSTM, TimeDistributed

IMAGE_WIDTH=99
IMAGE_HEIGHT=99
IMAGE_CHANNELS=3

convolutional_layers = Sequential([
    Conv2D(input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS),
           filters=6, kernel_size=(3, 3), strides=(2, 2), activation='relu',
           name='conv1'),
    BatchNormalization(),
    Conv2D(filters=64, kernel_size=(1, 1), strides=(1, 1), activation='relu',
           name='conv5_pixel'),
    BatchNormalization(),
    GlobalAveragePooling2D(name='avg_pool6'),
])

Вот сводка:

In [24]: convolutional_layers.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
conv1 (Conv2D)               (None, 49, 49, 6)         168
_________________________________________________________________
batch_normalization_3 (Batch (None, 49, 49, 6)         24
_________________________________________________________________
conv5_pixel (Conv2D)         (None, 49, 49, 64)        448
_________________________________________________________________
batch_normalization_4 (Batch (None, 49, 49, 64)        256
_________________________________________________________________
avg_pool6 (GlobalAveragePool (None, 64)                0
=================================================================
Total params: 896
Trainable params: 756
Non-trainable params: 140

Теперь я хочу, чтобы рекуррентный слой обрабатывал последовательности этих 64-мерных векторов и выводил меткудля каждой последовательности.

Я прочитал в руководствах, что слой TimeDistributed применяет свой входной слой к каждому временному срезу входных данных.

Я продолжаю свой код:

FRAME_NUMBER = 4

td = TimeDistributed(convolutional_layers, input_shape=(FRAME_NUMBER, 64))
model = Sequential([
    td,
    LSTM(units=1)
])

Результат - исключение IndexError: list index out of range

То же исключение для

td = TimeDistributed(convolutional_layers, input_shape=(None, FRAME_NUMBER, 64))

Что я делаю не так?

1 Ответ

0 голосов
/ 01 июня 2018

Расширение комментариев к ответу;слой TimeDistributed применяет данный слой к каждому временному шагу ввода.Следовательно, ваш TimeDistributed будет применяться к каждому кадру, дающему вход shape=(F_NUM, W, H, C).После применения свертки к каждому изображению вы получаете (F_NUM, 64), которые являются характеристиками для каждого кадра.

...