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

Qu’est-ce que le style transfer ? Comment cela fonctionne-t-il ? Comment en faire chez soi ? Cet article est là pour répondre à toutes ces questions, et pour vous guider pas à pas sur un exemple.

Le neural style, ou style transfer, a récemment fait son apparition, avec la publication d’un article en septembre 2015 [1]. Il émerge d’un contexte de fort développement des réseaux de neurones pour diverses applications, et notamment pour l’art. Quelques mois auparavant apparaissait le deep dream, programme faisant ressortir des patterns inexistants dans des images, créant ce qui pourrait être considéré comme un style artistique à part entière.

Le neural-style permet de récupérer le « style » d’une image et de l’appliquer sur une autre. Cela permet, avec quasiment aucun effort, de copier le style d’un grand maître pour l’appliquer sur la photo de son chat. Perspective fort intéressante !

Cet article couvrira un peu de théorie, puis décrira pas à pas l’installation puis le transfert d’un style vers notre Tux chéri (figure 1).

Fig. 1 : Tux modifié en utilisant comme style une image glanée sur une banque d’images libre de droits [2].

1. Un peu de théorie

Commençons par un peu de théorie : réseaux de neurones, deep learning, transfert de style et lien avec le deep dreaming.

1.1 Réseaux de neurones

Les réseaux de neurones sont une structure algorithmique copiant très schématiquement le fonctionnement de neurones dans le cerveau. Chaque neurone réalise une opération mathématique donnée, produisant ou non une sortie en fonction d’une valeur seuil qui lui est propre. Les réseaux peuvent avoir une immensité de topologies différentes, et les liens entre leurs neurones peuvent avoir des poids différents (appelés « poids synaptiques »).

Étant donnée la quantité de variables en jeu, la principale difficulté dans l’utilisation d’un réseau de neurones consiste en le choix de la valeur de ces variables. Différentes méthodes ont été testées pour apprendre automatiquement ces valeurs depuis l’apparition des réseaux de neurones dans les années 50. C’est l’efficacité des réseaux multi-couches (deep learning ou apprentissage profond) qui font le succès des réseaux de neurones depuis 2010.

1.2 Deep learning

L’idée du deep learning (apprentissage profond) est de structurer les tâches en couches reliées les uns aux autres, réalisant des opérations de niveaux d’abstraction différents. Par exemple, un réseau de reconnaissances d’images pourra être constitué d’une couche travaillant sur les pixels, reliée à une couche reconnaissant des bordures simples, elle-même reliée à une couche reconnaissant des motifs, puis des parties d’objets, puis des objets, etc.

Si le deep learning est aussi populaire en ce moment, c’est pour une raison simple : alors que l’on pensait jusqu’alors que l’avenir de l’intelligence artificielle passerait par l’enseignement d’heuristiques aux systèmes d’intelligence artificielle, on s’est rendu compte qu’avec une structure appropriée et une puissance de calcul suffisante, de telles structures étaient capables de découvrir les heuristiques par elles-mêmes. Mieux, elles pouvaient le faire parfois mieux que les humains ! On a ainsi vu un tel système battre un des plus grands maîtres du jeu de go, alors qu’une telle perspective semblait éloignée d’encore au moins quelques dizaines d’années.

En tant que système multi-couches, le deep learning est particulièrement sujet à la diversité des topologies possibles. Pour le transfert de style, le principal réseau utilisé se nomme VGG (Visual Geometry Group). Il s’agit d’un réseau de 16 couches de neurones (ou 19, selon la version), connu pour obtenir de bons résultats en reconnaissance d’image.

1.3 Transfert de style

Dans un article publié en septembre 2015, des chercheurs de Tübingen et de Houston ont introduit un algorithme utilisant du deep learning pour créer des « images artistiques de haute qualité perceptuelle ». Leur article introduit l’idée que la représentation du style et du contenu peuvent être séparés dans un certain type de réseau de neurones. Cela a lancé la voie du transfert de style, rapidement étendu et amélioré par d’autres articles : gain de vitesse, application au son ou à la vidéo, etc.

Pour parvenir à cette prouesse, les auteurs de l’article construisent un réseau capturant les informations de texture d’une image, mais pas l’organisation des éléments de celle-ci. Une fois ces informations de texture mémorisées dans un réseau, il est possible de les appliquer sur une image différente.

Le transfert de style est un problème d’optimisation : on cherche à appliquer un modèle précalculé (le style) sur une image. Pour cela, on définit une fonction objectif (loss function) qu’on cherche à minimiser. Il s’agit d’une somme pondérée de l’erreur (loss) entre l’image originale et l’image produite et de l’erreur entre le style original et celui appliqué. En jouant sur les paramètres de la pondération, on peut donc donner plus d’importance à l’image originale ou au style utilisé (cf. section 5).

1.4 Différences avec le deep dream

Le deep dream a été présenté dans un article de juillet 2015 par des chercheurs de Google. Antérieur à l’article précédent, il introduit l’idée de la génération d’images à but artistique par des réseaux de neurones profonds.

L’idée est ici plus simple : il s’agit de lancer « à l’envers » un réseau de neurones entraîné à reconnaître des images spécifiques. Le but est de produire en sortie l’image originale modifiée de telle sorte que l’on voie les endroits où le réseau « pense » reconnaître lesdites images. Cela produit des sortes d’hallucinations visuelles comparables à celles obtenues par un cerveau humain sous drogue psychédélique. On obtient ainsi une image étrange, où des formes inexistantes se dessinent sur les structures de l’image originale.

En faisant tourner l’algorithme plusieurs fois à partir de bruit, on obtient une représentation stylisée et combinée des objets que le réseau a été entraîné à reconnaître.

Le réseau de neurones utilisé pour l’article susnommé ayant été entraîné sur des images de chiens, de fractales colorées et de pagodes, on retrouve souvent des images hallucinantes contenant des chiens et des pagodes de façon colorée. Il est évidemment possible d’entraîner des réseaux sur de nouvelles images pour halluciner des choses différentes (pourquoi pas des tux ?).

La figure 2 montre le résultat d’un tux passé au filtre du Deep Dreaming.

Fig. 2 : Tux modifié avec le Deep Dream.


Nous n’étudierons pas plus en détail le deep dream dans cet article, car il y a tellement de choses à faire avec (notamment en jouant avec les différentes couches) que cela pourrait constituer un article à part entière !

Notez que le transfert de style est parfois aussi appelé deep dreaming.

2. Options d’utilisation

Plusieurs méthodes, plus ou moins simples et rapides, permettent de générer des images avec transfert de style. Passons-les en revue.

2.1 Demande à Claude

Passons rapidement sur la méthode la plus simple : utiliser le cloud (aussi appelé « l’ordinateur de quelqu’un d’autre »). Il existe de nombreuses pages web et applications pour smartphone permettant de générer des images en neural-style. L’avantage évident de tels systèmes est qu’on évite toute la partie installation (et éventuel achat de matériel nécessaire). L’inconvénient, c’est qu’on ne contrôle pas les paramètres, et que l’on n’apprend rien ! Dans cet article, nous allons donc nous attacher à tout installer nous-mêmes, mais sachez que des solutions directes existent.

Après quelques tests, je constate que leur qualité est très limitée : certains ne fonctionnent pas, beaucoup demandent une inscription, d’autres ne permettent pas de choisir le fichier de style, d’autres encore se veulent être des réseaux sociaux à part entière. À vrai dire, ceux qui fonctionnent correctement [3] sont basés sur la version rapide de l’algorithme (dont je discute les limites plus bas) et ne permettent pas de choisir le style.

2.2 Chez soi c’est quand même mieux

Voyons donc comment installer un des outils permettant de faire du style transfer : neural-style. Les explications qui suivent (ainsi que toutes les installations de l’article) sont prévues pour Debian Stretch.

Il faut commencer par installer torch, un framework en lua utilisé entre autres pour manipuler des réseaux de neurones. Il faut télécharger la version prévue pour l’installation (et non pas la version de développement) :

Le script d’installation vous demandera si vous souhaitez qu’il ajoute un script à votre .bashrc. Acceptez, il sert à exporter des variables d’environnement pour que torch puisse s’exécuter correctement.

Pour vérifier que l’installation de torch est correcte, il suffit d’utiliser la commande th et de voir si cela ouvre un shell interactif.

Maintenant que torch est activé, on peut installer le reste des dépendances de neural-style :

Pour la dernière commande, un bug vis-à-vis des versions de protobuf peut être contourné en l’exécutant en root.

Ensuite, on clone le dépôt et on télécharge le modèle VGG, c’est-à-dire le schéma des réseaux de neurones. Celui-ci a le format des réseaux Caffe, un autre framework de deep learning.

Il ne manque qu’une chose : les images à utiliser ! Pour notre exemple, j’ai pris les images [4] et [5]. Voilà, normalement tout est bon pour lancer un calcul :

Les options utilisées parlent d’elles-mêmes :

  • -style_image : le chemin vers l’image dont on veut copier le style ;
  • -content_image : le chemin vers l’image sur laquelle appliquer le style ;
  • -output_image : le nom du fichier de sortie. Notez que l’extension que vous indiquez sera utilisée pour produire l’image dans le format correspondant ;
  • -print_iter : pour afficher une sortie à chaque itération (il y en a 1000 par défaut) ;
  • -gpu -1 : pour ne pas utiliser de GPU (nous allons voir cela dans les sections suivantes).

Au cours du calcul, le script enregistre les images intermédiaires toutes les 100 itérations, ce qui permet de se rendre compte du fonctionnement du système (figure 3). On peut aussi les utiliser pour créer un GIF animé !

Fig. 3 : Les étapes (toutes les 100 itérations) de la génération de l’image finale.

3. Accélération

Bon voilà, c’est bien joli tout cela, mais notre calcul précédent prend plus ou moins… 10 heures ! Il va falloir étudier les moyens disponibles pour l’accélérer.

3.1 GPU

Les GPU sont très utiles pour accélérer des calculs de réseaux de neurones, ceux-ci bénéficiant particulièrement du calcul massivement parallèle.

3.1.1 Choix de la carte

Pour le choix de la carte, notez que si les cartes Nvidia ont un meilleur rapport qualité/prix, les pilotes libres ne permettent pas d’utiliser CUDA (mais d’autres technologies équivalentes moins performantes). Privilégiez une carte particulièrement performante pour les calculs de basse précision, ceux-ci étant massivement utilisés dans les réseaux de neurones.

Il faut de plus installer un backend permettant le calcul parallèle : CUDA ou OpenCL. Le backend CUDA étant plus utilisé par la communauté, il est plus abouti et plus efficace en terme de calcul. Le backend OpenCL, quant à lui, a l’avantage d’être en licence libre (et donc plus facile à installer). Pour les cartes gérant CUDA (Nvidia), l’utilisation additionnelle du backend cuDNN permet un léger gain de performance, et surtout une meilleure gestion de la mémoire (ce qui permet de générer des images plus grandes).

Une carte graphique milieu de gamme (environ 300€) est adaptée pour générer des images de taille 512×512, mais sera quelque peu limitée pour aller au-delà (jusqu’à 800-900 pour une carte avec 6 Gio de mémoire, en fonction des images). Le facteur limitant est ici la mémoire de la carte, sachant que le swap n’est généralement pas possible en cas d’utilisation totale de cette mémoire (peu de cartes le gèrent). La consommation mémoire de l’outil est assez importante : 3.5 Gio avec les paramètres par défaut, 1 Gio en utilisant un backend moins consommateur de mémoire. La carte graphique utilisée doit en posséder au moins autant, puisqu’une insuffisance en mémoire rendra l’exécution impossible.

3.1.2 Installation

Pour faire du calcul sur GPU, quelques installations supplémentaires sont nécessaires, et dépendent de la carte choisie et du backend désiré.

Pour OpenCL, l’installation est a priori simple, mais je ne l’ai pas testée. Il faut d’abord installer les drivers correspondant à la carte graphique (qui dépendent du constructeur, cf. [6]), puis installer cltorch et clnn :

Dans le cas d’une carte Nvidia, installer CUDA et cuDNN est plus compliqué. Le module du noyau nécessite que les headers du noyau utilisé soient installés. On commence donc par les installer, avant de faire de même pour tous les paquets nécessaires. Les paquets lua cutorch et cunn ne compilent qu’avec des versions de gcc inférieures à 5. Il faut donc passer des flags pour que les bonnes versions soient utilisées (vérifiez vos versions de gcc et g++ avant cela). En résumé :

Toujours dans le cas d’une carte Nvidia, on peut optionnellement rajouter cuDNN, qui permet un léger gain de performances, et surtout une meilleure utilisation mémoire. cuDNN n’est pas packagé sur Debian, il faut le télécharger sur le site de Nvidia [7], après enregistrement. On l’installe ensuite comme un paquet normal, puis on installe la bibliothèque lua associée :

Si tout est bon après un redémarrage, on peut désormais lancer neural-style avec l’option gpu (0 signifie d’utiliser le GPU numéro 0, pas de la désactiver), avec cuDNN si on l’a installé :

Ou en utilisant OpenCL :

Et voilà, le calcul ne prend plus que quelques minutes !

3.2 TPU

Les réseaux de neurones utilisés dans le style transfer ont la particularité de nécessiter uniquement du calcul sur petits entiers (8 bits). Si les GPU possèdent de nombreux cœurs, ceux-ci sont inutilement puissants pour une telle application. Pour cette raison, Google a développé des puces spécialement dédiées à ce genre de calcul, appelées TPU (Tensor Processing Unit), et les utilise depuis un an dans ses datacenters. Ces puces permettraient un énorme gain de vitesse et de performance par watt.

Et là vous vous dites : « Mais c’est super ! Ça se trouve où ? ». Malheureusement, ces puces ne sont pas disponibles dans le commerce, et Google n’a pas annoncé vouloir les commercialiser.

Pour être exhaustif, notons qu’il existe d’autres processeurs destinés à accélérer les outils de machine learning en se spécialisant dans les opérations mathématiques de basse précision : FPGA, d’autres types d’ASIC… [8]

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

La seconde partie de cet article sera publiée prochainement sur le blog, restez connectés 😉

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 !