Les réseaux de neurones convolutionnels sont la famille la plus performante pour la classification et l’analyse d’images. Leurs applications ont franchi de nombreuses limites et constituent l’élément clé de bon nombre d’applications de deep learning que nous utilisons aujourd’hui. À haut niveau, les CNN apprennent des représentations internes de caractéristiques à partir des images qu’on leur fournit. C’est ce qui fait leur puissance. Il se trouve que cette propriété n’est pas seulement utile pour la classification d’images, mais aussi pour la synthèse d’images. Des applications comme Deep Dream et le transfert de style neuronal composent des images à partir des activations de couches dans des CNN et des caractéristiques qu’elles extraient.
Dans ce tutoriel, vous allez étudier le fonctionnement du transfert de style neuronal et voir comment l’implémenter avec TensorFlow 2.0.
Remarque : pour suivre ce tutoriel, vous devez comprendre le fonctionnement des CNN. Si vous cherchez une mise à niveau rapide, essayez les ressources suivantes :
Pour celles et ceux qui débutent en vision par ordinateur et en deep learning, le terme neural style transfer peut paraître intimidant. Pour en comprendre chaque composant, considérez les deux images suivantes :
Dans le contexte du transfert de style, l’image de gauche est appelée image de contenu et celle de droite image de style. L’objectif est de styliser une image (ici, celle de gauche) à partir d’une autre (celle de droite). C’est ce qui constitue les deux derniers mots du terme – style transfer. Pour réaliser ce processus, un réseau neuronal (CNN) est entraîné à optimiser une fonction de perte personnalisée : d’où le premier mot – neural. Lorsque les deux images ci‑dessus sont fusionnées par transfert de style, le rendu final ressemble à ceci (à droite) :
À quoi sert le transfert de style neuronal ? Imaginez que vous ayez l’image d’un dessin réalisé à l’origine par Vincent van Gogh. Vous souhaitez voir comment ce style se traduirait sur l’un de vos propres dessins. C’est un cas d’usage typique. Autre exemple : des applications de filtres photo comme Prisma, qui vous permettent de réaliser un transfert de style via une interface fluide.
Isoler contenu et style
Jusqu’ici, vous avez compris que le transfert de style consiste à combiner le contenu d’une image avec le style d’une autre. C’est tout à fait exact. Dans cette section, voyons ce que recouvrent précisément contenu et style dans le contexte des CNN.
Un CNN est souvent constitué de plusieurs couches convolutionnelles et de pooling. Les couches convolutionnelles extraient des caractéristiques très complexes d’une image donnée, tandis que les couches de pooling éliminent des informations spatiales détaillées qui ne sont pas pertinentes pour la classification. Cela aide le réseau à apprendre le contenu d’une image plutôt que des éléments spécifiques comme la couleur, la texture, etc. Plus on va en profondeur, plus la complexité des caractéristiques augmente ; les couches convolutionnelles profondes sont souvent appelées représentations de contenu.
Le style correspond à tout ce qui relève de propriétés spécifiques de l’image comme la texture, la couleur, etc. — par exemple l’usage prononcé d’une teinte particulière dans un tableau. Comment extraire le style d’une image ? En calculant des corrélations entre les cartes de caractéristiques des couches convolutionnelles. Les corrélations mesurent à quel point deux (ou plusieurs) variables sont liées. Considérez une couche convolutionnelle apprise composée de plusieurs cartes de caractéristiques : pour chacune, on peut mesurer à quel point les motifs détectés se rapprochent de ceux des autres cartes de la même couche. Cela renseigne sur des points comme : une couleur détectée sur la première carte est‑elle proche d’une couleur sur une autre ? Des formes sont‑elles communes entre cartes ? Ces traits/similarités définissent le style d’une image. Mesurer la similarité entre les contenus de plusieurs cartes au sein d’une couche aide le réseau à apprendre une représentation multi‑échelle centrée sur des aspects spatiaux comme la texture et la couleur.
Point essentiel : lors d’un transfert de style, il faut aussi veiller à préserver le contenu de l’image tout en y appliquant le style souhaité. Vous verrez plus loin comment procéder. Dans la section suivante, vous apprendrez à extraire les caractéristiques d’une image (de contenu) et à calculer la perte de contenu.
Quantifier l’image de contenu et calculer la perte de contenu
Selon Image Style Transfer Using Convolutional Neural Networks, on utilise une architecture VGG‑19 pour extraire à la fois les caractéristiques de contenu et de style des images correspondantes. Pour le contenu, la deuxième couche convolutionnelle du quatrième bloc est utilisée, notée conv4_2. Une fois ces caractéristiques obtenues, on les compare à une image cible pour mesurer la perte de contenu. Qu’est‑ce qu’une image cible ? Pourquoi calculer une perte de contenu ici ? Prenons du recul.
Pour combiner contenu et style dans une seule image, on part d’une image cible, qui est soit une image blanche, soit une copie de l’image de contenu. Pour apprendre efficacement contenu et style avec un CNN, on définit une fonction de perte personnalisée que l’on optimise afin d’obtenir une image stylisée harmonieuse construite à partir des images de contenu et de style. Cette perte est la combinaison de deux termes :
La perte de contenu, qui veille à ce que la quantité de contenu soit préservée.
La perte de style, qui contrôle la quantité de style transférée à l’image cible.
Revenons à la perte de contenu et définissons‑la. La perte de contenu mesure à quel point les caractéristiques des images de contenu et cible s’éloignent l’une de l’autre. Le réseau cherchera à minimiser cette perte. Dans la section suivante, vous verrez comment déterminer la perte de style.
La perte de style et la matrice de Gram
Pour déterminer la perte de style, l’article indique de prendre les représentations (des valeurs numériques) issues des couches suivantes et de calculer les matrices de Gram des cartes de caractéristiques correspondantes.
'conv1_1''conv2_1''conv3_1''conv4_1''conv5_1'Propulsé par
L’intérêt d’utiliser plusieurs couches pour définir la perte de style est d’apprendre une représentation multi‑échelle du style contenu dans une image. Les matrices de Gram évaluent la similarité des caractéristiques entre cartes au sein d’une même couche convolutionnelle. Elles capturent ainsi une information non localisée qui façonne le style de l’image. Une matrice de Gram se calcule ici de la manière suivante.
Supposons qu’une image convoluée ait la dimension 8×8×16, soit 16 cartes de caractéristiques. On cherche à mesurer les similarités entre ces cartes via une matrice de Gram. Pour cela, on aplatit les deux premières dimensions en un vecteur 1D : on obtient 64 entrées. On répète l’opération pour chaque carte. On obtient une matrice finale de dimension 16×64 (appelons‑la A). On transpose ensuite cette matrice (64×16) puis on la multiplie par A. La matrice de Gram résultante est de dimension 16×16. Chaque valeur indique la similarité entre deux cartes. Visuellement, ce processus ressemble à :
Pour calculer la perte de style entre l’image cible et l’image de style, on prend la moyenne des distances quadratiques entre leurs matrices de Gram à chacun des blocs convolutionnels. Formellement :
où T(s,i) est la matrice de Gram de l’image cible au bloc i et S(s,i) celle de l’image de style au bloc i. Avec wi, vous pouvez pondérer différemment les blocs pour une représentation de style plus fine. Enfin, $a$ est une constante qui tient compte des valeurs dans chaque couche des blocs. Mettons maintenant les deux pertes ensemble pour définir la perte totale optimisée durant le transfert de style.
Définir la perte totale
La perte totale est simplement la somme pondérée des deux termes :
où $\alpha$ est le poids du contenu et $\beta$ le poids du style. Cela vous permet d’équilibrer le contenu et la quantité de style transférée à l’image cible. L’effet de différentes combinaisons de $\alpha$ et $\beta$ est illustré dans l’article ; n’hésitez pas à le consulter. Vous avez désormais toutes les pièces pour implémenter le transfert de style neuronal. Passons à la pratique.
Transfert de style neuronal en pratique
Pour l’implémentation, vous utiliserez TensorFlow 2.0. Cette version apporte de nombreuses nouveautés majeures et constitue l’une des mises à jour les plus complètes de la bibliothèque à ce jour. Si vous souhaitez en découvrir quelques‑unes, consultez cet article.
La dernière version de TensorFlow (au moment de la rédaction) est 2.0.0-beta0. Si vous ne l’avez pas encore, installez‑la en suivant les instructions indiquées ici. Commencez par importer les packages nécessaires ainsi que les images de contenu et de style.
# Packagesimport tensorflow as tf
from tensorflow.keras.applications.vgg19 import preprocess_input
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(7)%matplotlib inline
print(tf.__version__)Propulsé par
# Load the content and style images
content = plt.imread('Content.jpeg')
style = plt.imread('Style.jpg')# Display the images
fig,(ax1, ax2)= plt.subplots(1,2, figsize=(20,10))# Content and style images side-by-side
ax1.imshow(content)
ax1.set_title('Content Image')
ax2.imshow(style)
ax2.set_title('Style Image')
plt.show()Propulsé par
À l’étape suivante, vous écrirez une fonction utilitaire qui charge les deux images en tableaux numériques (les ordinateurs ne manipulent que des nombres) et les redimensionne pour les rendre compatibles avec le modèle.
# Use load_image of content and style images
content = load_image('Content.jpeg')
style = load_image('Style.jpg')# Verify the shapes
content.shape, style.shape
Propulsé par
(TensorShape([1,400,400,3]),TensorShape([1,400,400,3]))Propulsé par
Les images sont redimensionnées. Vous allez maintenant charger un modèle VGG19 pré‑entraîné pour extraire les caractéristiques. Comme il sert uniquement d’extracteur, la partie classifieur n’est pas nécessaire.
vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet')
vgg.trainable =FalsePropulsé par
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5
80142336/80134624[==============================]- 5s 0us/step
Propulsé par
Les auteurs ont indiqué les noms de blocs utilisés pour extraire contenu et style. Le modèle VGG19 que vous venez de charger utilise la même convention. Pour en profiter, commencez par afficher les noms de toutes les couches du réseau.
# Print the layer names for conveniencefor layer in vgg.layers:print(layer.name)Propulsé par
Créez maintenant un VGG personnalisé composé des couches spécifiées. Vous pourrez ainsi faire des passes avant sur les images et extraire les caractéristiques nécessaires au passage.
defmini_model(layer_names, model):
outputs =[model.get_layer(name).output for name in layer_names]
model = Model([vgg.input], outputs)return model
Propulsé par
Définir une matrice de Gram est très simple dans TensorFlow :
# Gram matrixdefgram_matrix(tensor):
temp = tensor
temp = tf.squeeze(temp)
fun = tf.reshape(temp,[temp.shape[2], temp.shape[0]*temp.shape[1]])
result = tf.matmul(temp, temp, transpose_b=True)
gram = tf.expand_dims(result, axis=0)return gram
Propulsé par
Vous allez maintenant définir un modèle personnalisé via la fonction mini_model(). Il renverra les caractéristiques de contenu et de style à partir des images correspondantes.
classCustom_Style_Model(tf.keras.models.Model):def__init__(self, style_layers, content_layers):super(Custom_Style_Model, self).__init__()
self.vgg = mini_model(style_layers + content_layers, vgg)
self.style_layers = style_layers
self.content_layers = content_layers
self.num_style_layers =len(style_layers)
self.vgg.trainable =Falsedefcall(self, inputs):# Scale back the pixel values
inputs = inputs*255.0# Preprocess them with respect to VGG19 stats
preprocessed_input = preprocess_input(inputs)# Pass through the mini network
outputs = self.vgg(preprocessed_input)# Segregate the style and content representations
style_outputs, content_outputs =(outputs[:self.num_style_layers],
outputs[self.num_style_layers:])# Calculate the gram matrix for each layer
style_outputs =[gram_matrix(style_output)for style_output in style_outputs]# Assign the content representation and gram matrix in# a layer by layer fashion in dicts
content_dict ={content_name:value
for content_name, value
inzip(self.content_layers, content_outputs)}
style_dict ={style_name:value
for style_name, value
inzip(self.style_layers, style_outputs)}return{'content':content_dict,'style':style_dict}Propulsé par
Maintenant que le modèle personnalisé est défini, utilisons‑le sur les images pour obtenir les caractéristiques de contenu et de style :
# Note that the content and style images are loaded in# content and style variables respectively
extractor = Custom_Style_Model(style_layers, content_layers)
style_targets = extractor(style)['style']
content_targets = extractor(content)['content']
In the paper, optimization was done using the L-BFGS algorithm, but you can use Adam also.Propulsé par
opt = tf.optimizers.Adam(learning_rate=0.02)Propulsé par
Définissons maintenant les poids globaux de contenu et de style, ainsi que les poids propres à chaque représentation de style, comme évoqué plus haut. Remarque : ce sont des hyperparamètres, à ajuster selon vos besoins.
# Custom weights for style and content updates
style_weight=100
content_weight=10# Custom weights for different style layers
style_weights ={'block1_conv1':1.,'block2_conv1':0.8,'block3_conv1':0.5,'block4_conv1':0.3,'block5_conv1':0.1}Propulsé par
Vient maintenant la partie cruciale qui rend le processus de transfert de style particulièrement intéressant : la fonction de perte.
# The loss function to optimizedeftotal_loss(outputs):
style_outputs = outputs['style']
content_outputs = outputs['content']
style_loss = tf.add_n([style_weights[name]*tf.reduce_mean((style_outputs[name]-style_targets[name])**2)for name in style_outputs.keys()])# Normalize
style_loss *= style_weight / num_style_layers
content_loss = tf.add_n([tf.reduce_mean((content_outputs[name]-content_targets[name])**2)for name in content_outputs.keys()])# Normalize
content_loss *= content_weight / num_content_layers
loss = style_loss + content_loss
return lossPropulsé par
Vous allez maintenant écrire une autre fonction qui :
calcule les gradients de la fonction de perte que vous venez de définir ;
utilise ces gradients pour mettre à jour l’image cible.
Avec GradientTape, vous profitez de la différenciation automatique pour calculer les gradients d’une fonction selon sa composition. Vous utiliserez aussi le décorateur tf.function pour accélérer l’exécution. Plus d’informations ici.
@tf.function()deftrain_step(image):with tf.GradientTape()as tape:# Extract the features
outputs = extractor(image)# Calculate the loss
loss = total_loss(outputs)# Determine the gradients of the loss function w.r.t the image pixels
grad = tape.gradient(loss, image)# Update the pixels
opt.apply_gradients([(grad, image)])# Clip the pixel values that fall outside the range of [0,1]
image.assign(tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=1.0))Propulsé par
La seule étape restante avant l’entraînement est de définir l’image cible. Ici, nous utiliserons l’image de contenu.
epochs =10
steps_per_epoch =100
step =0for n inrange(epochs):for m inrange(steps_per_epoch):
step +=1
train_step(target_image)
plt.imshow(np.squeeze(target_image.read_value(),0))
plt.title("Train step: {}".format(step))
plt.show()Propulsé par
WARNING: Logging before flag parsing goes to stderr.
W0617 16:21:34.491543140709216896896 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1205: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops)is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in2.0, which has the same broadcast rule as np.where Propulsé par
Nous vous encourageons à tester différentes valeurs pour les poids de contenu et de style afin d’observer l’impact sur l’image cible.
Pour conclure
L’article de référence utilisé ici ne mentionne pas l’optimisation supplémentaire de la qualité de l’image générée. Comme on l’observe dans les résultats ci‑dessus, un certain lissage des relations spatiales entre contenu et style serait utile. Pour y remédier, on introduit la total_variational_loss, analogue à une régularisation. À haut niveau, la total_variational_loss pénalise les artéfacts haute fréquence introduits par l’algorithme original de transfert de style. Consultez ce tutoriel si vous souhaitez l’implémenter. Voici quelques ressources qui ont servi de références pour la rédaction :
L'essor du développement de l'intelligence artificielle (IA) a entraîné une augmentation notable de la demande en matière de calcul, d'où la nécessité de disposer de solutions matérielles robustes. Les unités de traitement graphique (GPU) et les unités de traitement tensoriel (TPU) sont devenues des technologies essentielles pour répondre à ces demandes.
Initiez-vous aux structures de données de Python : apprenez-en plus sur les types de données et les structures de données primitives et non primitives, telles que les chaînes de caractères, les listes, les piles, etc.
Apprenez à utiliser JSON en Python, notamment la sérialisation, la désérialisation, le formatage, l'optimisation des performances, la gestion des API, ainsi que les limites et les alternatives de JSON.
Les réseaux de neurones convolutionnels sont la famille la plus performante pour la classification et l’analyse d’images. Leurs applications ont franchi de nombreuses limites et constituent l’élément clé de bon nombre d’applications de deep learning que nous utilisons aujourd’hui. À haut niveau, les CNN apprennent des représentations internes de caractéristiques à partir des images qu’on leur fournit. C’est ce qui fait leur puissance. Il se trouve que cette propriété n’est pas seulement utile pour la classification d’images, mais aussi pour la synthèse d’images. Des applications comme Deep Dream et le transfert de style neuronal composent des images à partir des activations de couches dans des CNN et des caractéristiques qu’elles extraient.
Dans ce tutoriel, vous allez étudier le fonctionnement du transfert de style neuronal et voir comment l’implémenter avec
TensorFlow2.0.Remarque : pour suivre ce tutoriel, vous devez comprendre le fonctionnement des CNN. Si vous cherchez une mise à niveau rapide, essayez les ressources suivantes :
Qu’est-ce que le transfert de style neuronal ?
Pour celles et ceux qui débutent en vision par ordinateur et en deep learning, le terme neural style transfer peut paraître intimidant. Pour en comprendre chaque composant, considérez les deux images suivantes :
Dans le contexte du transfert de style, l’image de gauche est appelée image de contenu et celle de droite image de style. L’objectif est de styliser une image (ici, celle de gauche) à partir d’une autre (celle de droite). C’est ce qui constitue les deux derniers mots du terme – style transfer. Pour réaliser ce processus, un réseau neuronal (CNN) est entraîné à optimiser une fonction de perte personnalisée : d’où le premier mot – neural. Lorsque les deux images ci‑dessus sont fusionnées par transfert de style, le rendu final ressemble à ceci (à droite) :
À quoi sert le transfert de style neuronal ? Imaginez que vous ayez l’image d’un dessin réalisé à l’origine par Vincent van Gogh. Vous souhaitez voir comment ce style se traduirait sur l’un de vos propres dessins. C’est un cas d’usage typique. Autre exemple : des applications de filtres photo comme Prisma, qui vous permettent de réaliser un transfert de style via une interface fluide.
Isoler contenu et style
Jusqu’ici, vous avez compris que le transfert de style consiste à combiner le contenu d’une image avec le style d’une autre. C’est tout à fait exact. Dans cette section, voyons ce que recouvrent précisément contenu et style dans le contexte des CNN.
Un CNN est souvent constitué de plusieurs couches convolutionnelles et de pooling. Les couches convolutionnelles extraient des caractéristiques très complexes d’une image donnée, tandis que les couches de pooling éliminent des informations spatiales détaillées qui ne sont pas pertinentes pour la classification. Cela aide le réseau à apprendre le contenu d’une image plutôt que des éléments spécifiques comme la couleur, la texture, etc. Plus on va en profondeur, plus la complexité des caractéristiques augmente ; les couches convolutionnelles profondes sont souvent appelées représentations de contenu.
Le style correspond à tout ce qui relève de propriétés spécifiques de l’image comme la texture, la couleur, etc. — par exemple l’usage prononcé d’une teinte particulière dans un tableau. Comment extraire le style d’une image ? En calculant des corrélations entre les cartes de caractéristiques des couches convolutionnelles. Les corrélations mesurent à quel point deux (ou plusieurs) variables sont liées. Considérez une couche convolutionnelle apprise composée de plusieurs cartes de caractéristiques : pour chacune, on peut mesurer à quel point les motifs détectés se rapprochent de ceux des autres cartes de la même couche. Cela renseigne sur des points comme : une couleur détectée sur la première carte est‑elle proche d’une couleur sur une autre ? Des formes sont‑elles communes entre cartes ? Ces traits/similarités définissent le style d’une image. Mesurer la similarité entre les contenus de plusieurs cartes au sein d’une couche aide le réseau à apprendre une représentation multi‑échelle centrée sur des aspects spatiaux comme la texture et la couleur.
Point essentiel : lors d’un transfert de style, il faut aussi veiller à préserver le contenu de l’image tout en y appliquant le style souhaité. Vous verrez plus loin comment procéder. Dans la section suivante, vous apprendrez à extraire les caractéristiques d’une image (de contenu) et à calculer la perte de contenu.
Quantifier l’image de contenu et calculer la perte de contenu
L’algorithme de transfert de style neuronal a été présenté pour la première fois par Gatys et al. en 2015 : A Neural Algorithm of Artistic Style. Ce tutoriel s’appuie toutefois sur Image Style Transfer Using Convolutional Neural Networks, qui prolonge le premier article.
Selon Image Style Transfer Using Convolutional Neural Networks, on utilise une architecture VGG‑19 pour extraire à la fois les caractéristiques de contenu et de style des images correspondantes. Pour le contenu, la deuxième couche convolutionnelle du quatrième bloc est utilisée, notée
conv4_2. Une fois ces caractéristiques obtenues, on les compare à une image cible pour mesurer la perte de contenu. Qu’est‑ce qu’une image cible ? Pourquoi calculer une perte de contenu ici ? Prenons du recul.Pour combiner contenu et style dans une seule image, on part d’une image cible, qui est soit une image blanche, soit une copie de l’image de contenu. Pour apprendre efficacement contenu et style avec un CNN, on définit une fonction de perte personnalisée que l’on optimise afin d’obtenir une image stylisée harmonieuse construite à partir des images de contenu et de style. Cette perte est la combinaison de deux termes :
Revenons à la perte de contenu et définissons‑la. La perte de contenu mesure à quel point les caractéristiques des images de contenu et cible s’éloignent l’une de l’autre. Le réseau cherchera à minimiser cette perte. Dans la section suivante, vous verrez comment déterminer la perte de style.
La perte de style et la matrice de Gram
Pour déterminer la perte de style, l’article indique de prendre les représentations (des valeurs numériques) issues des couches suivantes et de calculer les matrices de Gram des cartes de caractéristiques correspondantes.
L’intérêt d’utiliser plusieurs couches pour définir la perte de style est d’apprendre une représentation multi‑échelle du style contenu dans une image. Les matrices de Gram évaluent la similarité des caractéristiques entre cartes au sein d’une même couche convolutionnelle. Elles capturent ainsi une information non localisée qui façonne le style de l’image. Une matrice de Gram se calcule ici de la manière suivante.
Supposons qu’une image convoluée ait la dimension 8×8×16, soit 16 cartes de caractéristiques. On cherche à mesurer les similarités entre ces cartes via une matrice de Gram. Pour cela, on aplatit les deux premières dimensions en un vecteur 1D : on obtient 64 entrées. On répète l’opération pour chaque carte. On obtient une matrice finale de dimension 16×64 (appelons‑la A). On transpose ensuite cette matrice (64×16) puis on la multiplie par A. La matrice de Gram résultante est de dimension 16×16. Chaque valeur indique la similarité entre deux cartes. Visuellement, ce processus ressemble à :
Pour calculer la perte de style entre l’image cible et l’image de style, on prend la moyenne des distances quadratiques entre leurs matrices de Gram à chacun des blocs convolutionnels. Formellement :
où T(s,i) est la matrice de Gram de l’image cible au bloc i et S(s,i) celle de l’image de style au bloc i. Avec wi, vous pouvez pondérer différemment les blocs pour une représentation de style plus fine. Enfin, $a$ est une constante qui tient compte des valeurs dans chaque couche des blocs. Mettons maintenant les deux pertes ensemble pour définir la perte totale optimisée durant le transfert de style.
Définir la perte totale
La perte totale est simplement la somme pondérée des deux termes :
où $\alpha$ est le poids du contenu et $\beta$ le poids du style. Cela vous permet d’équilibrer le contenu et la quantité de style transférée à l’image cible. L’effet de différentes combinaisons de $\alpha$ et $\beta$ est illustré dans l’article ; n’hésitez pas à le consulter. Vous avez désormais toutes les pièces pour implémenter le transfert de style neuronal. Passons à la pratique.
Transfert de style neuronal en pratique
Pour l’implémentation, vous utiliserez
TensorFlow 2.0. Cette version apporte de nombreuses nouveautés majeures et constitue l’une des mises à jour les plus complètes de la bibliothèque à ce jour. Si vous souhaitez en découvrir quelques‑unes, consultez cet article.La dernière version de
TensorFlow(au moment de la rédaction) est2.0.0-beta0. Si vous ne l’avez pas encore, installez‑la en suivant les instructions indiquées ici. Commencez par importer les packages nécessaires ainsi que les images de contenu et de style.À l’étape suivante, vous écrirez une fonction utilitaire qui charge les deux images en tableaux numériques (les ordinateurs ne manipulent que des nombres) et les redimensionne pour les rendre compatibles avec le modèle.
Les images sont redimensionnées. Vous allez maintenant charger un modèle VGG19 pré‑entraîné pour extraire les caractéristiques. Comme il sert uniquement d’extracteur, la partie classifieur n’est pas nécessaire.
Les auteurs ont indiqué les noms de blocs utilisés pour extraire contenu et style. Le modèle VGG19 que vous venez de charger utilise la même convention. Pour en profiter, commencez par afficher les noms de toutes les couches du réseau.
Voici celles qui nous intéressent pour les caractéristiques de style :
Pour le contenu, vous aurez besoin de
conv4_2. Enregistrons ces noms dans des variables.Créez maintenant un VGG personnalisé composé des couches spécifiées. Vous pourrez ainsi faire des passes avant sur les images et extraire les caractéristiques nécessaires au passage.
Définir une matrice de Gram est très simple dans TensorFlow :
Vous allez maintenant définir un modèle personnalisé via la fonction
mini_model(). Il renverra les caractéristiques de contenu et de style à partir des images correspondantes.Maintenant que le modèle personnalisé est défini, utilisons‑le sur les images pour obtenir les caractéristiques de contenu et de style :
Définissons maintenant les poids globaux de contenu et de style, ainsi que les poids propres à chaque représentation de style, comme évoqué plus haut. Remarque : ce sont des hyperparamètres, à ajuster selon vos besoins.
Vient maintenant la partie cruciale qui rend le processus de transfert de style particulièrement intéressant : la fonction de perte.
Vous allez maintenant écrire une autre fonction qui :
Avec
GradientTape, vous profitez de la différenciation automatique pour calculer les gradients d’une fonction selon sa composition. Vous utiliserez aussi le décorateurtf.functionpour accélérer l’exécution. Plus d’informations ici.La seule étape restante avant l’entraînement est de définir l’image cible. Ici, nous utiliserons l’image de contenu.
Vous êtes désormais prêt à entraîner le réseau.
Nous vous encourageons à tester différentes valeurs pour les poids de contenu et de style afin d’observer l’impact sur l’image cible.
Pour conclure
L’article de référence utilisé ici ne mentionne pas l’optimisation supplémentaire de la qualité de l’image générée. Comme on l’observe dans les résultats ci‑dessus, un certain lissage des relations spatiales entre contenu et style serait utile. Pour y remédier, on introduit la total_variational_loss, analogue à une régularisation. À haut niveau, la total_variational_loss pénalise les artéfacts haute fréquence introduits par l’algorithme original de transfert de style. Consultez ce tutoriel si vous souhaitez l’implémenter. Voici quelques ressources qui ont servi de références pour la rédaction :
Si vous souhaitez développer vos compétences en deep learning, découvrez ces cours et tutoriels DataCamp :