0% ont trouvé ce document utile (0 vote)
22 vues41 pages

Initiation au Deep Learning en Python

Transféré par

pesdjock
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
22 vues41 pages

Initiation au Deep Learning en Python

Transféré par

pesdjock
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Initiation au Deep Learning : Des équations

mathématiques aux codes Python


Joël K Kazadi

To cite this version:


Joël K Kazadi. Initiation au Deep Learning : Des équa-
tions mathématiques aux codes Python. Master. Deep Learning,
[Link]
Congo-Kinshasa. 2023, pp.40. �hal-04304710�

HAL Id: hal-04304710


[Link]
Submitted on 24 Nov 2023

HAL is a multi-disciplinary open access L’archive ouverte pluridisciplinaire HAL, est


archive for the deposit and dissemination of sci- destinée au dépôt et à la diffusion de documents
entific research documents, whether they are pub- scientifiques de niveau recherche, publiés ou non,
lished or not. The documents may come from émanant des établissements d’enseignement et de
teaching and research institutions in France or recherche français ou étrangers, des laboratoires
abroad, or from public or private research centers. publics ou privés.
Initiation au Deep Learning : Des équations
mathématiques aux codes Python∗
Joël K. Kazadi†
November 8, 2023

Résumé

Ce guide d’initiation au Deep Learning présente les concepts fondamentaux


des réseaux de neurones artificiels. Il couvre les notions de vectorisation des
équations fondamentales d’un réseau de neurones, présente l’algorithme de
la descente du gradient en détails, et aborde la programmation des modèles
développés sous Python. Aussi, un accent particulier est mis sur la librairie
TensorFlow et son rôle dans l’entraı̂nement des réseaux à forte profondeur.

Mots-clés : Réseaux de neurones, Forward propagation, Backward propaga-


tion, TensorFlow.

Abstract

This introductory guide to Deep Learning focuses on the fundamental concepts


of artificial neural networks. It addresses the vectorization of the fundamen-
tal equations of neural networks, describes in detail the gradient descent algo-
rithm, and tackles the programming of models in Python. Special emphasis is
also laid to the TensorFlow library and its role in training deep neural networks.

Keywords: Neural networks, Forward propagation, Backward propagation,


TensorFlow.


J’exprime toute ma gratitude à Gradi L. Kamingu (PhD candidate, Operations and Decision Systems, Université
Laval, Canada) pour ses précieux commentaires sur les drafts préliminaires de ce document.

MSc. student in Statistics and Data Science, International University of Applied Sciences, Erfurt, Germany.
E-mail: [Link]@[Link], Tél: (+243) 898 297 768 / 824 548 764.
1 Introduction
“Deep learning is the future of artificial intelligence.”
Yann LeCun.

Imaginez un monde où les machines peuvent apprendre par elles-mêmes. Un monde où elles
peuvent comprendre l’univers qui les entoure et prendre des décisions en toute autonomie. Un
monde où les machines peuvent nous aider à résoudre les problèmes les plus complexes. Ce monde
est possible grâce au “Deep Learning”.

Le Deep Learning est une sous-branche du Machine Learning – qui lui même est une branche
de l’intelligence artificielle (AI) – qui utilise des réseaux de neurones artificiels afin d’apprendre à
partir de données. Les réseaux de neurones artificiels constituent l’un des algorithmes d’AI les plus
sophistiqués. Ils sont inspirés du fonctionnement du cerveau humain et sont capables d’apprendre
des modèles complexes à partir de grandes quantités d’informations.

Dans ce guide d’initiation, nous allons explorer les bases du Deep Learning. Nous commencerons
par une introduction au perceptron, le modèle de base des réseaux de neurones artificiels. Puis, nous
verrons comment combiner des perceptrons pour créer des réseaux de neurones plus complexes. En-
fin, nous apprendrons à coder de bout en bout nos réseaux de neurones en Python, à les entraı̂ner
avec la méthode de descente du gradient, et à évaluer leurs performances dans les exercices de
prédiction.

Afin de parcourir sans ambiguité le présent guide, le lecteur est supposé (i) maı̂triser le vocabu-
laire couramment employé en apprentissage supervisé, (ii) disposer d’un bon background en algèbre
linéaire, et (iii) avoir des connaissances en programmation sous le langage Python.

Vous pouvez lire ce guide parallèlement avec l’excellent ouvrage de Goodfellow et al. (2016) qui
fournit une bonne introduction au domaine du Deep Learning. Couvrant à la fois la théorie et la pra-
tique des algorithmes du Deep Learning, ce livre est considéré comme une lecture incontournable
pour quiconque souhaite acquérir une compréhension détaillée des outils du Deep Learning. Si vous
souhaitez approfondir vos connaissances dans ce domaine, vous pouvez vous référer au manuel de
Aggarwal (2018). Il couvre aussi bien les bases des réseaux de neurones artificiels que des sujets plus
avancés tels que (i) les réseaux de neurones convolutifs (CNNs) que l’on rencontre dans les applica-
tions de computer vision, et (ii) les réseaux de neurones récurrents (RNNs) que l’on rencontre dans
les applications de natural language processing.

` la fin de cette formation, vous devrez être capable de :


A

— Distinguer le Deep Learning du Machine Learning ;


´
— Ecrire les équations fondamentales d’un réseau de neurones artificiel ;

— Décrire l’algorithme de la descente du gradient ;

— Expliquer les concepts de “forward propagation” et “backward propagation” ;

— Programmer en Python un réseau de neurones quelconque avec la librairie NumPy ;

— Entraı̂ner un vrai modèle de Deep Learning avec la librairie TensorFlow.

2
2 Le perceptron
Nous débutons notre voyage dans l’univers du Deep Learning avec un modèle de réseau de neurones
élémentaire, à savoir le perceptron. Mais bien avant, il nous semble important de situer les réseaux
de neurones dans la grande famille des algorithmes du Machine Learning.

Le Machine Learning, c’est la facette statistique de l’intelligence artificielle. Il consiste à appren-


dre à une machine à réaliser des tâches de manière autonome en lui faisant étudier des exemples
de ces dernières, et ce, sans avoir été explicitement programmée à cette fin. Ces exemples sont
représentés par des données que l’on fournit à la machine afin qu’elle s’exerce à construire un modèle
statistique capable de généraliser toute autre information nouvelle. Parmi ces modèles statistiques,
on peut énumérer (i) la régression linéaire, (ii) la régression logistique, (iii) les arbres de décision, (iv)
l’algorithme des plus proches voisins, (v) l’algorithme Support Vector Machine, et (vi) les réseaux de
neurones.

On comprend que le Deep Learning est un domaine du Machine Learning qui se concentre ex-
clusivement sur un seul type de modèle, à savoir “les réseaux de neurones”. Tout comme le cerveau
humain, un réseau de neurones est composé de plusieurs neurones regroupés en couches et inter-
connectés entre-eux. Chaque neurone reçoit des entrées d’autres neurones, et calcule une sortie en
fonction de ces entrées. La sortie d’un neurone est ensuite transmise aux neurones de la couche suiv-
ante, et ainsi de suite. Plus il y a des couches et des neurones, plus le réseau est capable de résoudre
des problèmes à complexité élevée, tels que la reconnaissance faciale, la traduction automatique ou
le diagnostic médical.

Il est important de relever qu’un réseau comportant plusieurs couches et plusieurs neurones
nécessite qu’il lui soit fourni une très grande quantité de données pour son entraı̂nement, ce qui
peut simultanément accroı̂tre de manière exponentielle le temps de traitement. Il existe plusieurs
outils qui permettent de palier à ce dilemme, i.e. réduire le temps de traitement tout en conservant
la “profondeur” du réseau1 . Les librairies les plus populaires pour cette finalité sont PyTorch et
TensorFlow. Dans le cadre de ce guide, nous n’allons aborder que le deuxième outil, au regard de
sa facilité de codage. Mais il faut noter que le choix définitif de l’outil à utiliser dépend des besoins
spécifiques liés au projet et des préférences individuelles de chaque data scientist.

2.1 Formulation mathématique


Dans cette sous-section, nous allons présenter en langage mathématique un réseau à une couche et
un neurone. Ce modèle simpliste est connu dans la littérature sous le nom de “perceptron”. Il s’agit
d’un modèle de classification capable de séparer linéairement des classes de données. Il se présente
schématiquement de la manière suivante :

Vous avez sans doute compris qu’on parle de Deep Learning à cause de la “profondeur” du réseau de neurones à
1

construire (nombre de couches et de neurones à l’intérieur de ce réseau).

3
Figure 1: Perceptron

La Figure 1 représente un réseau qui prend en entrée des signaux xj , ∀j = 1, 2, . . . , m appelées


features (variables explicatives), lesquels sont agrégés au moyen de la fonction z(·) proportionnelle-
ment aux poids wj , puis sont transformés à l’aide de la fonction a(·) pour produire une sortie y
appelée target (variable à prédire). Le fonctionnement du neurone peut donc être décomposé en
deux étapes :

i Étape d’agrégation
Elle consiste à calculer la somme pondérée des entrées du neurone, à un biais près.

m
X
z(wj , b) = wj xj + b.
j=1

Dans le cas de notre perceptron, il y a deux variables explicatives, i.e. m = 2.

z(w1 , w2 , b) = w1 x1 + w2 x2 + b. (1)

La fonction d’agrégation dépend des coefficients de pondération des features et de la valeur du


biais, étant donné que ce sont ces paramètres qui déterminent le rôle de chaque variable ex-
plicative dans l’agrégation, i.e. rôle excitateur (poids positif) ou rôle inhibiteur (poids négatif).
Aussi, cette fonction permet de tracer la frontière de décision entre les classes de la variable
cible. L’équation de cette frontière linéaire s’écrit alors z(wj , b) = 0.

ii Étape d’activation
Une fois l’agrégation réalisée pour chaque exemple dans le dataset, il faudra convertir la
somme obtenue en un critère dichotomique à même de discriminer les classes de la variable de
sortie. C’est le rôle de la fonction d’activation. Elle s’écrit a = a(z) et peut prendre plusieurs
formes fonctionnelles2 . Puisque les résultats mathématiques qui seront établis ne sont pas
conditionnés par la forme fonctionnelle de la fonction d’activation, nous n’allons travailler
qu’avec la fonction logistique dans le cadre de ce guide.

1
a(z) = . (2)
1 + e−z

2
Les fonctions d’activation les plus couramment utilisées en Deep learning sont : (i) la fonction sigmoı̈de (logistique),
(ii) la fonction ReLU (Rectified Linear Unit), (iii) la fonction tanh (tangente hyperbolique), et (iv) la fonction Soft-Max.

4
Le but de la fonction d’activation, c’est d’associer à chaque prédiction une probabilité qu’un en-
registrement appartienne à la classe de référence de la variable cible. Au-dessus de la frontière
de décision (z > 0), la probabilité d’appartenance à la classe de référence est élevée, et vice-
versa en dessous de cette frontière (cf. Figure 2). Partant de ces probabilités, il devient possible
de prédire la classe d’appartenance d’un enregistrement au moyen de la règle ci-après :

(
1, si a ≥ 0.5
ŷ = (3)
0, autrement

Cette étape consiste à définir un seuil d’activation du neurone. Dans le cas de notre perceptron,
si la probabilité renvoyée par l’équation 2 est d’au moins 50%, alors le neurone va s’activer pour
retourner une sortie correspondant à la classe de référence de la variable cible, i.e. y = 1.

Figure 2: Agrégation et Activation


(b) Fonction logistique
(a) Frontière de décision

La Figure 2 présente le cas de prédiction de la variable cible y comportant deux classes : soit
l’objet est un cercle (y = 1), soit c’est un triangle (y = 0). En se basant sur les deux caractéristiques
x1 et x2 , il est possible de prédire la nature des objets (cercle ou triangle ?). Tout l’enjeu consiste
alors à trouver les paramètres wj et b pour lesquels les erreurs de prédiction sont les plus faibles
possibles. Pour ce faire, définissons une fonction-coût permettant de mesurer ces erreurs.
n
1X
L=− yi log(ai ) + (1 − yi ) log(1 − ai ), (4)
n i=1
où n dénote le nombre d’exemples présents dans le dataset (dans la Figure 2, n = 7). La variable
cible y est générée par une variable aléatoire Y distribuée suivant une loi de Bernoulli avec une
probabilité de succès égale à a(z), i.e. Y ∼ B(a) avec P(Y = y) = a(z)y × (1 − a(z))1−y . Ainsi,
la fonction-coût n’est rien d’autre que l’opposé de la log-vraisemblance de la variable aléatoire Y .
La stratégie à ce niveau consiste alors à minimiser la fonction-coût par rapport aux paramètres du
modèle. A ` cet effet, nous ferons recours à l’algorithme de la descente du gradient pour trouver les
paramètres optimaux. Cet algorithme permet de calculer itérativement les valeurs optimales des
paramètres du modèle en partant d’un point initial sur la fonction-coût, puis en suivant la direction
du gradient jusqu’à atteindre son minimum. En posant W = (wj , b), la valeur du paramètre W à
l’itération h est donnée par :

5
∂L
Wh = Wh−1 − α , avec α ∈ [0, 1], (5)
∂W W =Wh−1

où α désigne le taux d’apprentissage (learning rate). A


` chaque itération, l’algorithme prend
une petit pas dans la direction du gradient. Ce pas est exploité en utilisant le taux d’apprentissage
qui gouverne la vitesse de convergence vers le minimum global. Vous l’avez deviné, la fonction à
minimiser doit nécessairement être convexe, sinon la méthode de descente du gradient pourrait se
heurter à un minimum local !

A` ce stade, nous avons écrit toutes les équations fondamentales de notre perceptron. Il s’agit de
(i) la fonction d’agrégation, (ii) la fonction d’activation, (iii) la fonction-coût, et (iv) l’équation de la
descente du gradient. Résumons tout cela dans un système d’équations.


 z(W ) = w1 x1 + w2 x2 + b (fonction d’agrégation)






 1
a(z) = (fonction d’activation)



1 + e−z





1 Pn
L(a) = − yi log(ai ) + (1 − yi ) log(1 − ai ) (fonction-coût)


n i=1










 ∂L
Wh = Wh−1 − α (équation du gradient)



∂W

W =Wh−1

Dans ce système, la seule équation qui reste à manipuler, c’est celle de la descente du gradient.
Dans cette équation, l’on note la présence d’une dérivée partielle qu’il n’est pas possible de calculer
directement. En effet, L ne dépend pas explicitement de wj et b. Toutefois, en remontant jusqu’à
la première équation (la fonction d’agrégation), il est possible d’évaluer cette dérivée partielle au
moyen de la règle de dérivation en chaı̂ne.
∂L ∂L ∂a ∂z
= × × . (6)
∂W ∂a ∂z ∂W
W est un vecteur de format m + 1 composé des deux coefficients de pondération w1 et w2 ainsi
que du biais b. Il y a donc trois dérivées partielles de la fonction-coût à calculer, relativement à ces
trois paramètres présents dans notre modèle du perceptron. Chacune de ces trois dérivées partielles
sera calculée suivant la règle de dérivation en chaı̂ne. Dans l’équation 6, les deux premiers termes
∂L ∂a
et seront les mêmes pour les trois paramètres. Ils s’obtiennent de la manière suivante :
∂a ∂z
i Premier terme !
∂L 1 P yi 1 − yi
= − i −
∂a n ai 1 − ai

ii Second terme
∂a e−z
=
∂z (1 + e−z )2
1 e−z
= ·
1 + e−z 1 + e−z
1 + e−z
!
1 1
= −
1 + e−z 1 + e−z 1 + e−z
= a(1 − a)

6
Eu égard à ce qui précède, il devient possible de déduire les dérivées partielles de la fonction-coût
par rapport à chacun des trois paramètres du modèle.
∂L ∂L ∂a ∂z


 = × ×
∂w1 ∂a ∂z ∂w1









 ∂L ∂L ∂a ∂z
= × ×




∂w2 ∂a ∂z ∂w2



∂L ∂L ∂a ∂z



= × ×


∂b ∂a ∂z ∂b
Par substitution, on obtient :
! !
∂L 1 P yi 1 − yi

= − − ai (1 − ai ) xi1


 i



 ∂w1 n ai 1 − ai




 ! !
∂L 1 P yi 1 − yi


= − i − ai (1 − ai ) xi2
 ∂w2

 n ai 1 − ai




 ! !
∂L 1 P yi 1 − yi


= − − ai (1 − ai )



i
∂b n ai 1 − ai

Après quelques manipulations algébriques simples, on trouve en définitive :


∂L 1P


= (ai − yi )xi1
n i

∂w1









 ∂L 1P
= (ai − yi )xi2




∂w2 n i



∂L 1P



= (ai − yi )


∂b n i
Le système d’équations fondamentales du perceptron a été formé, et les gradients de notre algo-
rithme d’optimisation ont été dérivés. Dès lors, il ne nous reste plus qu’à coder toutes ces équations
sous Python pour évaluer la performance de notre modèle. Pour ce faire, nous ferons recours à la
librairie NumPy qui offre d’excellentes fonctionnalités de calcul numérique et d’algèbre linéaire.

NumPy est une bibliothèque Python qui fonctionne avec des objets de type array, i.e. des
“tableaux”. Lorsqu’un array est de dimension 1, il s’agit d’un vecteur. Lorsqu’il est de dimension 2,
on parle de matrice. Ainsi, avant de coder nos équations mathématiques en Python, il est nécessaire
de les réécrire sous un format compatible avec les objets array. C’est l’étape de la vectorisation.

7
2.2 Vectorisation des équations
En programmation, la vectorisation consiste à mettre les données à analyser dans des tableaux à
p-dimension (vecteurs et/ou matrices) afin d’effectuer des opérations mathématiques sur l’ensemble
de ces données. Rappelons notre système d’équations fondamentales et les gradients de l’algorithme
d’optimisation.

Système d’équations fondamentales Gradients de l’algorithme d’optimisation




 z(W ) = w1 x1 + w2 x2 + b
∂L 1P

 
(ai − yi )xi1

 
=
n i
 

 1 
 ∂w1
a(z) =

 

 
1 + e−z

 


 

  ∂L 1P
1P = (ai − yi )xi2

 L(a) = − yi log(ai ) + (1 − yi ) log(1 − ai )

 ∂w2 n i
n i

 


 

 
∂L 1P

 

 
= (ai − yi )
 

 ∂L 
∂b n i
Wh = Wh−1 − α



∂W

W =Wh−1

L’objectif poursuivi dans cette sous-section, c’est d’écrire ces deux groupes d’équations sous
forme matricielle. Pour y parvenir, réorganisons notre dataset sous forme de tableaux. Soient X la
matrice des features, y le vecteur target et W le vecteur des paramètres. On écrit alors :
   
x11 x12 1 y1  
 x21 x22 1
 
 y2 
  w1
n×(m+1) n×1
X =  ..
 .. ∈R
..  ,  ..  ∈ R
y=  et W = w2  ∈ R(m+1)×1 .
 
 . . .  . 
b
xn1 xn2 1 yn
Dès lors, le système d’équations fondamentales se réécrit sous forme vectorielle comme suit :




Z = X ·W où Z ∈ Rn×1





 1
où A ∈ Rn×1


 A =
1 + e−Z



(7)
1P


L = − y log(A) + (1 − y) log(1 − A) où L ∈ R1×1



n i








W = W − α · ∇L où ∇L désigne le Jacobien de la fonction-coût.

Le Jacobien est le vecteur des dérivées partielles de la fonction-coût par rapport aux paramètres
du modèle. Ceci implique que ∇L ∈ R(m+1)×1 (ici, m = 2). Tout ceci nous amène, en dernier ressort,
à vectoriser les gradients de l’algorithme d’optimisation, lesquels se rapportent intrinsèquement au
vecteur jacobien.
1 T
∇L = X · (A − y). (8)
n
Le système 7 représente les équations fondamentales du modèle vectorisées, et l’équation 8 les
gradients de l’algorithme d’optimisation vectorisés. Notons au passage que l’avantage de la vectori-
sation, c’est qu’elle permet de généraliser le problème à un nombre plus élevé de features, i.e. pour
m quelconque. Etant
´ donné que toutes nos expressions mathématiques ont été réécrites sous forme
matricielle, il est dès à présent possible de les coder en Python.

8
2.3 Programmation sous Python
Le système 7 et l’équation 8 seront codés en Python grâce à la librairie NumPy. Pour implémenter
de bout en bout notre modèle du perceptron, nous allons générer un dataset contenant n = 50 en-
registrements possédant chacun m = 2 caractéristiques avec une étiquette binaire y ∈ {0, 1}.

# Importation des librairies


import numpy as np
from sklearn . datasets import make blobs

# Generation d’un dataset fictif


X, y = make blobs ( n samples =50, n features =2, centers =2,
random state =0)

# Creation du vecteur unitaire pour le biais


unit vector = [Link]([Link] [0], int)
unit vector = unit vector . reshape (( unit vector .shape [0], 1))
# Reformatage de la matrice des features et du vecteur target
X = np. concatenate ((X, unit vector ), axis = 1)
y = y. reshape (([Link] [0], 1))

Le dataset a été généré grâce à la fonction make blobs() du package sklearn. Dans la
Figure 3, nous représentons les données générées sur un nuage de points habillés selon les classes
de la variable à prédire. Il en ressort que les deux classes sont linéairement sépérables, ce qui est
compatible avec le modèle du perceptron développé dans la sous-section 2.1.

from matplotlib import pyplot as plt


scatter plot = plt. scatter (X[:,0], X[:,1], c=y)
plt. xlabel (’Feature x1’)
plt. ylabel (’Feature x2’)
plt. legend ( ∗ scatter plot . legend elements (),
loc=’best ’, title=’Classes ’);

Figure 3: Espace des caractéristiques

9
Pour programmer le modèle du perceptron, le code Python sera structuré comme suit :

— Initialisation des paramètres comme point de départ de l’algorithme de la descente du gradient.

— Codage des équations fondamentales du modèle (cf. système 7).


´
— Evaluation du coût obtenu au niveau de l’itération en cours.

— Mise à jour des paramètres si la variation du coût à l’itération en cours n’est pas nulle.

— Répétition en boucle des deux dernières étapes jusqu’à minimiser la fonction-coût.

i Définition de la fonction d’initialisation


Elle permettra de fixer aléatoirement les paramètres initiaux de l’algorithme d’optimisation.
# Fonction d’initialisation
def initialize (X):
np. random .seed (6)
W = np. random .randn([Link] [1], 1)
return W

ii Définition des fonctions d’agrégation et d’activation


Elles permettront de retourner la probabilité qu’un enregistrement appartienne à la classe de
référence de la variable cible.
# Equations fondamentales
def model(X, W):
Z = [Link](W)
A = 1 / (1 + [Link](−Z))
return A

iii Définition de la fonction-coût


Elle permettra de calculer l’écart moyen entre les probabilités prédites et les vraies valeurs de
la variable cible.
# Fonction−cout
def log loss (A, y):
L=−1/len(y ) ∗ [Link] ((y ∗ [Link](A))+((1−y ) ∗ [Link](1−A)))
return L

iv Définition du vecteur jacobien


Il permettra de mesurer la variation de la fonction-coût par rapport aux paramètres obtenus
dans une itération donnée.
# Vecteur des gradients ( Jacobien )
def gradients (A, X, y):
J = 1/ len(y) ∗ [Link](X.T, (A − y))
return J

10
v Définition de la fonction de mise à jour
Elle permettra de rafraı̂chir les paramètres du modèle de sorte à minimiser les erreurs de
prédiction.
# Actualisation des parametres
def update (J, W, learning rate ):
W = W − learning rate ∗ J
return W

Après avoir codé toutes les équations en Python, procédons à présent au codage de l’algorithme
d’optimisation. Ce code permettra de visualiser l’évolution de la valeur du coût à travers les itérations,
et de retourner les valeurs optimales des paramètres du modèle. Le taux d’apprentissage dans
l’équation du gradient est fixé à α = 0.1 et le nombre d’itérations à H = 100.

# Algorithme d’optimisation
def perceptron (X, y, learning rate , n iterations ):

W = initialize (X)
L = []

for h in range( n iterations ):


A = model(X, W)
L. append ( log loss (A, y))
J = gradients (A, X, y)
W = update (J, W, learning rate )

[Link](L)
plt. xlabel (’Iterations ’)
plt. ylabel (’Cout ’)
[Link] ()

return W

# Entrainement du modele
W = perceptron (X, y, learning rate = .1, n iterations = 100)
print (W)

Table 1: Paramètres optimaux


Paramètres Valeurs optimales

w1 1.01641857
w2 -1.07049618
b 0.81282977

La Figure 4 indique l’évolution des erreurs effectués par le modèle dans son apprentissage à par-
tir des données. Le Tableau 1 reprend les valeurs optimales des paramètres du modèle de perceptron.
Maintenant que le modèle est entraı̂né, il peut servir à des fins de prédiction. Pour cela, nous allons

11
Figure 4: Courbe d’apprentissage

définir une fonction qui permettra de prédire la classe d’appartenance des enregistrements sur base
de la règle définie dans l’expression 3. Ensuite, nous calculerons la performance du modèle, i.e. sa
capacité à prédire fidèlement la classe d’appartenance d’un enregistrement étiquetté.

# Fonction de prediction
def predict (X, W):
A = model(X, W)
y pred = []
for i in range([Link] [0]):
if A[i] >= .5:
y pred . append (1)
else:
y pred . append (0)
return y pred

y pred = predict (X, W)

En Machine Learning, la performance d’un modèle est couramment évaluée au moyen d’un in-
dicateur appelé “accuracy”. L’accuracy est une métrique simple et intuitive à comprendre qui est
souvent utilisée par défaut pour évaluer les modèles de classification. Elle mesure la proportion
de prédictions correctes par rapport au nombre total de prédictions. Pour la calculer, on part d’un
tableau appelé “matrice de confusion”.

La matrice de confusion est un tableau à double entrée qui compare les classes réelles et les classes
prédites par un modèle d’apprentissage supervisé. Chaque ligne correspond à une classe prédite et
chaque colonne à une classe réelle. Une cellule donnée contient le nombre d’enregistrements de la
classe réelle qui ont été classés dans la classe prédite.

12
Table 2: Matrice de confusion
Valeurs observées
Classe A Classe B
Valeurs Classe A Vrais positifs (VP) Faux positifs (FP)
prédites Classe B Faux négatifs (FN) Vrais négatifs (VN)

# Matrice de confusion
def confusion matrix ( y true , y pred ):

y true = [Link]( y true )


y pred = [Link]( y pred )

n classes = np. unique ( y true ). shape [0]


confusion matrix = [Link] (( n classes , n classes ))

for i in range(len( y true )):


confusion matrix [ y true [i], y pred [i]] += 1

return confusion matrix

ConfusionMatrix = confusion matrix ( y true = y, y pred = y pred )


print ( ConfusionMatrix )

A` partir de la matrice de confusion, l’on peut évaluer la performance du modèle au moyen de la


formule 9. Cette métrique mesure le pourcentage de prédictions correctes effectuées par le modèle.
VP +VN
Accuracy = (9)
V P + FP + FN + V N

# Accuracy
def accuracy ( confusion matrix ):
diag = [Link]( confusion matrix , k = 0)
n correct = [Link] ()
n total = confusion matrix .sum ()
accuracy = n correct / n total
return accuracy

Acc = accuracy ( ConfusionMatrix )


print (Acc)

Pour le cas de notre perceptron, les résultats sont présentés dans le Tableau 3. Il en ressort que
quatre enregistrements n’appartenant pas à la classe de référence ont été prédits comme appartenant
à cette classe, et que deux enregistrements appartenant à cette classe ont été prédits comme n’y
appartenant pas. La performance globale de notre modèle du perceptron s’évalue ainsi à 88%.

13
Table 3: Matrice de confusion
Classes réelles
Accuracy : 88%
y=0 y=1
Classes y=0 V P = 23 F P = 2
prédites y=1 F N = 4 V N = 21

Pour clôturer cette partie, nous représentons à nouveau les données générées pour l’analyse
(l’espace des features) en y traçant la frontière de décision d’équation z(wj , b) = 0. A
` la lumière de
la Figure 5, l’on constate que les deux classes de la variable cible ont été linéairement séparées grâce
la droite z(wj , b) = 0. Aussi, l’on arrive à identifier visuellement les six enregistrements qui n’ont
pas été correctement prédits par le modèle.

# Frontiere de decision
scatter plot = plt. scatter (X[:,0], X[:,1], c=y)
plt. xlabel (’Feature x1’)
plt. ylabel (’Feature x2’)
plt. legend ( ∗ scatter plot . legend elements (),
loc=’best ’, title=’Classes ’)

x line = np. linspace (min(X[: ,0]) , max(X[: ,0]) , num = 100)


y line = −1/W[1] ∗ (W [0]∗ x line + W[2])
[Link]( x line , y line , c = ’red ’, lw = 3)

plt. annotate (’Frontiere \ nde decision ’, (−1,0), xytext = (−1.5,2),


arrowprops = dict( facecolor = ’black ’, width = .5),
fontstyle = ’oblique ’, weight = ’bold ’,
fontsize = 10, color = ’blue ’, alpha = .7)

Figure 5: Frontière de décision

14
3 Réseau artificiel à 2 couches
Dans la section 2, nous avons développé un modèle de réseau à une couche et un neurone. Ce modèle
est adapté pour des problèmes où les classes à prédire sont linéairement séparables. Cependant,
lorsqu’on sort de ce cadre, la performance du perceptron devient médiocre, car en réalité il s’agit d’un
modèle hautement simpliste. Dans cette section, nous allons enrichir ce modèle en l’augmentant
d’une couche supplémentaire, la première comportant deux neurones et la seconde un seul neurone.

Figure 6: Réseau de neurones artificiel

Les signaux situés à l’entrée du réseau forment la “couche source”, et les prédictions situées à la
sortie forment la “couche cible”. L’ensemble de neurones que l’on trouve à l’intérieur du réseau for-
ment les “couches masquées”. Ce sont ces couches qui permettent au modèle d’améliorer sa capacité
à se généraliser à de nouvelles données (pas de overfitting) et de pouvoir résoudre des problèmes de
Deep Learning plus complexes.

3.1 Formulation mathématique


Le fonctionnement du réseau de neurones artificiel proposé dans la Figure 6 se présente comme
[k]
suit. Les signaux d’entrée xj sont agrégés par la fonction zi associée au neurone i de la couche k,
[k]
moyennant des poids notés wij . Ces poids sont distincts d’un neurone à un autre, car les neurones ne
partagent pas les mêmes connexions provenant des signaux. Les valeurs obtenues à l’issue de chaque
[k]
agrégation sont ensuite transformées par la fonction d’activation ai présent dans le neurone i de la
[k]
couche k. Par la suite, les sorties des fonctions d’activation dans la couche k serviront d’entrée aj
[k+1]
pour l’agrégation dans la couche k + 1, moyennant des nouveaux poids notés wij . Le processus
d’agrégation-activation se poursuit ainsi jusqu’à la couche cible pour produire la classe de sortie
relative à la variable à prédire y. Ce processus s’appelle en Deep Learning la “forward propagation”.
Il consiste à faire circuler les données d’entrée du réseau de la première jusqu’à la dernière couche
afin de produire une sortie de la variable cible.

15
De ce qui précède, les équations de la forward propagation s’écrivent de la manière suivante :

i Fonction d’agrégation
m
[k] [k] [k−1] [k]
∀i ∈ {1, 2, . . . , p[k] } et ∀k ∈ {1, 2, . . . , q},
X
zi (wij , bi ) = wij aj + bi , (10)
j=1

où m dénote le nombre de signaux à l’entrée, p[k] le nombre de neurones présents dans la
couche k, et q le nombre de couches masquées qui constituent le réseau. Il faut noter que si
[0]
k = 1, alors aj = xj . Autrement dit, les entrées de la première couche sont les features de la
couche source, et celles des autres couches sont les activations des neurones précédents.

ii Fonction d’activation
[k] 1
ai (zi ) = [k] , ∀i ∈ {1, 2, . . . , p[k] } et ∀k ∈ {1, 2, . . . , q}. (11)
−zi
1+e

[k] [k]
Puisque chaque neurone dispose de ses propres paramètres wij et bi , leurs fonctionnements
seront indépendants les uns des autres, ce qui améliore in fine la puissance du modèle. Pour arriver
à implémenter un tel modèle, il est pratique de réécrire les équations qui le décrivent sous forme
matricielle, comme nous l’avons vu avec le perceptron dans la sous-section 2.2.

3.2 Vectorisation des équations


Soient A[k] ∈ Rn×(m+1) la matrice des signaux d’entrée à la couche k et y ∈ Rn×1 le vecteur des
classes à prédire. Dans un réseau contenant plus d’un neurone, les poids sont rangés dans une
matrice notée W [k] qui reprend les paramètres associés à la couche k du réseau.
 [k] [k] [k]

w w21 · · · wp1
 11
 w [k] [k] [k] 
w22 · · · wp2 
 12 
 . .. .. ..  (m+1)×p[k]
W [k] =  .
 . . . .  ∈R .
 [k] [k] 
[k] 
w
 1m w2m · · · wpm 
[k] [k]
b1 b2 · · · b[k]
p

Pour le cas du réseau proposé dans la Figure 6, p[1] = 2, et p[2] = 1. Dès lors, il devient possible
de réécrire les équations 10 et 11 comme suit.
[k]



 Z [k] = A[k−1] · W [k] , avec A[0] = X, où Z [k] ∈ Rn×p

(12)
 [k] 1 [k] n×p[k]
A = , où A ∈R


1 + e−Z [k]

` ce stade,
Le système 12 décrit le processus de la forward propagation en notation matricielle. A
on peut se poser la question suivante : “comment trouver les valeurs optimales des poids contenus
dans les matrices W [k] ” ? En d’autres termes, comment entraı̂ner le modèle construit de sorte à ce
que ses prédictions ne contiennent que très peu d’erreurs. Pour répondre à cette question, nous
suivrons la même stratégie que celle développée au niveau de la section 2.

16
Comme dans le cadre du modèle de perceptron, le modèle en réseau de neurones sera entraı̂né
à l’aide de l’algorithme de la descente du gradient. Cet algorithme se résume en des étapes que
voici : (i) définir une fonction-coût qui mesure les erreurs de prédiction du modèle ; (ii) calculer les
variations de la fonction-coût par rapport aux variations des paramètres dans toutes les couches du
réseau ; (iii) mettre à jour l’ensemble des paramètres du modèle afin de minimiser les erreurs de
prédiction de ce dernier.

iii Fonction-coût
1X
L=− y log(A[q] ) + (1 − y) log(1 − A[q] ), (13)
n i
où q désigne l’indice de la dernière couche masquée du réseau. En effet, le coût du modèle est
apprécié sur base des dernières activations produites par le réseau, lesquelles sont comparées
aux vraies étiquettes pour chaque exemple. Pour le cas du réseau 6, p[2] = 1 et q = 2. Ce qui
signifie qu’il sera question de comparer la matrice (vecteur colonne) A[2] avec le vecteur y.
iv Équation des gradients
W [k] = W [k] − α∇L[k] , (14)
∂L
où ∇L[k] = . Cette expression désigne une matrice de même format que W [k] où sont
∂W [k]
rangés par colonne tous les vecteurs jacobiens associés à chaque neurone dans la couche k.

Pour calculer les dérivées partielles qui forment les jacobiens de la matrice ∇L[k] , nous ferons
encore recours à la règle de dérivation en chaı̂ne. Elle nous permettra de voir comment le coût varie
en fonction des paramètres de la dernière couche masquée, puis ceux de l’avant-dernière couche
masquée, et ainsi de suite jusqu’à remonter au niveau des paramètres de la première couche masquée.
C’est ce qu’on appelle en Deep Learning la “backward propagation”. Il s’agit d’un processus qui
consiste à retracer l’évolution de la fonction-coût par rapport aux paramètres présents dans chaque
couche du réseau, en allant de la dernière jusqu’à la première couche masquée.

Figure 7: Forward propagation vs Backward propagation

La formule générique de dérivation en chaı̂ne pour un réseau de neurones avec des couches
d’indice k, pour k ∈ {1, 2, . . . , q}, s’écrit comme suit :

17
∂L ∂L ∂A[q] ∂Z [q] ∂A[q−1] ∂Z [q−1] ∂A[k] ∂Z [k]
= × × × × × · · · × × (15)
∂W [k] ∂A[q] ∂Z [q] ∂A[q−1] ∂Z [q−1] ∂A[q−2] ∂Z [k] ∂W [k]

Dans le cas où q = 2 (cf. Figure 6), on obtient les expressions suivantes :

∂A[2] ∂Z [2]

∂L ∂L
× ×


 =
∂W [2] ∂A[2] ∂Z [2] ∂W [2]


∂A[2] ∂Z [2] ∂A[1] ∂Z [1]




 ∂L ∂L
= × × × ×



∂W [1] ∂A[2] ∂Z [2] ∂A[1] ∂Z [1] ∂W [1]

∂L ∂A[2] ∂Z [2] ∂A[1]


Posons dZ2 = × et dZ1 = dZ2 × × . Il vient :
∂A[2] ∂Z [2] ∂A[1] ∂Z [1]
∂Z [2]

∂L
= dZ2 ×



∂W [2] ∂W [2]



(16)
∂Z [1]


 ∂L
= dZ1 ×



∂W [1] ∂W [1]

∂L ∂Z [k]
De manière générique, on écrira = dZk × . Le système 16 décrit les équations de la
∂W [k] ∂W [k]
backward propagation en notation matricielle. Ce qu’il nous reste à déduire, ce sont les expressions
∂L
des dérivées partielles ∇L[k] = qu’on retrouve dans l’équation des gradients. Avant tout,
∂W [k]
résumons le modèle que nous avons développé jusqu’ici.

Z [k] = A[k−1] · W [k] , avec A[0] = X






(fonction d’agrégation)





 1
A[k] = (fonction d’activation)



1 + e−Z [k]


1P


y log(A[q] ) + (1 − y) log(1 − A[q] ) (fonction-coût)


 L = −
n i








W [k] = W [k] − α∇L[k]


(équation des gradients)

La matrice ∇L[k] contient les vecteurs jacobiens des neurones de la couche k. Pour trouver les
expressions de ces jacobiens, nous allons recourir à la règle de dérivation en chaı̂ne décrite par le
système 16. Pour commencer, trouvons ce que valent les termes dZ2 et dZ1 .

i Premier terme
∂L ∂A[2]
dZ2 = ×
∂A[2] ∂Z [2] ! !
1P y 1−y
= − − · A[2] (1 − A[2] )
n i A[2] 1 − A[2]
!
1P
= A[2] − y
n i

18
ii Second terme
∂Z [2] ∂A[1]
dZ1 = dZ2 × ×
∂A[1] !∂Z [1] !
1P T
= A[2] − y · W [2] × A[1] (1 − A[1] )
n i

Eu égard à ce qui précède, les dérivées partielles se déduisent comme suit.

!
∂Z [2]

∂L 1 [1]T
= dZ × = A · A[2] − y


 2
∂W [2] ∂W [2] n




" ! !#
(17)
[1]


 ∂L ∂Z 1 T T
= dZ1 × = X · A[2] − y · W [2] × A[1] (1 − A[1] )




∂W [1] ∂W [1] n

Le système 17 représente les expressions développées des équations de la backward propagation.


A` présent, nous disposons de toutes les équations qui décrivent notre modèle. Nous pouvons donc
à partir d’ici l’implémenter sous Python avec la librairie NumPy.

3.3 Programmation sous Python


Dans cette sous-section, il sera question de coder les équations de la forward propagation (cf. système
12) et les équations de la backward propagation (cf. système 17). Pour programmer notre modèle en
réseau de neurones à 2 couches, nous allons générer un dataset contenant n = 100 enregistrements
répartis en deux classes y ∈ {0, 1} non séparables linéairement. De plus, chaque enregistrement va
posséder m = 3 caractéristiques observées à des échelles différentes.

# Importation des librairies


import numpy as np
from matplotlib import pyplot as plt
from sklearn . datasets import make moons

# Generation d’un dataset a separabilite non−lineaire


X, y = make moons ( n samples = 100, noise = 0.1, random state = 0)

# Creation d’une troisieme feature sur une echelle differente


x3 = np. where(y == 1, np. random . randint (20, 30, 100) ,
np. random . randint (30, 40, 100))
x3 = x3. reshape (([Link] [0], 1))
# Creation du vecteur unitaire pour le biais
unit vector = [Link]([Link] [0], int)
unit vector = unit vector . reshape (( unit vector .shape [0], 1))

# Reformatage de la matrice des features et du vecteur target


X = np. concatenate ((X, x3 , unit vector ), axis = 1)
y = y. reshape (([Link] [0], 1))

# Visualisation des donnees


scatter plot = plt. scatter (X[:, 0], X[:, 1], c = y)
plt. xlabel (’Feature x1’)

19
plt. ylabel (’Feature x2’)
plt. legend ( ∗ scatter plot . legend elements (),
loc=’best ’, title=’Classes ’)

Figure 8: Espace des caractéristiques

Le dataset a été généré grâce à la fonction make moons() du package sklearn. Dans la Fig-
ure 8, nous représentons les données sur un nuage de points, en considérant uniquement les deux
premières caractéristiques. Il en ressort que les deux classes ne sont pas linéairement sépérables.
Cette situation est la plus fréquemment rencontrée dans des applications réelles, et les réseaux de
neurones ont la capacité de résoudre de tels problèmes.

# Statistiques descriptives
means = [Link](X[: ,:3] , axis = 0)
stds = [Link](X[: ,:3] , axis = 0)
minimum = [Link](X[: ,:3] , axis = 0)
maximum = [Link](X[: ,:3] , axis = 0)
quartiles = np. percentile (X[: ,:3] , [25, 50, 75], axis = 0)

Il est à noter que la troisième caractéristique se situe à une échelle différente des deux premières
(cf. Tableau 4). En effet, les réseaux de neurones sont sensibles aux différences dans les échelles des
données des variables explicatives. C’est ce qu’on appelle le “feature scaling”. Si les plages de valeurs
des caractéristiques d’entrée sont très différentes, cela peut entraı̂ner des problèmes de convergence
de l’algorithme d’optimisation, ce qui peut endommager la performance du modèle en réseau de
neurones. Pour surmonter cet obstacle, il est nécessaire de rédimensionner les données au moyen
notamment de la standardisation. Cette technique consiste à soustraire la moyenne de chaque car-
actéristique et à la diviser par l’écart-type. Cela permet de ramener toutes les caractéristiques à une
moyenne de 0 et à une variance de 1, et donc sur des échelles assez semblables.

20
Table 4: Statistiques descriptives (données non-standardisées)

Feature x1 Feature x2 Feature x3


Moyenne 0.5001399 0.2429004 29.1500000
Écart-type 0.8667698 0.5042064 5.6380404
Minimum -1.1006935 -0.6375463 20.0000000
Quartile (25%) -0.0443350 -0.1820928 24.0000000
Quartile (50%) 0.5347266 0.2868138 29.5000000
Quartile (75%) 1.0140432 0.6583112 34.0000000
Maximum 2.0604572 1.1150326 39.0000000

# Standardisation
from sklearn . preprocessing import StandardScaler
X scaled = StandardScaler (). fit(X[: ,:3]). transform (X[: ,:3])
X scaled = np. concatenate (( X scaled , unit vector ), axis = 1)

# Statistiques descriptives
means s = [Link]( X scaled [: ,:3] , axis = 0)
stds s = [Link]( X scaled [: ,:3] , axis = 0)
minimum s = [Link]( X scaled [: ,:3] , axis = 0)
maximum s = [Link]( X scaled [: ,:3] , axis = 0)
quartiles s = np. percentile ( X scaled [: ,:3] , [25, 50, 75], axis = 0)

Table 5: Statistiques descriptives (données standardisées)

Feature x1 Feature x2 Feature x3


Moyenne 1.33226763e-17 -2.34048891e-16 2.79776202e-16
Écart-type 1.00000000 1.00000000 1.00000000
Minimum -1.84689565 -1.74620298 -1.62290429
Quartile (25%) -0.62816555 -0.84289541 -0.91343793
Quartile (50%) 0.03990303 0.08709401 0.06207831
Quartile (75%) 0.59289476 0.82389046 0.86022796
Maximum 1.80015194 1.72971278 1.74706091

21
Pour programmer le modèle du réseau de neurones développé dans cette section, nous allons
adopter le même cheminement que celui proposé à la section 2.3.

i Définition de la fonction d’initialisation


# Fonction d’initialisation
def initialize (m, p1 , p2):

np. random .seed (0)


W1 = np. random .randn(m, p1)
W2 = np. random .randn(p1 , p2)

parametres = {
’W1’: W1 ,
’W2’: W2
}

return parametres

ii Définition des fonctions d’agrégation et d’activation


# Equations de la forward propagation
def forward propagation (X, parametres ):

Z1 = [Link]( parametres [’W1’])


A1 = 1 / (1 + [Link](−Z1))

Z2 = [Link]( parametres [’W2’])


A2 = 1 / (1 + [Link](−Z2))

activations = {
’A1’: A1 ,
’A2’: A2
}

return activations

iii Définition de la fonction-coût


# Fonction−cout
def log loss (activations , y):
Aq = activations [’A2’]
L = −1/len(y ) ∗ [Link] ((y ∗ [Link](Aq)) + ((1−y ) ∗ [Link](1−Aq )))
return L

22
iv Définition des vecteurs jacobiens
# Equations de la backward propagation
def backward propagation (parametres , activations , X, y):

A1 = activations [’A1’]
A2 = activations [’A2’]
W2 = parametres [’W2’]

dW2 =1/ len(y ) ∗ [Link](A1.T, (A2−y))


dW1 =1/ len(y ) ∗ [Link](X.T, ([Link] ((A2−y), W2.T ) ∗ ( A1∗(1−A1 ))))

jacobiens = {
’dW2 ’: dw2 ,
’dW1 ’: dW1
}

return jacobiens

v Définition de la fonction de mise à jour


# Actualisation des parametres
def update (parametres , jacobiens , learning rate ):

W1 = parametres [’W1’]
W2 = parametres [’W2’]

dW1 = jacobiens [’dW1 ’]


dW2 = jacobiens [’dW2 ’]

W1 = W1 − learning rate ∗ dW1


W2 = W2 − learning rate ∗ dW2

parametres = {
’W1’: W1 ,
’W2’: W2
}

return parametres

vi Définition de la fonction de prédiction


# Fonction de prediction
def predict (X, parametres ):
activations = forward propagation (X, parametres )
A2 = activations [’A2’]
y pred = []

for i in range([Link] [0]):


if A2[i] >= .5:

23
y pred . append (1)
else:
y pred . append (0)

return y pred

Après avoir codé toutes les équations en Python, procédons à présent au codage de l’algorithme
d’optimisation. Ce code permettra de visualiser l’évolution de la valeur du coût à travers les itérations,
et de retourner les valeurs optimales des paramètres du modèle. Les détails sur les sorties de chaque
bloc de codes sont disponibles dans le notebook dont le lien est fourni en conclusion du présent guide.

# Algorithme d’optimisation
def ANN(X, y, m, p1 , p2 , learning rate , n iterations ):

parametres = initialize (m, p1 , p2)


L = []

for h in range( n iterations ):


activations = forward propagation (X, parametres )
A2 = activations [’A2’]

L. append ( log loss ( activations , y))


jacobiens = backward propagation (parametres , activations ,X,y)
parametres = update (parametres , jacobiens , learning rate )

[Link](L)
plt. xlabel (’Iterations ’)
plt. ylabel (’Cout ’)
[Link] ()

return parametres

Pour entraı̂ner le modèle, le taux d’apprentissage a été fixé à α = 0.1 et le nombre d’itérations à
H = 1000. Nous avons considéré deux neurones pour la première couche, et un seul pour la seconde.

# Entrainement du modele
parametres =ANN(X = X scaled , y = y, m = X scaled .shape [1], p1 = 2,
p2 = 1, learning rate = .1, n iterations = 1000)
print ( parametres )

# Matrice de confusion
y pred = predict ( X scaled , parametres )
ConfusionMatrix = confusion matrix ( y true = y, y pred = y pred )
print ( ConfusionMatrix )
# Accuracy
Acc = accuracy ( ConfusionMatrix )
print (Acc)

24
Partant des codes précédemment écrits, il est possible d’entrainer d’autres modèles de réseau
comportant un nombre plus élevé de neurones dans les deux couches masquées. Il suffira pour
cela de faire varier les arguments p1 et p2 de la fonction ANN(). L’on pourra alors se poser la
question du choix judicieux de ces deux arguments, mais également des valeurs optimales du taux
d’apprentissage et du nombre d’itérations. Ces discussions sont abordées dans la section 4.

# Definition de la grille pour la frontiere de decision


h = 0.02
x min , x max = X scaled [:, 0]. min () − 1, X scaled [:, 0]. max () + 1
y min , y max = X scaled [:, 1]. min () − 1, X scaled [:, 1]. max () + 1
xx ,yy=np. meshgrid (np. arange ( x min , x max ,h),np. arange ( y min , y max ,h))

# Predire la classe pour chaque point de la grille


weights = { ’W1’: parametres [’W1’][[0 ,1]] , ’W2’: parametres [’W2’]}
grid points = np. c [[Link] (), [Link] ()]
predictions = predict ( grid points , weights )

# Reformatage des predictions en fonction de la grille


predictions = [Link]( predictions )
predictions = predictions . reshape ([Link])

# Tracage de la frontiere de decision non−lineaire


scatter plot = plt. scatter ( X scaled [:, 0], X scaled [:, 1], c=y)
plt. xlabel (’Feature x1’)
plt. ylabel (’Feature x2’)
plt. legend ( ∗ scatter plot . legend elements (),
loc=’best ’, title=’Classes ’)
plt. contourf (xx , yy , predictions , alpha =0.2);

Figure 9: Frontière de décision

25
La Figure 9 révèle que la prise en compte de la sépérabilité non-linéaire des classes à prédire
a amélioré la performance du modèle. En effet, le modèle ajusté accuse une accuracy de 99%, ce
qui peut sembler très intéressant à première vue. Cependant, une performance très élevée dans
la phase d’apprentissage est aussi susceptible de présager le problème “overfitting”. L’overfitting
(sur-apprentissage) se produit lorsqu’un modèle de Machine Learning est exagérément adapté aux
données d’entraı̂nement au point de ne plus parvenir à se généraliser à des données nouvelles. Une
solution à ce problème consiste à faire recours à la “validation croisée”, telle que discutée dans la
section suivante.

4 Perceptron multi-couches
Dans les deux précédentes sections, nous avons codé de bout en bout notre propre programme
de réseau de neurones artificiels. Lors de l’entrainement des modèles, nous avons fixé de manière
arbitraire le taux d’apprentissage à α = 0.1 et le nombre d’itérations à H = 1000. En effet, la per-
formance d’un modèle est aussi dictée par les valeurs prises par ces deux arguments. Il sied donc de
les choisir minutieusement lors de la phase d’apprentissage du modèle. L’objectif de cette section
consiste à discuter en détails du réglage de ces arguments dans le cadre d’un modèle de perceptron
comportant plus de deux couches masquées.

Les arguments susmentionnés sont appelés en Machine Learning des “hyper-paramètres”. Con-
trairement aux paramètres contenus dans la matrice W [k] , les hyper-paramètres ne sont pas appris
´
par le modèle pendant l’entraı̂nement, mais définis préalablement par le data scientist. Etant donné
qu’ils ont un impact considérable sur la performance du modèle, leur réglage est une question qu’il
faut traiter avec beaucoup de soins. Pour ce faire, nous allons recourir à la librairie scikit-
learn afin de réaliser ce “tuning process”.

Pour le cas d’un modèle en réseau de neurones, les principaux hyper-paramètres à définir sont
les suivants : (i) le taux d’apprentissage, (ii) le nombre d’itérations, (iii) la profondeur du réseau, i.e.
le nombre de couches masquées et le nombre de neurones dans chaque couche masquée, et (iv) le
type d’activation (logistique, tanh, ReLU, …). Le réglage de ces hyper-paramètres consiste à tester
différentes valeurs, puis à choisir celles qui donnent la meilleure performance. Plusieurs méthodes
permettent d’y parvenir. L’une des plus couramment utilisées, c’est la validation croisée. Elle con-
siste, dans un premier temps, à diviser le dataset en deux partitions, la base d’apprentissage et la
base de test. Ensuite, on entraı̂ne le modèle sur la base d’apprentissage et on évalue sa performance
sur la base de test.

Au regard de ce qui précède, cette section sera structurée de la manière suivante :

— D’abord, il sera question de charger un dataset réel puis le partitionner en base d’apprentissage
et base de test.

— Ensuite, il sera question d’entraı̂ner le modèle en réseau de neurones sur la base d’apprentissage,
tout en optimisant les valeurs des hyper-paramètres par validation croisée.

— Enfin, il sera question d’évaluer la performance du modèle entraı̂né sur des données nouvelles,
i.e. sur la base de test.

26
4.1 Partitionnement des données
Le dataset qui sera analysé dans cette section se rapporte à 1797 images de chiffres manuscrits, cha-
cune de taille 8x8 pixels. Les images sont divisées en 10 classes : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Chaque
image est représentée par un tableau de 64 valeurs, chacune représentant l’intensité d’un pixel. Les
valeurs des pixels sont comprises entre 0 et 16. Le code ci-après a permis de procéder au chargement
du dataset.

# Importation des librairies


import numpy as np
import pandas as pd
import matplotlib . pyplot as plt
import seaborn as sns
import warnings
from tqdm import tqdm
from sklearn . datasets import load digits
from sklearn . neural network import MLPClassifier
from sklearn . model selection import train test split , GridSearchCV
from sklearn . model selection import validation curve
from sklearn . metrics import confusion matrix , classification report

# Chargement des donnees


digits = load digits ()
print ( digits [’DESCR ’])

Dans la Figure 10, nous représentons un échantillon d’images contenues dans le dataset. Le but
de cette application sera d’arriver à prédire, à partir des caractéristiques d’une image (ses pixels), le
chiffre qui lui correspond.

# Preparation du dataset
features = pd. DataFrame (data = digits [’data ’],
columns = digits [’ feature names ’])
target = pd. DataFrame (data = digits [’target ’],
columns = [’digits ’])
digits data = pd. concat ([ features , target ], axis = 1)
digits data .info ()

# Creation de la figure d’images


fig , axes = plt. subplots (nrows = 2, ncols = 5, figsize = (10, 4))
for i, ax in enumerate (axes. flatten ()):
sns. heatmap (data = digits . images [i], ax = ax ,
cmap = ’gray ’, cbar = False)
[Link](’off ’);

27
Figure 10: Visualisation des données

Le dataset étant prêt pour l’analyse, il peut être divisé en base d’apprentissage et base de test.
Comme évoqué précédemment, le partitionnement des données permet d’éviter que le modèle tombe
dans le piège du sur-apprentissage. Nous effectuerons la division aléatoire des données, en conser-
vant 10% des enregistrements pour l’évaluation finale du modèle entraı̂né.

# Partitionnement des donnees


X train , X test , y train , y test = train test split (features , target ,
test size = 0.1,
random state = 0)
print ( X train .shape , X test .shape , y train .shape , y test .shape)

Table 6: Formats des bases d’apprentissage et de test


Base d’apprentissage Base de test
Features (1617, 64) (180, 64)
Target (1617, 1) (180, 1)

4.2 Entraı̂nement du modèle


Le modèle en réseau de neurones sera entraı̂né de sorte à sélectionner soigneusement les valeurs
des hyper-paramètres clés. La technique de la validation croisée sera utilisée à cet effet. La fonc-
tion GridSearchCV() du package scikit-learn nous permettra de définir des valeurs
raisonnables des hyper-paramètres, puis de rechercher de manière exhaustive les valeurs optimales
de ceux-ci. D’amples détails au sujet des hyper-paramètres à régler dans le cadre d’un réseau de
neurones peuvent être trouvés dans la documentation relative à la fonction MLPClassifier(),
laquelle permet d’implémenter un perceptron multi-couches3 .

# Entrainement du modele
warnings . filterwarnings (’ignore ’)
hyper param = {# profondeur du reseau
’ hidden layer sizes ’: [(10 ,) , (10 ,10 ,) , (10 ,10 ,10)] ,

# fonction d’activation
’activation ’: [’logistic ’, ’tanh ’, ’relu ’],
3
Lien vers la documentation ici.

28
# type de taux d’apprentissage
’ learning rate ’: [’invscaling ’, ’adaptive ’],

# algorithme d’optimisation
’solver ’: [’lbfgs ’, ’sgd ’],

# parametre de regularisation
’alpha ’: [.4, .5, .6]
}

Grid NN = GridSearchCV ( MLPClassifier ( random state = 0),


param grid = hyper param , cv = 10)

# Obtention du nombre total d’iterations pour la grille de recherche


len layers = len( hyper param [’ hidden layer sizes ’])
len act = len( hyper param [’activation ’])
len learn rate = len( hyper param [’ learning rate ’])
len solver = len( hyper param [’solver ’])
len alpha = len( hyper param [’alpha ’])
total iter = len layers ∗ len act ∗ len learn rate ∗ len solver ∗ len alpha

# Affichage de la barre de progression


with tqdm( total= total iter , desc=’Grid Search Progress ’) as pbar:
for param in Grid NN . param grid :
Grid NN .fit( X train , y train )
pbar. update (1)

Le code ci-dessus permet d’entrainer le modèle en optimisant les hyper-paramètres renseignés.


´Etant donné le nombre de valeurs à tester par hyper-paramètre, le temps requis pour l’exécution de
ce code peut s’avérer être très long. Pour estimer ce temps, nous avons programmé, au moyen de
la librairie tqdm, une barre de progression qui permet de suivre l’exécution du code à travers les
itérations qui se succèdent. Pour ce cas précis, le nombre maximum d’itérations est estimé à H = 108
et la vitesse d’exécution du code à 1001.12 secondes par itérations, ce qui chiffre la durée requise pour
l’exécution du code jusqu’à convergence de l’algorithme d’optimisation à 83 minutes et 25.6 secondes
! Ce temps de traitement peut encore explosé si l’on rajoute d’autres couches supplémentaires dans
le réseau. Vous l’avez compris, cela constitue l’une des principales limites de la librairie scikit-
learn. C’est pour cette raison que nous proposons une prise en main de la librairie TensorFlow
dans la section 5.

# Valeurs optimales des hyper−parametres


print ( Grid NN . best params )

# Performance du modele dans l’apprentissage


NN model = Grid NN . best estimator
NN model . score( X train , y train )

29
Table 7: Réglage des hyper-paramètres
Hyper-paramètres Valeurs optimales

Profondeur du réseau (10, 10, 10)


Fonction d’activation ReLU
Algorithme d’optimisation Descente de gradient
Type de taux d’apprentissage Adaptatif
Paramètre de régularisation 0.4

Accuracy lors de l’entraı̂nement 0.95

Après entraı̂nement du modèle, les résultats indiquent une performance de 95% sur la base
d’apprentissage. Dans la Figure 11, nous représentons dans le panel (a) l’évolution de l’accuracy
du modèle durant la phase d’entraı̂nement en fonction d’un hyper-paramètre clé, à savoir le taux
d’apprentissage. Dans le panel (b) de cette même Figure, nous représentons l’évolution de la courbe
d’apprentissage du modèle selon les itérations de l’algorithme d’optimisation. On constate que le
modèle a été bien entraı̂né (car la courbe descend), ce qui justifie le score d’accuracy élevé obtenu
pour l’apprentissage.

# Tuning process ( reglage des hyper−parametres )


learning rate = np. logspace(−1,−5,5)
score train , score cv = validation curve ( MLPClassifier ( random state =0),
X train , y train , cv = 10,
param range = learning rate ,
param name =’ learning rate init ’)
score cv =pd. DataFrame ( score cv .mean(axis =1), columns =[’Accuracy ’])
score cv . set index ( learning rate , inplace = True)
score cv . [Link] = [’Learning Rate ’]
sns. lineplot (data = score cv ). axvline ( score cv [’Accuracy ’]. idxmax (),
color = ’red ’,
linestyle = ’dashed ’);
# Courbe d’apprentissage
sns. lineplot (x = range (1, len( NN model . loss curve )+1) ,
y = NN model . loss curve )
plt. xlabel (’Iterations ’)
plt. ylabel (’Cout ’);

Figure 11: Performance du modèle dans la base d’apprentissage


(a) optimisation de α (b) fonction-coût

30
4.3 Évaluation du modèle
Après avoir entraı̂né le modèle sur la base d’apprentissage, il sera évalué (validé) sur la base de test.
Il s’agit là d’une étape essentielle du processus de développement d’un modèle de Machine Learning.
Elle permet de s’assurer que le modèle est performant et qu’il ne souffre pas de sur-apprentissage
(overfitting).

Le Tableau 8 fournit le rapport de classification qui reprend les principales métriques permettant
d’apprécier le modèle entraı̂né. La métrique precision mesure la fraction de prédictions positives qui
sont réellement correctes. La métrique recall mesure la fraction d’instances positives réelles qui sont
correctement identifiées par le modèle. La métrique F1-score est une mesure combinée de la capacité
du modèle à identifier correctement les cas positifs tout en minimisant les faux positifs et les faux
négatifs.

` l’issue de l’évaluation sur la base de test, le modèle accuse une performance de 93%. Ce résultat
A
atteste que le modèle est capable de bien prédire la classe d’appartenance de toute donnée nouvelle.
Par conséquent, notre réseau de neurones peut passer à la phase de déploiement, i.e. il peut être mis
en production et commencer à être utiliser pour des tâches futures de prédiction.

# Rapport de classification et Matrice de confusion


y predict NN = NN model . predict ( X test )
print ( classification report ( y test , y predict NN ))
conf matrix NN =pd. DataFrame ( confusion matrix ( y test , y predict NN ))
conf matrix NN

# Performance du modele au test


NN model . score( X test , y test )

Table 8: Rapport de classification


classes precision recall f1-score support

0 1.00 1.00 1.00 11


1 0.82 0.90 0.86 20
2 1.00 1.00 1.00 16
3 0.77 1.00 0.87 10
4 1.00 1.00 1.00 10
5 0.90 0.90 0.90 21
6 0.96 0.96 0.96 25
7 0.95 1.00 0.98 20
8 1.00 0.78 0.88 23
9 0.96 0.92 0.94 24

accuracy 0.93 180


macro avg 0.94 0.95 0.94 180
weighted avg 0.94 0.93 0.93 180

31
5 Projet complet avec la librairie TensorFlow
L’ajout de plusieurs couches masquées dans un réseau de neurones donne la capacité à ce dernier
d’apprendre des problèmes beaucoup plus compliqués. En même temps, cela rend son entraı̂nement
très long. La librairie TensorFlow permet de trouver le juste équilibre dans ce dilemme. En effet,
cette librairie a pour vocation de réduire considérablement le temps requis pour l’entraı̂nement d’un
réseau de neurones artificiel profond.

Dans le cadre de ce dernier projet, nous allons considérer un dataset semblable à celui analysé
dans la section 4. Il s’agit d’un ensemble de données de 60 000 images de taille 28x28 pixels dont
les valeurs sont comprises entre 0 et 255, ainsi que d’un ensemble de test de 10 000 images compor-
tant les mêmes caractéristiques. L’objectif du projet est de développer un modèle de Deep Learning
capable de classifier ces images de chiffres manuscrits. Pour ce faire, nous allons recourir à l’API
Keras qui est chargeable par défaut dans la librairie TensorFlow.

Keras est une Application Programming Interface (API) open-source de haut niveau très utilisée
en Machine Learning4 . Il a été développé par François Chollet, qui est Ingénieur en AI chez
Google. Cette API est conçue pour faciliter la construction et l’entraı̂nement des modèles de Machine
Learning en général, et des réseaux de neurones en particulier. Il peut être directement chargé via
la librairie TensorFlow, laquelle dispose d’une syntaxe simple et assez intuitive, par opposition
à la librairie PyTorch.

5.1 Prétraitement et exploration des données


Dans cette sous-section, nous effectuerons les opérations relatives au prétraitement des données,
puis nous passerons à la phase exploratoire afin de mieux comprendre les données à notre disposi-
tion. Dans le bout de codes ci-dessous, nous chargeons notre dataset et examinons les formats des
bases d’apprentissage et de test.

# Importation des librairies


#!pip install tensorflow ( uncomment this line on first run)
import numpy as np
import pandas as pd
import matplotlib . pyplot as plt
import seaborn as sns
from tensorflow .keras. datasets import mnist
from tensorflow .[Link] import to categorical
from tensorflow .keras. models import Sequential
from tensorflow .keras. layers import Dense

# Chargement des donnees


( X train , y train ) , ( X test , y test ) = mnist. load data ()
print (’Train set X:’, X train .shape)
print (’Test set X:’, X test .shape)
print (’Train set y:’, y train .shape)
print (’Test set y:’, y test .shape)

4
La documentation TensorFlow-Keras est disponible ici.

32
Table 9: Formats des bases d’apprentissage et de test
Base d’apprentissage Base de test
Features (60 000, 28, 28) (10 000, 28, 28)
Target (60 000,) (10 000,)

` la lumière du Tableau 9, on constate que les caractéristiques des données sont dans un for-
A
mat à trois dimensions (le nombre d’images, les pixels en largeur et les pixels en hauteur). Ce type
de format des données est couramment rencontré dans des tâches de computer vision, un des prin-
cipaux domaines d’application du Deep Learning. Dans la modélisation, nous allons procéder à
l’aplatissement des pixels pour chaque image afin de retrouver le format classique à deux dimen-
sions. Bien avant, nous représentons graphiquement un échantillon des données de notre dataset
dans la Figure 12.

# Visualisation des donnees


fig , axes = plt. subplots (nrows = 1, ncols = 8, figsize = (10, 2))
for i, ax in enumerate (axes. flatten ()):
sns. heatmap (data= X train [i], ax=ax , cmap=’gray ’, cbar=False)
[Link](’off ’)

plt. tight layout ();

Figure 12: Visualisation des données

Les pixels des images varient dans une plage allant de 0 à 255. Cela implique que, pour certaines
images, les valeurs des pixels peuvent être proches de 0 (couleur noire), et pour d’autres, elles peu-
vent être proches de 255 (couleur blanche). En d’autres termes, les données ne sont pas sur la même
échelle. Sachant que les réseaux de neurones sont des modèles sensibles au feature scaling, il est
crucial de procéder à la standardisation des données avant la phase de modélisation. La technique
qui sera utilisée ici est celle du “Min-Max Scaler” qui consiste à placer les données dans une échelle
variant entre 0 et 1. Cette opération de prétraitement devrait permettre d’améliorer la convergence
de l’algorithme d’optimisation des paramètres du modèle.

# Reformatage et Standardisation des donnees


from sklearn . preprocessing import MinMaxScaler
X train new = X train . reshape ( X train .shape [0], −1)
X test new = X test . reshape ( X test .shape [0], −1)
X train = MinMaxScaler (). fit( X train new ). transform ( X train new )
X test = MinMaxScaler (). fit( X test new ). transform ( X test new )

print (’Train set:’, X train .shape)


print (’Test set:’, X test .shape)

33
Table 10: Nouveaux formats des caractéristiques
Format

Base d’apprentissage (60 000, 784)


Base de test (10 000, 784)

Le Tableau 10 renseigne les formats des données standardisées. A ` l’issue de la mise à l’échelle
des données, les caractéristiques ont été placées dans un format à deux dimensions. L’opération a
consisté à aplatir les pixels de chaque image de sorte à les ranger dans un vecteur unidimensionnel.
Ce qui nous a permis d’obtenir un total de 784 (28x28) caractéristiques par image.

Un autre élément pour lequel il faut se rassurer avant de passer à la phase de modélisation, c’est
la distribution des classes dans la base d’apprentissage. Ceci nous permet de vérifier si il y existe des
classes sur-représentées ou sous-représentées. Si les classes sont inéquitablement réparties, on dit
alors qu’il existe un “déséquilibre dans les données” (imbalanced data). Pour le cas de notre dataset,
la distribution des données semble équitable entre les classes (cf. Figure 13). Il n’est donc pas utile de
recourir ici aux techniques de ré-échantillonnage devant conduire à résoudre un problème potentiel
de déséquilibre des classes à prédire.

# Equilibre dans les donnees


classes = np. unique ( y train , return counts =True)
classes = pd. DataFrame ({ ’class ’: classes [0], ’freq ’: classes [1]})

bar plot =sns. barplot (data=classes , x=’class ’, y=’freq ’,


color=’lightgray ’)
for i in range(len( classes [’class ’])):
bar plot .text(i, classes .iloc[i][’freq ’]−500,
classes .iloc[i][’freq ’], ha = ’center ’);

Figure 13: Distribution des classes

34
Avant de clôturer cette sous-section, nous allons également reformater le vecteur de la variable
cible. Il s’agit d’une variable catégorielle dont les modalités sont les 10 classes à prédire. Ce refor-
matage sera effectué par encodage catégoriel des étiquettes de la variable cible en vecteurs one-hot.
Les vecteurs one-hot sont des vecteurs de longueur égale au nombre de modalités de la variable cible.
Chaque entrée du vecteur est égale à 0, sauf l’entrée correspondant à la catégorie de l’étiquette, qui
est égale à 1. Cet encodage est nécessaire pour la plupart des modèles de Deep Learning, car il per-
met de prendre en compte le fait que les différentes classes à prédire sont mutuellement exclusives.

# Encodage categoriel des etiquettes en vecteurs one−hot


num classes = 10
y train = to categorical ( y train , num classes )
y test = to categorical ( y test , num classes )

print (’Train set:’, y train .shape)


print (’Test set:’, y test .shape)

Table 11: Nouveaux formats de la variable cible


Format

Base d’apprentissage (60 000, 10)


Base de test (10 000, 10)

5.2 Construction, entraı̂nement et évaluation du modèle


Le phase de prétraitement étant achevée, cette sous-section aborde la phase de modélisation pro-
prement dite. La construction du modèle sera réalisée au moyen de la fonction Sequential()
qui permet de créer les couches du réseau l’une après l’autre. La première couche comporte 128
neurones, la deuxième 64 neurones, et la troisième 32 neurones. Ces trois premières couches sont
dotées d’une fonction d’activation du type “ReLU”. La fonction Rectified Linear Unit (ReLU) est une
fonction d’activation non-linéaire couramment utilisée dans les réseaux de neurones artificiels. Elle
présente l’avantage de favoriser la sparsité des poids d’un réseau de neurones. Ce phénomène de
sparsité se produit lorsque de nombreux poids dans le réseau sont proches de zéro. La fonction ReLU
permet ainsi de réduire le nombre de paramètres à optimiser, ce qui peut accélérer l’apprentissage
du modèle. C’est cet avantage qui fait de la ReLU une fonction idéale pour les premières couches du
réseau à entraı̂ner.

La dernière couche comporte 10 neurones, en référence aux 10 classes à prédire. Elle dotée
d’une fonction d’activation du type “soft-max”. Au moins trois raisons conduisent les data scientists
à utiliser cette fonction d’activation pour la dernière couche d’un réseau de neurones. (i) La fonction
soft-max est différentiable, tout comme la fonction logistique. Cette propriété est nécessaire pour
l’entraı̂nement des réseaux de neurones par la backward propagation. (ii) Tout comme la fonction
logistique, la fonction soft-max produit des sorties sous forme de probabilités. Seulement, la fonction
soft-max est plus adaptée aux problèmes de classification multi-classes. (iii) Contrairement à la
fonction logistique, la fonction soft-max est compatible avec l’entropie croisée comme fonction-coût.

35
Notre modèle est configuré en considérant l’entropie croisée comme mesure permettant de quan-
tifier les erreurs de prédiction. L’entropie croisée est un indicateur de la similarité entre deux dis-
tributions de probabilité. Minimiser cette fonction-coût revient donc à réduire la différence entre la
distribution des prédictions du modèle et la distribution des données réelles. Elle est préférée à la
fonction-coût log loss développée dans les sections 2 et 3 en ce sens qu’elle pénalise fortement les
prédictions qui sont confiantes, mais incorrectes5 . De plus, l’entropie croisée est compatible avec la
fonction d’activation soft-max, laquelle est souvent utilisée dans la dernière couche d’un réseau de
neurones pour transformer les valeurs agrégées en probabilités. Enfin, l’algorithme d’optimisation
spécifié pour la configuration du modèle est la descente de gradient stochastique, et la métrique de
précision utilisée est l’Accuracy. L’architecture du modèle configuré est présentée dans la Figure 14.

# Construction du modele
model = Sequential ()
model .add(Dense(units =128 , activation =’relu ’,
input dim =len( X train [1])))
model .add(Dense(units =64, activation =’relu ’))
model .add(Dense(units =32, activation =’relu ’))
model .add(Dense(units =10, activation =’softmax ’))

# Configuration et Resume du modele


model . compile (loss=’ categorical crossentropy ’,
optimizer =’sgd ’, metrics =’accuracy ’)
model . summary ( show trainable = True)

# Graphique du modele
"""
!pip install pydot
!pip install graphviz
import os
os. environ [’PATH ’] += os. pathsep + ’C:/ Program Files/ Graphviz /bin/’
"""
from tensorflow .[Link] import plot model
plot model (model , to file = ’ModelGraph .png ’,
show shapes = True , show layer activations = True)

""" INSTRUCTIONS SUPPLEMENTAIRES


Pour afficher le graphique du modele , vous devez :
(i) telecharger GRAPHVIZ : https :// graphviz . gitlab .io/ download /
(ii) ajouter le chemin vers son executable a l’environnement PATH
"""

Une fois le modèle construit et configuré, il peut être entraı̂né sur la base d’apprentissage. Pour
des raisons de comparaison, nous allons retenir le même nombre d’itérations qu’au modèle entraı̂né
dans la section précédente avec la librairie scikit-learn. Le but ici sera d’apprécier le gain en
termes de temps de traitement qu’offre la librairie TensorFlow. Enfin, nous conserverons 25%
des données d’entraı̂nement pour l’évaluation des métriques (perte et précision) par itération en
guise de validation croisée.
5
On dit qu’une prédiction est confiante et incorrecte lorsqu’elle se rapporte à la mauvaise classe prédite pour
l’enregistrement, et simultanément associée à une forte probabilité d’appartenance à cette classe en sortie.

36
Figure 14: Architecture du modèle

# Entrainement du modele sur la base d’apprentissage


NN model = [Link]( X train , y train , epochs =100 ,
batch size =32, validation split =.25)

# Evaluation du modele sur la base d’apprentissage


train loss , train acc = model. evaluate ( X train , y train )
print (’Train accuracy :’, train acc )

# Evaluation du modele sur la base de test


test loss , test acc = model. evaluate ( X test , y test )
print (’Test accuracy :’, test acc )

Avec la librairie TensorFlow, il n’est pas nécessaire de programmer une barre de progression
pour suivre le temps requis pour entrainer le modèle. En effet, la méthode fit() produit déjà le
temps d’exécution du code à travers les itérations durant l’entraı̂nement du modèle. Les résultats in-
diquent qu’il a fallu en moyenne 4.68 secondes par itération pour entraı̂ner complètement le modèle,
ce qui correspond à une durée totale de traitement de 7 minutes et 48.7 secondes ! Il s’agit là d’un
énorme gain en temps, d’autant plus que le modèle entraı̂né dans cette section comporte plus de
couches masquées que celui entraı̂né dans la section précédente. Les performances du modèle dans
les bases d’apprentissage et de test sont renseignées dans le Tableau 12.

´
Table 12: Evaluation du modèle
Accuracy

Base d’apprentissage 99.31%


Base de test 97.56%

37
Globalement, le modèle semble être très bien entraı̂né sur les données d’apprentissage et est ca-
pable de bien se généraliser aux données de test. La Figure 15 retrace l’évolution des courbes de
perte et de précision sur les données d’entraı̂nement et de validation. Elle indique que, le long des
itérations, la fonction-coût baisse progrèssivement et parallèlement la métrique de précision aug-
mente progrèssivement. Mais à un certain niveau, la perte sur les données de validation ne baisse
plus sensiblement, et la précision sur ces mêmes données commence à stagner lorsque le nombre
d’itérations s’accroı̂t. Il s’agit là d’une indication d’un phénomène dont on a déjà discuté, à savoir
l’overfitting. En effet, le modèle adapté pour les problèmes de classification d’images, ou de computer
vision en général, c’est les réseaux de neurones convolutifs (CNNs). Les bases de ce type de modèle
furent introduits dans la littérature par Rumelhart et al. (1986). Il a fallu attendre le papier de LeCun
et al. (1998) pour appliquer les CNNs à un problème du monde réel, ce qui a permis de les populariser.

Les CNNs sont une catégorie des réseaux artificiels composés de plusieurs couches, dont les
couches de convolution. Ces dernières appliquent un ensemble de filtres apprenables aux données
d’entrée pour les scanner en vue de détecter des motifs spécifiques, tels que les bords, les textures ou
les formes. L’apprentissage de ce type de réseaux de neurones dépasse le cadre du présent guide qui
n’a consisté qu’à une initiation aux modèles de Deep Learning. Nous recommandons vivement aux
lecteurs de consulter les ouvrages et articles repris dans la section bibliographique afin d’approfondir
leurs connaissances sur les techniques avancées en Deep Learning.

# Courbes de perte et de precision

plt. figure ( figsize = (12, 4))


plt. subplot (1, 2, 1)
sns. lineplot (data = NN model . history [’loss ’][:50] ,
label = ’Entrainement ’, color = ’blue ’)
sns. lineplot (data = NN model . history [’ val loss ’][:50] ,
label = ’Validation ’, color = ’red ’)
plt. legend ()
plt. xlabel (’Iterations ’)
plt. ylabel (’Cout ’)
plt. title (’(a) Courbe de Perte ’, fontstyle = ’oblique ’)

plt. subplot (1, 2, 2)


sns. lineplot (data = NN model . history [’accuracy ’][:50] ,
label = ’Entrainement ’, color = ’blue ’)
sns. lineplot (data = NN model . history [’ val accuracy ’][:50] ,
label = ’Validation ’, color = ’red ’)
plt. legend ()
plt. xlabel (’Iterations ’)
plt. ylabel (’Accuracy ’)
plt. title (’(b) Courbe de Precision ’, fontstyle = ’oblique ’);

38
Figure 15: Courbes d’apprentissage

6 Conclusion
Dans ce guide, nous avons exploré les fondements du Deep Learning, en partant du modèle sim-
ple du perceptron pour arriver à un perceptron multi-couches. Nous avons dérivé les équations
mathématiques qui caractérisent un réseau de neurones, en l’occurence les équations de la forward
propagation et de la backward propagation. Ces équations ont été codées en Python au moyen de
la librairie NumPy, démontrant ainsi la flexibilité et la puissance de ce langage de programmation
pour le calcul numérique.

Nous avons également abordé l’utilisation des librairies scikit-learn et TensorFlow,


respectivement pour le réglage des hyper-paramètres et l’entrainement d’un réseau de neurones
profond. Ces outils offrent une grande facilité d’utilisation et permettent de gérer efficacement des
réseaux de neurones de grande taille. De cette manière, ce guide a constitué une introduction solide
aux principes fondamentaux du Deep Learning, et nous espérons qu’il a fourni les bases nécessaires
aux lecteurs pour commencer à utiliser en pratique les réseaux de neurones artificiels.

Il est important de noter que le Deep Learning est un domaine en constante évolution et qu’il
est essentiel de continuer à apprendre et à expérimenter. Le notebook contenant les codes Python
utilisés tout au long de ce guide est disponible sur mon compte GitHub6 . Ceci permettra aux lecteurs
de manipuler directement les concepts présentés et de les approfondir. Plusieurs autres exemples
pratiques peuvent aussi être trouvés dans l’ouvrage de Chollet (2018).

En définitive, n’oubliez pas que le Deep Learning n’est qu’un outil parmi tant d’autres dans
la boı̂te à outils de l’Intelligence Artificielle. Il est important de comprendre quand et comment
l’utiliser, mais aussi de connaı̂tre ses limites. Merci d’avoir suivi ce guide et bonne continuation
dans votre exploration du Deep Learning !

6
Pour télécharger le notebook, cliquez ici.

39
References
Aggarwal, C. C. (2018). Neural Networks and Deep Learning: A Textbook. Springer International
Publishing.

Chollet, F. (2018). Deep Learning with Python. Manning Publications.

Goodfellow, I., Bengio, Y., and Courville, A. (2016). Deep Learning. MIT Press.

LeCun, Y., Bottou, L., Bengio, Y., and Haffner, P. (1998). Gradient-based learning applied to Document
recognition. Proceedings of the IEEE, 86(11):2278–2324.

Rumelhart, D. E., Hinton, G. E., and Williams, R. J. (1986). Learning internal representations by
Error propagation. In Rumelhart, D. E. and (ed.), J. L. M., editors, Parallel Distributed Processing:
Explorations in the Microstructure of Cognition, volume 1: Foundations. MIT Press.

Contents
1 Introduction 2

2 Le perceptron 3
2.1 Formulation mathématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Vectorisation des équations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Programmation sous Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Réseau artificiel à 2 couches 15


3.1 Formulation mathématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Vectorisation des équations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 Programmation sous Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

4 Perceptron multi-couches 26
4.1 Partitionnement des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2 Entraı̂nement du modèle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
´
4.3 Evaluation du modèle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5 Projet complet avec la librairie TensorFlow 32


5.1 Prétraitement et exploration des données . . . . . . . . . . . . . . . . . . . . . . . . 32
5.2 Construction, entraı̂nement et évaluation du modèle . . . . . . . . . . . . . . . . . . 35

6 Conclusion 39

40

Vous aimerez peut-être aussi