Transfert de style : et si Van Gogh peignait Tux ? – Partie 2/2

3.3 Fast neural network

Il existe une implémentation plus récente du style transfer permettant un calcul bien plus rapide. Celle-ci est basée sur un article d’octobre 2016 [9]. L’idée est de remplacer l’erreur (loss) « par pixel » par l’erreur « perceptuelle ». En d’autres termes, le système ne cherche plus à faire coller chaque pixel à l’image originale, mais calcule la perte à un niveau plus élevé, ce qui permet de mesurer plus finement la similitude « perçue » entre deux images. De plus, l’implémentation utilise une modification dans l’architecture du réseau qui permet également un gain de performance. Celle-ci se base sur un précalcul du modèle, qui peut alors être utilisé à faible coût pour être appliqué sur de nouvelles images.

Au niveau pratique, les modèles doivent donc être précalculés afin de pouvoir être utilisés. Une fois le projet précédent installé, il n’y a rien de nouveau à installer pour créer de nouvelles images en utilisant les modèles préinstallés (en fait, il y a même moins de dépendances). Il n’y a donc qu’à cloner le dépôt :

Vous pouvez à présent créer de nouvelles images avec les modèles existants :

Notez qu’avec cette implémentation, la création d’images utilisant des modèles existants ne prend plus qu’une minute sur CPU (et quelques secondes sur GPU !). L’entraînement de nouveaux modèles reste cependant extrêmement coûteux : 4 à 6 heures sur une carte graphique haut de gamme (on passe de 6 à 4,5h avec cuDNN). Il n’est donc pas vraiment envisageable d’entraîner de nouveaux modèles sur CPU…

Justement, voyons maintenant l’entraînement de nouveaux modèles. Pour cela, il y a encore 2-3 choses à installer : torch-hdf5 et python-h5py.

Pour entraîner un réseau, il faut de plus le faire sur une banque d’images. Il faut donc un tel jeu d’images, et le préparer pour créer un fichier .hdf5, qui contient des informations sur le contenu des images. On va utiliser le jeu de données COCO, une grosse base de données d’images variées. Celui-ci est composé d’un jeu d’entraînement de 13 Gio ainsi que d’un jeu de vérification de 6 Gio. Ce dernier sert à effectuer des passes de vérification du bon fonctionnement de l’entraînement du réseau sur des images différentes de celles du jeu d’entraînement.

Notez que l’exécution du script prend quelques heures. Il est a priori possible d’obtenir des résultats très similaires avec un sous-ensemble très réduit du jeu de données, mais cette étape n’est à exécuter qu’une seule fois de toute manière, et l’étape d’entraînement n’est pas accélérée par l’utilisation d’un jeu d’images plus petit.

Comme pour neural-style, on a besoin du réseau VGG pour entraîner notre modèle :

Si tout est bon, on peut commencer à entraîner notre nouveau modèle :

Si, comme c’est le cas à l’heure où j’écris ces lignes, vous obtenez cette erreur :

Voici une manière de la corriger :

  • installez le paquet libhdf5-serial-dev ;
  • modifiez le fichier hdf5-0-0.rockspec pour ajouter le dossier de localisation de hdf5.h à la commande cmake. Concrètement, remplacez la ligne :

par :

Puis relancez la commande d’installation :

On obtient le résultat visible en figure 4 :

Fig. 4 : Résultat obtenu avec fast-neural-style.


Comme je le disais plus haut, le résultat est bien moins intéressant qu’avec la version lente de l’algorithme. Cependant, l’image Tux est très « lisse » et « simple » . On obtient des résultats bien plus intéressants pour d’autres images : cf. figure 5 par exemple. Ce dernier est tout de même à mon goût moins intéressant que son équivalent neural-style (figure 6).

Fig. 5 : Une autre image avec fast-neural-style.

Fig. 6 : L’équivalent de l’image de la figure 5 avec le neural-style original.

4. Quelques conseils artistiques

Après quelques utilisations sur diverses images, voici les conseils que je peux donner pour obtenir des résultats intéressants :

  • Parfois, les fichiers d’étapes (cf. figure 3) sont plus intéressants que le résultat final (notamment les 200 premières itérations). Pensez aussi à essayer d’augmenter le nombre d’itérations si l’image finale n’est pas « terminée » (c’est-à-dire si les images d’étapes changent encore beaucoup dans les dernières centaines d’itérations).
  • Pour les styles, choisir des images de styles avec de nombreux détails, ou un style bien défini. Prendre un simple logo donne des résultats inintéressants (utiliser Tux ou le logo Debian comme image de style ne donne rien de bien).
  • Par défaut, les images sont générées avec une taille de 512 pixels pour son côté le plus grand. Cela donne des images assez petites, et surtout pixelisées. Agrandir l’image de résultat (avec l’option -image_size) augmente le niveau de détails en même temps que la netteté (pensez à l’option style_scale pour remédier à cela). Comme indiqué plus haut, il est cependant difficile d’augmenter beaucoup les tailles des images générées, puisque l’utilisation mémoire augmente de façon quadratique. La mémoire de la carte graphique est donc rapidement pleine, à moins d’en avoir plusieurs… Quant à l’option du calcul sur CPU (pour bénéficier d’une mémoire plus grande et de la possibilité de swaper), il est extrêmement lent : il m’a fallu 46h de calcul pour générer une image de 1024×682 pixels !
  • Notez qu’il est possible d’utiliser plusieurs styles à la fois avec neural-style, ce qui peut donner des résultats intéressants. Avec fast-neural-style, ce n’est pas possible.
  • L’outil fast-neural-style, s’il est plus rapide, donne des résultats moins intéressants. Comme le notent les auteurs de l’article, cette solution a tendance à produire des motifs répétitifs. À mon sens, le résultat est vraiment moins pertinent.

Il est possible de jouer avec les paramètres des outils. Étudions-en quelques-uns :

  • L’option style_scale permet d’appliquer le style avec une échelle plus ou moins grande. Varier ce paramètre peut donner une meilleure intégration du style dans le résultat final (voir figure 7).

Fig. 7 : Résultats obtenus en faisant varier l’option style_scale avec les valeurs suivantes : 0.1, 0.2, 0.5, 0.8, 1.5, 2.0 (valeur par défaut : 1.0). Les valeurs supérieures demandent trop de mémoire pour ma carte graphique de 6 Gio.

 

  • Les options content_weight et style_weight permettent de donner plus ou moins de poids au style ou à l’image originale dans la construction de l’image finale. Leurs valeurs par défaut sont respectivement 5 et 100. Les figures 8 et 9 montrent les résultats obtenus en faisant varier ces paramètres.

Fig. 8 : Résultats obtenus en faisant varier l’option content_weight avec les valeurs suivantes : 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 (valeur par défaut : 5).

Fig. 9 : Résultats obtenus en faisant varier l’option style_weight avec les valeurs suivantes : 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 (valeur par défaut : 100).

 

  • Ne pas hésiter à jouer avec tous les autres paramètres ! Les outils présentés en possèdent de nombreux, qu’il serait long de passer en détail. Par exemple, l’option -init image permet de démarrer le calcul à partir de l’image d’origine, plutôt que d’un bruit aléatoire. Cela donne un résultat moins déconstruit, plus proche de l’image originale (cf. figure 10).

Fig. 10 : Résultats obtenus en faisant varier l’option -init image (à gauche) au lieu de -init random (à droite).

5. Pour aller plus loin : la vidéo

Les images c’est bien. Quand elles bougent, c’est mieux ! Il existe plusieurs techniques différentes pour passer de l’image à la vidéo. Voyons-en une rapide, et une autre orientée vers un meilleur résultat.

5.1 En temps réel

L’outil précédent (fast-neural-style) est tellement rapide qu’il permet une exécution en temps réel sur une entrée vidéo. Et justement, il comprend un script permettant de faire cela. Pour l’utiliser, il faut installer quelques dépendances supplémentaires :

Pour lancer le script, il faut utiliser qlua et non plus th :

Le script s’occupe de chercher une entrée vidéo (webcam) et d’y appliquer le transfert de style en temps réel. Et voilà !

5.2 Stabilisée

Vous remarquerez cependant rapidement un défaut avec le script précédent : le style n’est pas appliqué identiquement à chaque image, ce qui donne une sorte de clignotement assez désagréable. Cela est dû au fait qu’étant initialisée avec des valeurs aléatoires, chaque image va converger vers un maximum local différent. Un article d’octobre 2016 [10] par des chercheurs de l’université de Freiburg a étudié la question pour corriger ce problème. Pour simplifier, ses auteurs proposent d’initialiser chaque image avec les valeurs de l’image précédente afin de conserver une certaine uniformité, et calculent en plus le flux optique, c’est-à-dire le mouvement apparent des objets prenant en compte le mouvement relatif de la caméra. Cela donne un résultat stable, bien qu’encore imparfait (on trouve entre autres des artefacts étranges dans le résultat et il reste des soucis de cohérence). Notez que cet algorithme utilise neural-style et non fast-neural-style, et est donc lent : j’ai mis environ 7 heures pour générer une vidéo de 10 secondes en 320×200.

Si vous avez déjà installé les dépendances des outils précédents (torch7, loadcaffe et CUDA), il n’y a plus qu’à cloner le dépôt et à télécharger deux outils, disponibles directement sous la forme de binaires. Ceux-ci servent à calculer le flux optique entre deux images.

Un script existe pour lancer l’outil avec les options par défaut :

Si on veut utiliser d’autres options pour le transfert de style, il faut décomposer le script : celui-ci découpe une vidéo en images, calcule le flux optique, lance le transfert de style sur chaque image, puis reconstruit la vidéo à partir des images générées. En bref :

Attention : comme auparavant, on se retrouve rapidement à court de mémoire si on utilise des images trop grandes. Il sera certainement nécessaire de réduire la taille des images lors de la conversion de la vidéo en images avec l’option -vf scale=<résolution> de ffmpeg.

6. File au zoo, fi !

Le développement du machine learning à des fins artistiques pose de nouveaux questionnements philosophiques. S’il y a quelques années, il était encore courant de penser que l’art resterait pour longtemps du domaine de l’humain, inaccessible par la machine, la publication du deep dream par des chercheurs de Google a balayé cette supposition d’un revers de main : une intelligence artificielle aurait créé un nouveau style d’art ! Évidemment, cette affirmation est à relativiser largement puisque c’est avant tout les chercheurs et non la machine qui ont créé cet art. Le style transfer va encore plus loin : une machine est désormais capable de copier le style d’un humain sur une nouvelle image. Incroyable !

La barrière est donc repoussée. On peut se réconforter en se disant que l’art consiste avant tout à créer quelque chose de nouveau en fonction du contexte, qui sache perturber, questionner et émerveiller le spectateur. Et ça, la machine en est toujours incapable, puisqu’elle doit nécessairement être guidée par un être humain. Pour l’instant. Mais pour combien de temps ? Le défi est lancé !

L’image de la fin

En note finale, remarquons que si le transfert de style fonctionne pour les images, rien ne l’empêche d’être possible pour d’autres arts, notamment la musique [11] et la danse [12]. À vos claviers !

Et pour finir, voici quelques images de tux modifié en utilisant quelques images et photos glanées sur divers sites proposant des images libres de droits. Imaginez ce qu’il est possible de faire en ne se limitant pas pour des questions de droit !

Fig. 11 : D’autres résultats avec des images de style différentes.


Célestin Matte
[Doctorant INSA Lyon (financé par la région Rhône-Alpes)]

Références

[1] GATYS L., ECKER A. et BETHGE M., « A neural algorithm of Artistic style », 2015 : https://arxiv.org/pdf/1508.06576v2.pdf
[2] Photo de Jeffrey Betts : http://finda.photo/image/11418
[3] Application Aristo : https://artisto.my.com/
[4] Photo de Jeffrey Betts : http://finda.photo/image/11418
[5] Image de Tux : https://commons.wikimedia.org/wiki/File:Tux.png
[6] Installation des drivers des cartes graphiques sous Debian : https://wiki.debian.org/fr/GraphicsCard
[7] cuDNN : https://developer.nvidia.com/rdp/cudnn-download
[8] Accélération des outils de machine learning : https://en.wikipedia.org/wiki/AI_accelerator
[9] JOHNSON J., ALAHI A. et LI F.-F., « Perceptual losses for real-time style transfer and super-resolution », ECCV 2016 : http://cs.stanford.edu/people/jcjohns/eccv16/
[10] RUDER M., DOSOVITSKIY A. et BROX T., « Artistic style transfer for videos », 2016 : https://arxiv.org/pdf/1604.08610.pdf
[11] Algorithmic Music Generation with Recurrent Neural Networks : https://www.youtube.com/watch?v=0VTI1BBLydE
[12] Generative Choreography using Deep Learning : http://peltarion.com/creative-ai

Retrouvez cet article (et bien d’autres) dans GNU/Linux Magazine n°202, disponible sur la boutique et sur la plateforme de lecture en ligne Connect !