On se retrouve pour la deuxième partie du tutoriel sur le Deep Learning et Tensorflow. Après l’introduction rapide aux premiers principes du deep learning la dernière fois, nous continuons directement sur de la pratique avec Tensorflow.
Tensorflow est une API qui va venir se greffer sur un langage, ici Python. Elle permet de faciliter l’intégration des GPUs/TPUs dans les calculs mais aussi de fournir un environnement de haut niveau pour le deep learning. Dans la vidéo on expliquera son fonctionnement atypique par diagramme de flux de données avant de mettre nos connaissances actuelles en pratique pour faire notre tout premier modèle.
Le programme est expliqué en détail dans la vidéo, néanmoins il est aussi décrit, de manière plus brève, en dessous de la vidéo. Vous retrouverez aussi l’intégralité du code dans un bloc en bas de la page.
Rentrons donc dans ce code un peu plus en détail :
[python] import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) [/python]
Ici on appelle simplement Tensorflow et la base de donnée que l’on définit sous le nom de « mnist »
[python] def fcl(input,size_in,size_out): W = tf.Variable(tf.truncated_normal([size_in,size_out], stddev=0.1)) b = tf.Variable(tf.constant(0.1,shape=[1,size_out])) output = tf.matmul(input, W) output = tf.add(output, b) return output [/python]
Ensuite on définit une fonction permettant de créer une couche de neurones entièrement connectée.
Les paramètres de cette fonction sont : le flux de donnée entrant (input), la taille du flux (size_in) et la taille de la couche de neurones (size_out).
Il nous faut donc créer nos variables de poids (W) et de biais (b), qu’on initialise de manière aléatoire pour les premiers, et de manière constante pour les seconds. Avec des tailles correspondantes à ce que l’on recherche.
Enfin on crée la sortie (output), grâce à l’équation :
Output = Input*W + b
Maintenant il va nous falloir définir notre modèle, notre diagramme de flux de données puis l’entraîner.
[python] input_images = tf.placeholder(tf.float32, [None,784]) labels = tf.placeholder(tf.float32, [None,10]) [/python]
Ici nous définissons nos « placeholder », soit les portes d’entrées de nos flux de données. Les images entrantes ont une taille de 784px, soit la quantité de pixels d’images de 28×28, et pour les labels, une taille de 10, soit la quantité de chiffres.
On pourra remarquer la présence d’un « None », en taille d’entrée, cela permet de préciser que notre flux de donnée entrant (la quantité d’image entrant dans le réseau) peut avoir n’importe quelle taille.
[python] layer_1 = fcl(input_images,784,300) layer_1 = tf.nn.relu(layer_1) #max(x,0) layer_2 = fcl(layer_1,300,500) layer_2 = tf.nn.relu(layer_2) prediction = fcl(layer_2,500,10) [/python]
Ces lignes permettent de définir l’architecture du modèle. Composé de deux couches de neurones entièrement connectées avec respectivement 300 et 500 neurones.
Une fonction d’activation, ReLu, pour Rectified Linear Unit, est utilisée à la sortie de chacune des couches, permettant de réduire drastiquement l’erreur (d’un facteur 3). Elle consiste à utiliser la valeur du neurones si elle est positive, sinon la laisser à 0. (f(x)=max(x,0)
)
C’est la fonction d’activation la plus courante.
[python] erreur = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=prediction, labels=labels)) optimiseur = tf.train.AdamOptimizer().minimize(erreur) [/python]
Dans ces deux lignes, on définit l’erreur et le bloc d’optimisation de notre modèle, qui cherchera à minimiser cette erreur. L’erreur que l’on minimisera est donc la moyenne des erreurs sur la largeur de notre flux de données.
L’optimiseur utilisé est le AdamOptimizer, reconnu pour être très performant.
[python] predictions_correctes = tf.equal(tf.argmax(prediction,1), tf.argmax(labels,1)) accuracy = tf.reduce_mean(tf.cast(predictions_correctes, tf.float32)) [/python]
Enfin, pour finir la déclaration de notre modèle, il nous faut des variables permettant de récupérer la précision, la performance. Ainsi on récupère la valeur de véracité de nos prédictions en les comparant avec les réelles étiquettes de nos images, puis on en retire le pourcentage de précision.
Notre modèle est maintenant totalement défini, il ne reste plus qu’à l’entraîner.
[python] n_epochs = 10 batch_size = 1000 [/python]
Ces deux variables sont des variables sur la manière dont on va entraîner le réseau.
Le nombre d’epochs représente la quantité de passes sur les données d’entraînement que l’on va faire.
La taille du batch sera la taille, la largeur, du flux de données, qui va rentrer dans le diagramme, le modèle. C’est la quantité d’images en cours d’utilisation dans le modèle à un instant T. Cette valeur viendra remplacer les « None » des valeur d’entrée des placeholders définis plus haut.
Passons maintenant à la fonction qui entraînera notre modèle.
[python] def train(): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) flux_test = {input_images:mnist.test.images, labels:mnist.test.labels} precision = sess.run(accuracy, feed_dict=flux_test) print("\nPrecision:", precision*100, "Epoch:", 0) for epoch in range(n_epochs): for i in range(int(len(mnist.train.images)/batch_size)): flux_image, flux_labels = mnist.train.next_batch(batch_size) flux_train = {input_images:flux_image, labels:flux_labels} sess.run(optimiseur, feed_dict=flux_train) precision = sess.run(accuracy, feed_dict=flux_test) print("\nPrecision:", precision*100, "Epoch:", epoch+1) train() [/python]
La seconde ligne permet d’ouvrir une Session Tensorflow qui ouvrira un environnement dans lequel les opérations sur les tenseurs s’exécuteront.
On commence par initialiser nos variables, nos poids et biais.
Les trois prochaines lignes permettent d’observer la précision de notre modèle, qui pour le moment est totalement aléatoire (10%), car il n’est pas encore entraîné.
Ainsi on définit notre flux de données de test en créant un dictionnaire d’images de test et des étiquettes (labels) correspondantes.
On définit ensuite notre précision par l’exécution dans la session de la variable tensorielle « accuracy » en lui injectant notre flux de test.
Enfin on affiche simplement la précision.
Passons maintenant à l’entraînement du modèle.
On va définir deux boucles for imbriquées, pour générer notre mouvement à l’intérieur de notre base de données.
La première boucle représente le nombre de passage sur la totalité des images d’entrainement. Tandis que la deuxième boucle représente la quantité d’images que l’on va piocher dans la base de donnée à chaque fois, qui sera le flux de données.

De la même manière que nous avons défini le flux de test, on définit un flux d’entrainement de la taille du batch en prenant les images suivantes dans la base de données. Flux qui passera dans notre diagramme de flux de données pour entraîner le modèle.
Il nous faut donc lancer dans la session l’optimiseur en lui fournissant comme flux, le flux d’entrainement défini juste avant. Avec juste ceci le modèle s’entraînera !
Il ne manque plus qu’à récupérer la précision du modèle à chaque fin de passage (epoch) sur les données. On reprend donc la partie de code juste avant les boucles pour l’afficher, en précisant le nombre de passages actuel.
Voilà, la fonction d’entrainement est fin prêtre, finissons par simplement la lancer.
Le code est terminé, il ne reste plus qu’à l’exécuter et observer le résultat. Qui devrait se situer vers les 97% de précision.
Cela conclut la deuxième partie du tutoriel Tensorflow, si vous avez une quelconque question n’hésitez pas à nous contacter, via les commentaires sur la vidéo, ici, ou encore directement via notre Discord.
N’oubliez pas de regarder la vidéo qui va plus dans les détails des explications !
La prochaine fois nous verrons comment représenter ce réseau de neurones sous Tensorboard, pour mieux visualiser ce que nous venons de faire.
Voici la totalité du programme :
[python]
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) def fcl(input,size_in,size_out): W = tf.Variable(tf.truncated_normal([size_in,size_out], stddev=0.1)) b = tf.Variable(tf.constant(0.1,shape=[1,size_out])) output = tf.matmul(input, W) output = tf.add(output, b) return output input_images = tf.placeholder(tf.float32, [None,784]) labels = tf.placeholder(tf.float32, [None,10]) layer_1 = fcl(input_images,784,300) layer_1 = tf.nn.relu(layer_1) #max(x,0) layer_2 = fcl(layer_1,300,500) layer_2 = tf.nn.relu(layer_2) prediction = fcl(layer_2,500,10) erreur = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=prediction, labels=labels)) optimiseur = tf.train.AdamOptimizer().minimize(erreur) predictions_correctes = tf.equal(tf.argmax(prediction,1), tf.argmax(labels,1)) accuracy = tf.reduce_mean(tf.cast(predictions_correctes, tf.float32)) n_epochs = 10 batch_size = 1000 def train(): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) flux_test = {input_images:mnist.test.images, labels:mnist.test.labels} precision = sess.run(accuracy, feed_dict=flux_test) print("\nPrecision:", precision*100, "Epoch:", 0) for epoch in range(n_epochs): for i in range(int(len(mnist.train.images)/batch_size)): flux_image, flux_labels = mnist.train.next_batch(batch_size) flux_train = {input_images:flux_image, labels:flux_labels} sess.run(optimiseur, feed_dict=flux_train) precision = sess.run(accuracy, feed_dict=flux_test) print("\nPrecision:", precision*100, "Epoch:", epoch+1) train() [/python]