Je veux prédire la prochaine image d'une vidéo (en niveaux de gris) étant donné N
images précédentes - en utilisant des CNN ou RNN dans Keras. La plupart des didacticiels et autres informations concernant la prédiction de séries chronologiques et Keras utilisent une entrée unidimensionnelle dans leur réseau, mais le mien serait en 3D (N frames x rows x cols)
Je ne suis actuellement pas vraiment sûr d'une bonne approche pour ce problème. Mes idées incluent:
Utilisation d'une ou plusieurs couches LSTM. Le problème ici est que je ne sais pas s'ils sont adaptés pour prendre une série d'images à la place d'une série de scalaires en entrée. La consommation de mémoire n'exploserait-elle pas? Si vous pouvez les utiliser: comment les utiliser dans Keras pour des dimensions supérieures?
Utilisation d'une convolution 3D sur l'entrée (la pile d'images vidéo précédentes). Cela soulève d'autres questions: pourquoi cela aiderait-il lorsque je ne fais pas une classification mais une prédiction? Comment puis-je empiler les couches de telle manière que l'entrée du réseau ait des dimensions (N x cols x rows)
et la sortie (1 x cols x rows)
?
Je suis assez nouveau pour les CNN/RNN et Keras et j'apprécierais tout indice dans la bonne direction.
Donc, fondamentalement, chaque approche a ses avantages et ses inconvénients. Passons en revue celles que vous avez fournies, puis d'autres pour trouver la meilleure approche:
LSTM
: L'un de leurs plus grands avantages est la possibilité d'apprendre un modèle de dépendance à long terme dans vos données. Ils ont été conçus pour pouvoir analyser de longues séquences comme par ex. discours ou texte. Cela peut également provoquer des problèmes en raison de paramètres numériques qui peuvent être très élevés. D'autres architectures de réseau récurrentes typiques comme GRU
peuvent résoudre ce problème. Le principal inconvénient est que dans leur standard (implémentation séquentielle), il est impossible de les adapter sur des données vidéo pour la même raison que les couches denses sont mauvaises pour les données d'imagerie - les charges de temps et les invariances spatiales doivent être apprises par une topologie qui est complètement pas adapté pour les attraper de manière efficace. Décaler une vidéo d'un pixel vers la droite peut complètement changer la sortie de votre réseau.
Une autre chose qui mérite d'être mentionnée est que l'entraînement LSTM
est considéré comme similaire à la recherche d'un équilibre entre deux processus de rivalité - trouver de bons poids pour un dense-like calculs de sortie et trouver une bonne dynamique de mémoire interne dans le traitement des séquences. Trouver cet équilibre peut durer très longtemps, mais une fois qu'il est trouvé - il est généralement assez stable et produit de très bons résultats.
Conv3D
: Parmi leurs plus grands avantages, on peut facilement trouver une capacité à capturer des invariances spatiales et temporelles de la même manière que Conv2D
Dans un cas d'imagerie. Cela rend la malédiction de la dimensionnalité beaucoup moins nuisible. D'un autre côté - de la même manière que Conv1D
Pourrait ne pas produire de bons résultats avec des séquences plus longues - de la même manière - un manque de mémoire pourrait rendre l'apprentissage d'une séquence longue plus difficile.
Bien sûr, on peut utiliser différentes approches comme:
TimeDistributed + Conv2D
: En utilisant un wrapper TimeDistributed
- on peut utiliser un convnet pré-entraîné comme par exemple Inception
image par image, puis analysez les cartes d'entités de manière séquentielle. Un avantage vraiment énorme de cette approche est la possibilité d'un apprentissage par transfert. Comme inconvénient - on peut y penser comme un Conv2.5D
- il manque une analyse temporelle de vos données.
ConvLSTM
: cette architecture n'est pas encore supportée par la dernière version de Keras
(le 6 mars 2017) mais comme on peut le voir ici elle devrait être fournie dans le futur . Il s'agit d'un mélange de LSTM
et Conv2D
Et il est préférable d'être empilé que Conv2D
Et LSTM
.
Bien sûr, ce n'est pas le seul moyen de résoudre ce problème, j'en mentionnerai un autre qui pourrait être utile:
TimeDistributed(ResNet)
puis la sortie est alimentée en Conv3D
avec un regroupement spatial multiple et agressif et finalement transformée par une couche GRU/LSTM
.PS:
Une autre chose qui mérite également d'être mentionnée est que la forme des données vidéo est en fait 4D
Avec (frames, width, height, channels
).
PS2:
Dans le cas où vos données sont réellement 3D
Avec (frames, width, hieght)
, Vous pouvez réellement utiliser un classique Conv2D
(En changeant channels
en frames
) en analyser ces données (qui pourraient en fait être plus efficaces sur le plan des calculs). Dans le cas d'un transfert d'apprentissage vous devez ajouter une dimension supplémentaire car la plupart des modèles CNN
ont été formés sur des données de forme (width, height, 3)
. On peut remarquer que vos données n'ont pas 3 canaux. Dans ce cas, une technique généralement utilisée consiste à répéter la matrice spatiale trois fois.
PS3:
Un exemple de cette approche 2.5D
Est:
input = Input(shape=input_shape)
base_cnn_model = InceptionV3(include_top=False, ..)
temporal_analysis = TimeDistributed(base_cnn_model)(input)
conv3d_analysis = Conv3D(nb_of_filters, 3, 3, 3)(temporal_analysis)
conv3d_analysis = Conv3D(nb_of_filters, 3, 3, 3)(conv3d_analysis)
output = Flatten()(conv3d_analysis)
output = Dense(nb_of_classes, activation="softmax")(output)
Après avoir fait beaucoup de recherches, je suis finalement tombé sur le exemple Keras pour le ConvLSTM2D
layer (déjà mentionné par Marcin Możejko), qui fait exactement ce dont j'ai besoin.
Dans la version actuelle de Keras (v1.2.2), cette couche est déjà incluse et peut être importée à l'aide de
from keras.layers.convolutional_recurrent import ConvLSTM2D
Pour utiliser cette couche, les données vidéo doivent être formatées comme suit:
[nb_samples, nb_frames, width, height, channels] # if using dim_ordering = 'tf'
[nb_samples, nb_frames, channels, width, height] # if using dim_ordering = 'th'