FR Tanagra Tensorflow Keras Python PDF
FR Tanagra Tensorflow Keras Python PDF
FR Tanagra Tensorflow Keras Python PDF
1 Objectif
Découverte des librairies de Deep Learning Tensorflow / Keras pour Python. Implémentation
de perceptrons simples et multicouches dans des problèmes de classement (apprentissage
supervisé).
« Deep learning », « Tensorflow », « Keras »… ouh là là, plus racoleur tu meurs. Bon, j’en ai
tellement entendu parler dernièrement, mes étudiants sont dans une telle attente par rapport à
ces techniques et technologies, que je me suis décidé à rédiger une série de cours sur le sujet
durant cet été. Et, comme d’habitude, quand je commence à m’intéresser à des algorithmes de
machine learning, je regarde d’abord les outils disponibles. Il ne sert à rien de développer des
enseignements sur des méthodes, fussent-elles extraordinaires, si elles ne sont disponibles dans
aucun logiciel. Elles sont de facto inutilisables.
Je souhaitais travailler sous Python, au moins dans un premier temps (un tutoriel pour R
viendra). Sur le podium des librairies récentes les plus populaires figurent Tensorflow, Sckit-
learn et Keras (« Top 20 – Python AI and Machine Learning Open Source Projects »,
KDnuggets Polls, Février 2018). J’avais écrit un petit guide sur « scikit-learn » qui m’avait
permis de cerner les réelles possibilité de Python en machine learning il y a un moment déjà
(« Python – Machine Learning avec scikit-learn », Tutoriel Tanagra, Septembre 2015). Reste à
explorer Tensorflow et Keras qui, ça tombe bien, sont clairement estampillés « deep learning »
si l’on se réfère aux documents disponibles sur le web.
Tensorflow est une bibliothèque open-source développée par l’équipe Google Brain qui l’utilisait
initialement en interne. Elle implémente des méthodes d’apprentissage automatique basées sur
le principe des réseaux de neurones profonds (deep learning). Une API Python est disponible.
Nous pouvons l’exploiter directement dans un programme rédigé en Python. C’est faisable, il
existe des tutoriels et des ouvrages à ce sujet. Pourtant, j’ai préféré passer par Keras parce que
le formalisme imposé par Tensorflow est déroutant au possible pour un néophyte. Découvrir de
nouveaux algorithmes devient vite rédhibitoire si on a du mal à se dépatouiller avec un outil que
nous sommes censés utiliser pour les mettre en application.
Keras est une librairie Python qui encapsule l’accès aux fonctions proposées par plusieurs
librairies de machine learning, en particulier Tensorflow. De fait, Keras n’implémente pas
nativement les méthodes. Elle sert d’interface avec Tensorflow simplement. Mais pourquoi
alors s’enquiquiner avec une surcouche supplémentaire direz-vous ? Parce qu’elle nous facilite
grandement la vie en proposant des fonctions et procédures relativement simples à mettre en
œuvre. Un apprenant qui a déjà assimilé les démarches types du machine learning, qui a pu
par ailleurs utiliser des librairies qui font référence telles que scikit-learn, ne sera pas dépaysé
lorsqu’il aura à travailler avec Keras. L’accès aux fonctionnalités de Tensorflow devenant
transparentes, il pourra se focaliser sur la compréhension des méthodes.
Ce tutoriel a pour objectif la prise en main des outils. Pour aller à l’essentiel, nous
implémenterons des perceptrons simples et multicouches dans des problèmes d’analyse
prédictive. Ayant déjà nos repères concernant ces méthodes (RAK, avril 2013), nous pourrons
nous consacrer pleinement à l’assimilation du mode de fonctionnement de Tensorflow / Keras.
Les supports de cours consacrés aux méthodes de Deep Learning suivront.
Il faut être très vigilant durant cette phase. Les problèmes d’installation sont vite arrivés. Il sera
difficile par la suite de faire la part entre les erreurs de configuration machine et les appels de
fonctions erronés.
Nous avions utilisé ce jeu de données précédemment (RAK, 2013 ; section 2). Il s’agit d’un
problème de discrimination binaire dans le plan. La frontière séparant les classes prend la forme
d’une parabole (Figure 1) :
0
0
neg pos
Recodage de la variable cible. Notre variable Y prend ses valeurs dans {pos, neg}…
#décompte des classes
print(pandas.value_counts(D.Y))
#un vecteur de 0
y = numpy.zeros(D.shape[0])
#vérification
print(numpy.sum(y))
La somme des valeurs est égale à 859.0. Elle correspond au nombre d’observations positives
de notre jeu de données.
#vérification
print(numpy.mean(yTrain),numpy.mean(yTest))
Architecture du réseau. Nous importons les classes Sequential et Dense pour définir notre
modèle et son architecture.
#keras
from keras.models import Sequential
from keras.layers import Dense
La classe Sequential est une structure, initialement vide, qui permet de définir un empilement de
couches de neurones (https://keras.io/getting-started/sequential-model-guide/) :
#instanciation du modèle
modelSimple = Sequential()
Note : Sequential parce que les couches de neurones vont être ajoutées séquentiellement.
Pour spécifier un perceptron simple, nous ajoutons une couche qui relie directement la couche
d’entrée (input_dim, nombre de neurones = nombre de variables prédictives) avec la couche de
sortie (units = 1, une seule sortie puisque la variable cible est binaire, codée 1/0), avec une
fonction d’activation sigmoïde (activation) :
#architecture
modelSimple.add(Dense(units=1,input_dim=2,activation="sigmoid")) #ou input_shape=(2,)
Note : Dense parce que tous les neurones de couche précédente seront connectés à tous les
neurones de la couche suivante.
… nous retiendrons surtout que notre perceptron est pourvu du biais (ou intercept) avec l’option
« use_bias : True » c.-à-d. un neurone qui prend systématiquement la valeur 1, ce qui évite à
l’hyperplan séparateur de passer nécessairement par l’origine.
Biais
a0
a1
X1
a2
X2
d(X) = a0 + a1 X1 + a2 X2
Avec l’application de la fonction d’activation sigmoïde, nous avons en sortie du neurone de la
couche de sortie
1
𝑔 (𝑑 ) =
1 + 𝑒 −𝑑
g(d) est une estimation de la probabilité conditionnelle P(Y = pos / X1, X2), déterminante dans
les problèmes de classement.
Estimation des paramètres du réseau sur l’échantillon d’apprentissage. Nous pouvons lancer
l’estimation des poids synaptiques (coefficients) du réseau à partir des données étiquetées.
epochs est le nombre maximum d’itérations ; batch_size correspond aux nombre d’observations
que l’on fait passer avant de remettre à jour les poids synaptiques.
L’évolution de l’apprentissage est affichée dans la console IPython. En ce qui me concerne, voici
les valeurs finales de loss = 0.6374 et accuracy = 0.6387. La similitude des valeurs est une
coïncidence pour notre exemple.
Une fois l’apprentissage finalisée, nous pouvons afficher les poids estimés :
#poids synaptiques
print(modelSimple.get_weights())
Nous obtenons :
#print(modelSimple.get_weights())
[array([[0.1563818],
[2.0969372]], dtype=float32), array([-1.3740215], dtype=float32)]
Tout l’enjeu est de pouvoir les replacer dans notre structure (Figure 2) : nous avons une matrice
avec deux lignes, il s’agit des poids reliant les 2 neurones de la couche d’entrée à la sortie ; le
biais est la valeur dans un vecteur à part (Figure 3).
Biais
-1.374
0.156
X1
2.096
X2
Ces poids sont assez similaires à ceux que nous avions avec Tanagra dans un précédent
tutoriel (RAK, 2013 ; page 5). Les structures de réseaux sont identiques, mais l’algorithme est
différent : Tanagra optimise l’erreur quadratique et s’appuie sur un gradient stochastique (une
approche incrémentale même, les poids sont recalculés au passage de chaque individu).
Remarque : Il est possible d’obtenir les scores d’appartenance, pour le scoring ou encore pour
l’élaboration de la courbe ROC, avec la commande predict_proba().
Nous utilisons les outils de la librairie scikit-learn pour calculer la matrice de confusion :
#matrice de confusion
from sklearn import metrics
print(metrics.confusion_matrix(yTest,predSimple))
[[227 58]
[121 94]]
Et le taux de reconnaissance :
#taux de succès
print(metrics.accuracy_score(yTest,predSimple))
Fonction d’évaluation. L’autre solution consiste à utiliser l’outil dédié de la librairie Keras.
#outil dédié
score = modelSimple.evaluate(XTest,yTest)
print(score)
Dans cette section, nous passons à un perceptron multicouche. Nous créons toujours une
structure Sequential, dans lequel nous ajoutons successivement deux objets Dense : le premier
fait la jonction entre la couche d’entrée (d’où l’option input_dim indiquant le nombre de variables
prédictives) et la couche cachée qui comporte (units = 3) neurones ; le second entre cette
couche cachée et la sortie à un seul neurone (units = 1). Nous avons une fonction d’activation
sigmoïde dans les deux cas.
#modélisation
modelMc = Sequential()
modelMc.add(Dense(units=3,input_dim=2,activation="sigmoid"))
modelMc.add(Dense(units=1,activation="sigmoid"))
Biais
Biais
X1
X2
#apprentissage
modelMc.fit(XTrain,yTrain,epochs=150,batch_size=10)
#poids synaptiques
print(modelMc.get_weights())
Nous avons une première matrice 2 lignes (parce que 2 neurones dans la couche d’entrée) et 3
colonnes (parce que 3 neurones dans la couche intermédiaire) ; un vecteur avec 3 valeurs (lien
entre le biais de la couche d’entrée et les 3 neurones de la couche cachée) ; une matrice avec
3 lignes (3 neurones de la couche cachée) et 1 colonne (1 neurone de la couche de sortie) ; et
enfin un vecteur avec une valeur (lien entre le biais et la couche de sortie) (Figure 5).
Biais
-0.79
Biais 1.52
-7.19
0.35
1.30
-1.91
10.63
-2.77
-3.28
X1
-1.95
11.52
4.75
X2
2.24
4.1 Données
Recodage de la variable cible. Keras ne sait pas manipuler directement une variable cible
multivaluée. Il faut la transformer en une série d’indicatrices 0/1. Dans notre cas, « cultivars »
prend ses valeurs dans {1, 2, 3}, il faudra donc produire 3 variables binaires, une pour chaque
classe.
Notons qu’il a fallu tout d’abord ramener la cible dans {0, 1, 2} avant de procéder à l’appel de
la procédure. Voici les 5 premières lignes de la matrice de dimension (178, 3) :
[[1. 0. 0.]
[1. 0. 0.]
[1. 0. 0.]
[1. 0. 0.]
[1. 0. 0.]]
fit_transform() calcule tout d’abord les paramètres de la transformation (les moyennes et écarts-
type pour chaque variable), puis l’applique sur ces mêmes données XTrain.
Modélisation. Nous instancions un perceptron simple pour notre étude. Nous l’appliquons sur
nos données d’apprentissage standardisées.
#keras
from keras.models import Sequential
from keras.layers import Dense
#instanciation du modèle
model = Sequential()
#architecture
model.add(Dense(units=3,input_dim=13,activation="sigmoid"))
#compilation - algorithme d'apprentissage
model.compile(loss="categorical_crossentropy",optimizer="adam",metrics=["accuracy"])
#apprentissage
model.fit(XTrainStd,yTrain,epochs=150,batch_size=10)
input_dim = 13 parce que 13 variables prédictives, units = 3 parce que 3 neurones (une par
classe) dans la couche de sortie. La fonction de perte « loss = categorical_crossentropy » est la
généralisation à la distribution multinomiale de la log-vraisemblance.
Nous avons…
[array([[ 0.625605 , -1.4449003 , -0.00824617],
[ 0.14056818, -0.5485751 , 0.62404203],
[ 0.84487724, -0.84564555, 0.43422145],
[-0.22156928, 0.8705117 , 0.04653621],
[ 0.56018865, -0.42105287, -0.02743064],
[ 0.67341274, 0.15105425, -0.44733304],
[ 0.17756191, 0.49981773, -0.21034321],
[-0.6545906 , 0.20898524, -0.12943994],
[ 0.28324762, 0.15685035, -0.06623794],
[ 0.68136525, -1.1478251 , 1.0142568 ],
[ 0.7295266 , 0.8817851 , -0.6588781 ],
[ 0.7156769 , -0.06721698, -0.98883486],
[ 1.4496145 , -1.5374287 , -0.35039604]], dtype=float32), array([-
1.0351434, -1.0276651, -1.569456 ], dtype=float32)]
…une matrice avec 13 lignes (13 neurones de la couche d’entrée) et 3 colonnes (3 neurones de
la couche de sortie) ; puis un vecteur avec 3 valeurs (lien entre le biais et les 3 neurones de la
couche de sortie).
Evaluation sur l’échantillon test. Pour appliquer le modèle sur l’échantillon test, il faudrait déjà
centrer et réduire les variables de ce dernier… mais en utilisant les moyennes et écarts-type
calculés sur l’échantillon d’apprentissage ! La dernière partie de la phrase est particulièrement
importante. En effet, l’échantillon test préfigure la population dans laquelle sera déployée le
modèle. Les observations sont considérées individuellement, indépendamment les uns des
autres. Par conséquent, calculer des paramètres sur l’échantillon test n’a pas de sens.
Pour la classe StandardScaler instanciée plus haut (section 4.2), nous utilisons la méthode
transform() :
#centrage-réduction des variables de l'échantillon test
#avec (!) les paramètres de l'éch. d'apprentissage
XTestStd = cr.transform(XTest)
Nous pouvons enfin faire appel à la procédure evaluate() pour mesurer les performances :
#évaluation
score = model.evaluate(XTestStd,yTest)
print(score)
5 Conclusion
Finalement Tensorflow / Keras sont des packages comme les autres. Une fois assimilé la
syntaxe des principales commandes, nous marchons sur des sentiers battus et rebattus. Le
mode opératoire n’a rien de sorcier. Maintenant que nous savons les utiliser, le véritable enjeu
sera de disséquer les différents algorithmes de machine learning proposés par Tensorflow :
quels sont leurs caractéristiques, quels types de problèmes résolvent-ils, dans quelles situations
telle ou telle approche s’applique le mieux, comment les paramétrer efficacement, etc. Hum ! ce
n’est pas le boulot qui va nous manquer pour les prochaines semaines…
6 Références
Keras : The Python Deep Learning Library (https://keras.io/).
Tensorflow : An Open-Source Machine Learning Framework for Everyone (https://www.tensorflow.org/).
(RAK, 2013) Ricco Rakotomalala, « Paramétrer le perceptron multicouche », avril 2013.
Karlijn Willems, « Keras Tutorial : Deep Learning in Python », May 2017 ;
https://www.datacamp.com/community/tutorials/deep-learning-python
Jason Brownlee, « Develop Your First Neural Network in Python With Kears Step-By-Step », May 2016.