Neural Style (2/3) - Fast Forward!

Neural Style (2/3) - Fast Forward!

2017-03-16T00:00+02:00

Nous avions, dans un article précédent, décrit l'idée principale du célèbre Neural Style à partir de la publication originelle, A Neural Algorithm of Artistic Style - Leon A. Gatys; Alexander S. Ecker; and Matthias Bethge. Nous proposons aujourd'hui de continuer cette aventure en abordant une évolution déterminante de cette pratique par l'emploi de Fast Forward Networks. Au delà de l'historique, cette approche est intéressante à conserver en mémoire, car elle s'inscrit dans un objectif très particulier : la performance en déplaçant l'apprentissage sur un réseau qui sera ensuite exploité au runtime.

Neural style is too slow and too big...

En parcourant les issues du projet original, une même question revient sans cesse concernant la performance de l'algorithme. En effet, celui-ci impliquait de mettre en place tout un apprentissage pour chaque nouvelle image que l'on désire générer, ce qui rend caduc tout objectif d'utilisation temps réel ou même d'expérimentation poussée. De plus, dans la mesure où lors de son apprentissage, l'algorithme stockait en mémoire le réseau (d'où étaient extraites les fonctions de coût) et l'image, la consommation en mémoire de cet algorithme devenait énorme pour des images de résolution correcte, limitant drastiquement l'utilisation de cet algorithme pour des usages professionnels.

Arrive Texture Nets! Texture Networks: Feed-forward Synthesis of Textures and Stylized Images - Dmitry Ulyanov Vadim Lebedev Andrea Vedaldi Victor Lempitsky(https://arxiv.org/abs/1603.03417). Si cette publication vise en premier lieu à générer des textures crédibles et nouvelles à partir de photographie (qui était aussi un des enjeux de la publication originelle), elle propose aussi d'adapter sa démarche au Neural Style, avec un gain de temps hors du commun et des résultats largement comparables. L'ensemble des illustrations présentes dans ce post de blog sont issues de cette publication.

blog neural2 1 textures

Texture Nets

La solution exposée propose donc une approche radicalement différente. L'ancien algorithme mettait en oeuvre l'apprentissage sur l'image en cours de création et convergeait vers une image répondant suffisamment aux contraintes de contenu et de style imposées. Ici, il est proposé de mettre en oeuvre l'apprentissage d'un réseau dédié (et non plus d'une image cible) qui sera capable d'apprendre le style donnée en entrée et pourra ensuite être appliqué sur n'importe quelle image de contenu. Texture Nets propose donc d'apprendre des réseaux de neurones qui ensuite agiront comme des opérateurs de transformation de l'image à style constant. L'apprentissage de ce réseau est toujours assez long, mais une fois ce réseau généré, il peut transformer des images de taille libre extrêmement rapidement.

blog neural2 2 network

L'architecture du réseau ci-dessus reprend bien ce fonctionnement, ici pour la génération d'une texture. On retrouve à gauche le réseau de génération de l'image finale, qui en entrée prend un vecteur stochastique et en sortie génère la texture voulue. À droite, le réseau de type VGG chargé d'extraire les composantes de la fonction de coût (contenu, style & total variation) récupère cette texture pour permettre le suivi de l'apprentissage. Le schéma ci-dessus représente uniquement la phase d'apprentissage pour un style donné. On peut ici établir une corrélation avec les Generative Adversarial Networks, quand bien même dans ce cas de figure, le réseau chargé de générer la fonction de coût reste complètement statique au cours de l'entraînement.

Le réseau de gauche est une succession de couches convolutionelles suivies d'up-sampling (permettant d'augmenter la résolution des feature maps en cours de traitement) depuis l'ensemble des vecteurs de "bruit". On peut à ce stade signaler une solution élégante pour entraîner un réseau qui, par la suite, pourra recevoir des images de n'importe quelle résolution. En effet, l'input de ce réseau est un ensemble de vecteurs aléatoires (Zk) qui ont chacun une dimension double du vecteur précédent. Ce fonctionnement permet d'agréger différents niveaux de détail pour n'importe quelle résolution et reste facilement évolutif sur ce point. On note enfin qu'ici, ces variables Zk jouent un rôle de variable latente - que nous abordions dans l'article de blog consacré aux V.A.E.

Nous décrivons ici la génération de textures :

blog neural2 3 textures

Le passage de la génération de ces textures à la génération de style se fait assez rapidement en modifiant l'entrée du réseau lors de son entrainement comme lors de son utilisation. Au lieu de simplement fournir en entrée des échantillons Zk aléatoires, nous fournissons ces derniers accompagnés de l'image de contenu sur laquelle le style sera utilisé. Attention : là où l'image de style reste fournie pendant l'entraînement (et où de nombreuses images de contenu sont exploitées pour faire converger le réseau), l'image de contenu reste une variable du réseau pendant l'entraînement comme pendant son utilisation.

Résultats

Là où l'ancienne solution peinait énormément à créer une image, un réseau entraîné par Texture Nets génère une image en étant approximativement 500x plus rapide. L'utilisation de ces styles sur des applications temps-réel devient ainsi crédible. De même, la solution utilise beaucoup moins de mémoire que l'original (170MB pour générer un sample contre 1100MB pour la solution originale). Un code est disponible sur Github développé en Torch. Cette implémentation va au delà de la publication car elle implémente aussi dans le Neural Style des méthodologies développées dans Perceptual Losses for Real-Time Style Transfer and Super-Resolution - Justin Johnson; Alexandre Alahi; Li Fei-Fei des auteurs de la publication originale. Cette deuxième publication est assez similaire mais elle, par exemple, permet en oeuvre des opérations de super-résolution.