Dans cet article, les (mes) premiers pas pour prendre en main Tensorflow (1.15): installation, "hello world", quelques opérations arithmétiques de base et introduction aux, j'espère, principaux concepts et composants de Tensorflow.
Nous allons:
Pour ma part je suis en train de monter en compétence sur ce framework, et pour le moment,je suis très satisfait de cette procédure d'installation fournie par tensorflow.org et jouer avec l'outil en ligne de commande ou via des script python édités sous Vim. Cela changera certainement en m'attaquant à des exemples plus sophistoqués. Il y aura alors peut-être de nouveaux articles à ce moment.
Pour le reste de l'article, j'utiliserais un notebook Jupyter, et pour être honnête, l'installation a été un peu plus compliqué et je ne me souviens plus des détails. Je n'ai pas non plus envie de casser mon installation courante: pour suivre certains tutos, j'avais besoin d'une version spécifique de Keras avec tensorflow 1.13, j'ai effectué les installations via conda, mais pour le coup n'étant pas un wizard de Python, et étant habitué à Java et Maven, c'était juste très pénible.
foo@bar: virtualenv --no-site-packages tf-venv
foo@bar: source ./tf-venv/bin/activate
foo@bar: pip install tensorflow==1.15
foo@bar: python -c "import tensorflow; print(tensorflow.__version__)"
Dans cette section, nous allons exécuter un "hello world" et des opérations arithmétiques de base, introduire au passage des concepts et composants de base de Tensorflow, et prendre en main Tensorboard.
import tensorflow as tf
print(tf.__version__)
hello = tf.constant("Hello, world")
with tf.Session() as sess:
print(sess.run(hello))
Essayons d'expliquer ces 2 lignes de code: Nous avons défini une "Session", qui, comme l'indique la documentation, est un objet encapsulant l'environnement dans lequel des objets de type Operation sont exécutés, et des objets de type Tenseur sont évalués.
Ainsi, on a donc décrit ici un graphe avec une seule "operation", ou noeud, qui est une constante, dont la valeur est "hello world".
On exécute sess.run()
dans un with afin de s'assurer que la session est fermée à la fin du calcul.
Les opérations dans Tensorflow sont donc décrites sous la forme d'un graphe de calcul, où les noeuds sont les opérations et les données circulant entre les noeuds sont des tenseurs, d'où Tensorflow (malin Google).
On décrit le graphe de calcul simplement en créant des opérations.
On crée une Session
pour effectuer un calcul, calcul qui sera déclenché via la commande sess.run($nom_du_noeud)
.
Il est à noter que sess.run()
est "lazy", ainsi uniquement les noeuds du graphe qui sont nécessaires au résultat demandé sont éxécutés.
Par exemple, prenons le graphe suivant:
Que nous pourrions décrire avec les instructions suivantes
a=tf.constant(1)
b=tf.constant(3)
Add = tf.math.add(a,b)
c=tf.constant(5)
Mult = tf.math.multiply(Add,c)
une commande du genre sess.run(Add)
n'effectuerait pas l'opération de multiplication:
with tf.Session() as sess:
Add_result = sess.run(Add)
print(Add_result)
exécuter l'opération Mult exécute alors l'ensemble du graphe.
with tf.Session() as sess:
Mult_result = sess.run(Mult)
print(Mult_result)
On peut aussi consulter le graphe des opérations via l'outil Tensorboard. Inspectons le graphe ci-dessus des opérations arithmétiques dans Tensorboard
writer=tf.summary.FileWriter('toto', tf.get_default_graph())
writer.close()
!tensorboard --logdir="toto"
Intéressant de voir que l'on peut démarrer tensorboard depuis un notebook Jupyter :) !
Voici ce que l'on peut observer à l'url indiquée dans la sortie précédente:
On peut donc voir le graphe qui a été décrit précédemment. On peut nommer manuellement les noeuds si on le souhaite
a=tf.constant(1, name="a")
b=tf.constant(3, name="b")
Add = tf.math.add(a,b)
c=tf.constant(5)
Mult = tf.math.multiply(Add,c)
writer=tf.summary.FileWriter('toto', tf.get_default_graph())
writer.close()
!tensorboard --logdir="toto"
Il est intéressant de constater la sortie suivante:
W0114 05:52:20.973693 139813787256576 plugin_event_accumulator.py:294] Found more than one graph event per run, or there was a metagraph containing a graph_def, as well as one or more graph events. Overwriting the graph with the newest event.
En effet, la 2e fois, nous avons écrit le graphe dans le même répertoire que la 1e fois. Voyons ce que donne la sortie:
Ainsi en écrivant le graphe dans le même répertoire, on peut conserver les données des graphes d'exécutions précédentes.
Intéressant à savoir, voyons à l'avenir si cela est d'une quelconque utilité, ou au contraire si cela est une source d'ennuis.
Examinons 2 nouveaux concepts et composants de base de Tensorflow, les placeholders et les variables.
les placeholders sont l'équivalents des variables final
en java. Elles sont initialisées une seule fois, ensuite on ne peut pas modifier leur valeur.
Reprenons notre exemple arithmétique précédent en introduisant des placeholders.
a=tf.constant(1, name="a")
b=tf.placeholder(tf.int32, name="b")
Add = tf.math.add(a,b)
c=tf.constant(5)
Mult = tf.math.multiply(Add,c)
with tf.Session() as sess:
mult_res = sess.run(Mult)
print(mult_res)
ah, nous avons une erreur, en effet, nous n'avons pas initialisé le placeholder 'b'. Comme en java, si nous avions une varible final non-initialisée, sauf qu'en java on l'aurait su à la compilation, et pour ceux qui utilisent un IDE (qui n'en utilise pas ?!) l'ide nous l'aurait immédiatement signalé et aurait purement et simplement refusé d'exécuter notre code.
On initialise un placeholder dans la commande sess.run()
, avec un paramètre feed_dict
, qui est un dictionnaire Python classique, dans lequel les clés sont les noms des placeholders, et les valeurs sont les valeurs avec lesquelles ont les initialise.
a=tf.constant(1, name="a")
b=tf.placeholder(tf.int32, name="b")
Add = tf.math.add(a,b)
c=tf.constant(5)
Mult = tf.math.multiply(Add,c)
with tf.Session() as sess:
mult_res = sess.run(Mult, feed_dict={b:5})
print(mult_res)
Maintenant les variables. Les variables sont des tenseurs (article à venir à ce sujet) mutables, dont la valeur peut changer au cours du temps, contrairement aux constantes et placeholders, et qui sont recalculés à la demande.
a=tf.constant(2, name="a")
b=tf.Variable(1,tf.int32, name="b")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(5):
b = tf.math.multiply(a,b)
print(sess.run(b))
Il est important d'ajouter la ligne sess.run(tf.global_variables_initializer())
, autrement, nous nous retrouverions avec l'erreur suivante Attempting to use uninitialized value
:
a=tf.constant(2, name="a")
b=tf.Variable(1,tf.int32, name="b")
with tf.Session() as sess:
for i in range(5):
b = tf.math.multiply(a,b)
print(sess.run(b))
Voila pour