Vous êtes sur la page 1sur 12

TP informatique

S3 - Chapitre 3: Algorithmes pour l’IA


TP: Reconnaissance de panneaux par un algorithme kNN – Énoncé

I Mise en situation
I.1 La reconnaissance des panneaux par les voitures

Les systèmes de reconnaissance des panneaux


de signalisation embarqués dans les voitures
récentes ont amélioré la sécurité des conduc-
teurs, des passagers mais aussi des piétons.
Une application au limiteur de vitesse au-
tomatique est possible ainsi lorsque le véhi-
cule reconnait un panneau de limitation de
vitesse et qu’il roule à une vitesse supérieure
à celle autorisée, alors il ralentit de lui-même
afin d’avancer à une vitesse autorisée (voir Fi-
gure 1). Figure 1 – Principe du limiteur de vitesse auto-
matique

I.2 Difficultés liées à la compréhension des panneaux


La détection des panneaux de signalisation est un procédé complexe. En effet les images sont acquises
alors que le véhicule est en mouvement, par conséquent elles peuvent être dégradées par la présence
de vibrations, de lignes floues, de variations de lumière... Aussi la présence d’objets de formes et de
couleurs similaires aux panneaux peut fausser la détection. Il faut donc passer par une phase de pré-
traitement (Figure 2) pour que l’image du panneau détecté soit de bonne qualité en vue de la phase
de reconnaissance automatique (est-ce une limitation de vitesse, un sens interdit etc...).

Figure 2 – Exemple de « Remise à plat » des formes détectées

Algorithmes pour l’IA 1/12


TP informatique

Dans le cadre de ce TP, le prétraitement a déjà été réalisé. Plusieurs panneaux ont été détectés par
le véhicule, les images obtenues sont situées dans le dossier Recherche. Le dossier Source contient
des images de références de panneaux connus (Figure 3) et qui serviront pour l’apprentissage des
nouveaux panneaux du dossier Recherche. Toutes les images ont les mêmes dimensions (100 lignes et
100 colonnes) et possèdent le même nombre de pixels RGB (100×100=10000).

Figure 3 – Les différents panneaux de signalisations connus dans le dossier Source

Objectif
On souhaite pouvoir mener une procédure d’apprentissage supervisé en associant les panneaux incon-
nus du dossier Recherche aux panneaux déjà connus du dossier Source grâce à un algorithme des k
plus proches voisins (ou kNN pour k Nearest Neighbors en américain).

I.3 Matériel de travail


Répertoire de travail
Dans les parties II, III, IV, V et VI de ce TP on utilisera la trame fournie dans le code
Etablissement_kNN.py du dossier Codes\Etablissement_kNN.

Dans la partie VII on utilisera la trame fournie dans le code Utilisation_scikit.py du dossier
Codes\Utilisation_scikit.

Librairies utilisées
Dans ce TP les librairies suivantes seront utilisées : matplotlib.pyplot, mglearn, numpy, math et
sklearn. Il est possible de les télécharger avec la commande pip install nom_librairie dans le
Prompt d’Anaconda.

Algorithmes pour l’IA 2/12


TP informatique

II Principe de l’algorithme kNN


Le pseudo-code de l’algorithme kNN est le suivant :
Algorithme 1 : Idée de l’algorithme kNN
Entrées :
• Plusieurs listes de données étiquetées connues ;
• un ou plusieurs éléments à identifier ;
• le nombre de plus proches voisins à considérer (ici k).
#
Initialisation :
Écrire les coordonnées de chaque élément (données étiquetées ou éléments à identifier) dans le
même format ;.
#
Calcul des distances euclidiennes entre chaque élément à identifier et l’ensemble des données
étiquetées connues :
pour chaque élément à identifier faire
pour chaque donnée étiquetée faire
Stocker dans un même support (liste, tableau...) la distance euclidienne entre un
élément à identifier et une donnée étiquetée
fin
fin
#
Identification des k plus proches voisins pour chaque élément à identifier :
pour chaque ensemble de distances entre un élément à identifier et toutes les données
étiquetées faire
Relever les k plus petites distances et les étiquettes des données connues associées
fin
#
Décompte du plus grand nombre d’occurences pour déduire la nature de l’élément à identifier
pour chaque ensemble de k plus proches voisins pour un élément à identifier faire
Associer l’élément à identifier à la donnée étiquetée qui revient le plus dans les k plus
proches voisins
fin

Grâce à la librairie mglearn et à sa base de données déjà disponible, on peut avec le code ci-dessous
obtenir une illustration de l’algorithme kNN en Figure 4.

1 import matplotlib . pyplot as plt


2 import mglearn
3
4 plt . figure ()
5 # On pioche dans les données de la librairie mglearn
6 # pour donner une illustration de l’algorithme kNN
7 mglearn . plots . plot_knn_classification ( n_neighbors =3)
8 plt . show ()

Algorithmes pour l’IA 3/12


TP informatique

3 training class 0
training class 1
test pred 0
2 test pred 1

1
8.0 8.5 9.0 9.5 10.0 10.5 11.0 11.5 12.0

Figure 4 – Illustration des 3 plus proches voisins au sens de la norme euclidienne pour 3 points tests
(les étoiles) et 2 sources étiquetées connues (les points bleus et triangles oranges), les étoiles sont de
la couleur de la donnée étiquetée qui revient le plus dans les 3 plus proches voisins

III Mise en place de l’algorithme kNN


Pour mettre en place l’algorithme kNN il faut mettre en place les étapes suivantes :
(1) le calcul de la distance euclidienne entre 2 vecteurs ;
(2) la détermination des k plus proches voisins d’une donnée à tester ;
(3) la prédiction de la classe de la donnée testée.
Les sous-sections qui suivent visent à écrire des fonctions qui répondent aux points (1) et (2). On
répondra au point (3) lorsque les images auront été préparées en vue d’appliquer la fonction de déter-
mination des k plus proches voisins.

III.1 Distance euclidienne entre 2 vecteurs


Soient u = (u0 , u1 , ..., un−1 ) et v = (v0 , v1 , ..., vn−1 ) 2 vecteurs de même taille n. La distance euclidienne
deuc entre ces 2 vecteurs vaut par définition :
v
un−1
uX
deuc =t (vi − ui )2
i=0

Q1. Écrire une fonction DistanceEuclidienne(u,v) qui prend pour entrées 2 listes u et v de même
taille n et qui renvoie la distance euclidienne associée à ces 2 n-uplets.

Algorithmes pour l’IA 4/12


TP informatique

III.2 k plus proches voisins


Q2. Écrire une fonction ListeDistances(u,liste_v) qui prend pour entrées un n-uplet u et une liste
de n-uplets liste_v. Cette fonction renvoie une liste de distances entre u et chaque n-uplet de liste_v
avec l’indice associé.

Q3. Écrire une fonction PlusProchesVoisins(u,liste_v,k) qui renvoie une liste des k plus proches
voisins de u dans la liste liste_v au sens de la norme euclidienne, à partir du résultat de la fonction
ListeDistances(u,liste_v). À quelle condition sur k cette fonction marche-t-elle ?

Remarque : on autorise l’utilisation de liste.sort() pour trier les éléments de liste en place par
rapport à la première composante de tous ses éléments (les distances ici).

IV Lecture des images


On souhaite dans cette partie adapter les images de panneaux afin de pouvoir appliquer l’algorithme
kNN défini dans la section précédente. Il faut donc traduire l’information d’une image en une liste.

On donne la fonction suivante pour montrer une image à partir de l’array correspondant :

1 import matplotlib . pyplot as plt


2 plt . close ( ’ all ’) # On ferme toutes les figures déjà affichées
3
4 def AfficheImage ( array_image ):
5 plt . figure () # Création d’une fen^ etre de figure
6 plt . imshow ( array_image ) # Appel de l’image désirée
7 plt . axis ( ’ off ’) # Pas de système d’axes sur la figure
8 plt . show () # Affichage de l’image désirée lors de l’appel de la fonction
9 plt . pause (0.00001) # Petite pause pour éviter des bugs d’affichage

À partir d’une image au format array d’entiers codés sur 8 bits, la fonction AfficheImage affiche
cette image sur une figure.

On rappelle que l’ouverture au format array d’une image se réalise avec la commande imread en
indiquant le chemin d’accès à l’image chemin_image :

1 plt . imread ( chemin_image )

Q4. Écrire une fonction LectureImage(chemin_image) qui renvoie l’array associé à l’image de che-
min contenu dans la variable chemin_image. Quelles sont les dimensions de l’array obtenu ? À quoi
correspondent-elles ?

V Fonctions d’analyse des images


Il a été vu que la conversion d’une image en array donnait une matrice en 3 dimensions. Or l’algorithme
kNN défini en partie III ne prend pour entrées que des listes. Il faut alors chercher à convertir la matrice
3D d’une image en liste.

Algorithmes pour l’IA 5/12


TP informatique

V.1 Conversion d’un array d’une image en liste


Q5. Écrire une fonction ConversionArrayList(image_array) qui prend pour entrée une image sous
forme d’array et qui renvoie la liste des couleurs de chaque pixel l’un après l’autre comme dans
l’exemple ci-dessous :

1 image_array = np . array ([[[1 ,2 ,3] ,[4 ,5 ,6]] ,[[7 ,8 ,9] ,[10 ,11 ,12]]])
2 image_array . shape
3 >>> (2 ,2 ,3) # image_array est une image 2×2 pixels avec 3 couleurs
4 image_liste = ConversionArrayList ( image_array )
5 print ( image_liste )
6 >>> [1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0 , 8.0 , 9.0 , 10.0 , 11.0 , 12.0]

Remarque : On précisera dans le code que les valeurs contenues dans image_array sont des flottants
afin d’éviter les problèmes de calculs des distances euclidiennes.

Q6. Écrire une fonction ConversionArrayListGlobale(liste_chemins) qui prend pour argument la


liste des chemins des différentes images du dossier Source et qui renvoie la liste des listes de couleurs
RGB associées à chacune des images du dossier. On prévoira l’affichage de l’avancée de la fonction
avec le texte ’Apprentissage image 1 sur 40’ par exemple.

V.2 Création de la base de données


Il y a 8 dossiers numérotés de 0 à 7 dans le dossier Source, chacun comporte plusieurs images d’un
même panneau bien connu. On donne les listes suivantes :

1 Dossiers = [0 ,1 ,2 ,3 ,4 ,5 ,6 ,7] # Nom des différents dossiers


2 nb_images_dossiers = [5 ,5 ,5 ,5 ,5 ,5 ,5 ,5] # Nombre d’images dans chaque dossier

Chaque image contenue dans le dossier source possède :


• un chemin ;
• un numéro de dossier ;
• un numéro d’image.
On souhaite créer les 3 listes liste_chemins, liste_dossiers et liste_num qui, pour un même in-
dice (et donc une même image), contiennent les 3 informations de la liste à puces précédente. Pour la
suite on appellera « Indice d’une image » son indice dans ces 3 listes.

Q7. Écrire une fonction InfosImages(liste_nom_dossiers,liste_nb_images_dossiers) qui prend


en entrées la liste des numéros de dossiers et la liste du nombre d’images dans chaque dossier puis
renvoie les listes liste_chemins, liste_dossiers et liste_num définies précédemment. On affichera
les résultats de la manière suivante :

Algorithmes pour l’IA 6/12


TP informatique

1 liste_chemins = \
2 InfosImages ( Dossiers ,\
3 nb_images_dossiers )[0]
4 print ( liste_chemins )
5 >>> [ ’ Source \\0\\0. bmp ’ , 1 liste_dossiers = \ 1 liste_num = \
6 ’ Source \\0\\1. bmp ’ , 2 InfosImages ( Dossiers ,\ 2 InfosImages ( Dossiers ,\
7 ’ Source \\0\\2. bmp ’ , 3 nb_images_dossiers )[1] 3 nb_images_dossiers )[2]
8 ’ Source \\0\\3. bmp ’ , 4 print ( liste_dossiers ) 4 print ( liste_num )
9 ’ Source \\0\\4. bmp ’ , 5 >>> [0 , 0 , 0 , 0 , 0 , 5 >>> [0 , 1 , 2 , 3 , 4 ,
10 ’ Source \\1\\0. bmp ’ , 6 1, 1, 1, 1, 1, 6 0, 1, 2, 3, 4,
11 ’ Source \\1\\1. bmp ’ , 7 2, 2, 2, 2, 2, 7 0, 1, 2, 3, 4,
12 ’ Source \\1\\2. bmp ’ , 8 3, 3, 3, 3, 3, 8 0, 1, 2, 3, 4,
13 ’ Source \\1\\3. bmp ’ , 9 4, 4, 4, 4, 4, 9 0, 1, 2, 3, 4,
14 ’ Source \\1\\4. bmp ’ , 10 5, 5, 5, 5, 5, 10 0, 1, 2, 3, 4,
15 ... , 11 6, 6, 6, 6, 6, 11 0, 1, 2, 3, 4,
16 ’ Source \\7\\0. bmp ’ , 12 7 , 7 , 7 , 7 , 7] 12 0 , 1 , 2 , 3 , 4]
17 ’ Source \\7\\1. bmp ’ ,
18 ’ Source \\7\\2. bmp ’ ,
19 ’ Source \\7\\3. bmp ’ ,
20 ’ Source \\7\\4. bmp ’]

VI Reconnaissance automatique des panneaux inconnus


Le dossier Recherche contient les images de tous les panneaux à identifier grâce à l’algorithme kNN.
Ces images sont toutes issues d’une photo en situation réelle et le premier numéro de leur nom corres-
pond au dossier auquel elles devraient appartenir.

Les images sources ayant un fond blanc, l’algorithme s’adapte automatiquement à n’importe quel fond.
En effet, une image recherchée ayant un fond quelconque sera à la même « distance » que toutes les
images sources sur la partie extérieur, l’algorithme sélectionnera alors celle qui se rapproche le plus
dans la comparaison du contenu intérieur du panneau.

Q8. En utilisant les fonctions précédemment établies, écrire un code qui permet d’ouvrir, d’afficher et
d’analyser (création de sa liste liste_RGB) une image du dossier Recherche au choix.

Q9. Toujours à partir des fonctions déjà disponibles, écrire un code qui détermine les k = 5 plus proches
voisins de l’image recherchée et crée les listes resultat_ind (indices des images résultats), resul-
tat_dossiers (dossiers correspondants) et resultat_num (numéros des images dans les dossiers). Ce
code doit afficher dans la console les dossiers et numéros des images trouvées.

Q10. Écrire une fonction MaxOccurences(liste) qui renvoie le terme qui apparait le plus dans la liste
liste, et le plus petit s’il y a des exæquo. Vérifier :

1 liste = [3 ,3 ,1 ,2 ,3] 1 liste = [1 ,3 ,1 ,2 ,3]


2 print ( MaxOccurences ( liste )) 2 print ( MaxOccurences ( liste ))
3 >>> 3 3 >>> 1

Q11. Écrire un code permettant de déterminer le dossier résultat, qui l’affiche dans la console et affiche
l’une des images de ce dossier.

Algorithmes pour l’IA 7/12


TP informatique

VII Algorithme kNN avec la librairie scikit-learn


Dans le cadre de l’initiation à l’Intelligence Artificielle, il peut être demandé d’utiliser des librairies
pour appliquer l’algorithme des k plus proches voisins. La librairie la plus utilisée et la plus complète à
l’heure actuelle est scikit-learn, appelée avec la commande import sklearn dans Python. Cette li-
brairie est complétées par mglearn qui contient des jeux de données pour illustrer les principes de l’IA.

Toutefois comme toute librairie à partir de laquelle on peut faire appel à des fonctions dont on ne
connait pas facilement le code source, il faut faire appel à de la documentation technique pour bien
l’utiliser. La documentation de scikit-learn est disponible à l’adresse suivante :
https://scikit-learn.org/stable/index.html

Pour rappel on utilisera la trame Utilisation_scikit.py du dossier Codes\Utilisation_scikit.

Le cahier des charges des performances attendues de l’algorithme kNN pour ce problème est le suivant :

Critère Niveau
Données test parmi les données source 25%
Valeur de k optimale Maximise l’exactitude et la précision
Exactitude pour k optimal > 80%
Précision pour chaque type de source et pour k optimal > 80%

Table 1 – Extrait du cahier des charges concernant les performances de l’algorithme kNN avec les
sources à disposition

VII.1 Identification d’un panneau inconnu avec NearestNeighbors


Ici on s’intéressera à la fonction NearestNeighbors de la documentation liée à l’algorithme kNN :
https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.NearestNeighbors.
html?highlight=nearestneighbors#sklearn.neighbors.NearestNeighbors

Q12. En utilisant la documentation de scikit-learn, proposer un code qui permet de retrouver le


même dossier identifié qu’en question Q11. Une réutilisation d’une partie des fonctions définies dans
ce TP sera nécessaire.

VII.2 Tracé de la matrice de confusion avec KNeighborsClassifier


Dans le cadre d’un apprentissage supervisé avec l’algorithme kNN, on souhaite contrôler la qualité du
choix du paramètre k. Pour cela on prend les données sources (connues) et on les sépare en 2 parties :
• des données dites d’« Apprentissage » dont on connait les étiquettes qui serviront de référence
pour le contrôle de qualité de l’algorithme ;
• des données de « Test » dont on supposera les étiquettes qui permettront de valider l’algorithme
(car initialement toutes les données ont des étiquettes connues).
On peut alors lancer la prédiction des étiquettes des données de test pour évaluer les erreurs qui sont
affichées dans une matrice de confusion.

Algorithmes pour l’IA 8/12


TP informatique

On donne le code ci-dessous qui permet de construire la matrice de confusion d’un jeu de données
grâce à sklearn :

1 # Commentaire à compléter...
2 X , y = make_classification ( random_state =0)
3
4 # Commentaire à compléter...
5 X_train , X_test , y_train , y_test = train_test_split (X , y , random_state =0)
6
7 # Commentaire à compléter...
8 clf = KNeighborsClassifier ( n_neighbors =5)
9
10 # Commentaire à compléter...
11 clf . fit ( X_train , y_train )
12
13 # Commentaire à compléter...
14 p lo t_ c on fusion_matrix ( clf , X_test , y_test )
15 plt . show ()

Q13. En s’appuyant sur la documentation du site https://scikit-learn.org/stable/index.html,


expliquer en complétant les commentaires du code ci-dessus le rôle des fonctions make_classification,
train_test_split, KNeighborsClassifier et fit. Donner le type et la longueur des variables X, y,
X_train, X_test, y_train et y_test. Comment assurer un nombre d’échantillons test égal à un quart
du nombre total d’échantillons ?

Remarque : la variable random_state est un argument non obligatoire écrit comme un entier qui
assure la reproductibilité des résultats. Avec random_state = n (avec n un entier au choix entre 0 et
42) et en lançant le code plusieurs fois d’affilée, les variables X et y sont toujours les mêmes.

La matrice de confusion obtenue pour le test précédent est donnée en Figure 5. la figure Figure 6
est obtenue avec la librairie pédagogique mglearn et la commande :

1 plt . figure ()
2 mglearn . plots . p l ot _ b in a r y_ c o n fu s i on _ m at r i x ()
3 plt . tight_layout () # Toute la figure rentre dans la fen^ etre affichée
4 plt . show ()

Algorithmes pour l’IA 9/12


TP informatique

TN FP
11
10
9
negative class
0 11 2
8

FN TP
7
True label

6
5
1 5 7
4 positive class
3
2
0 1
Predicted label predicted negative predicted positive

Figure 5 – Matrice de confusion obtenue avec le Figure 6 – Aide à l’interprétation de la matrice


code fourni pour k = 5 de confusion
L’interprétation est la suivante :
• Parmi les données test qui s’avéraient être négatives (negative class) un certain nombre est prédit
comme négatif (predicted negative), ce sont des TN pour True Negative ;
• Parmi les données test qui s’avéraient être positives (positive class) un certain nombre est prédit
comme positif, ce sont des TP pour True Positive ;
• Parmi les données test qui s’avéraient être positives (positive class) un certain nombre est prédit
comme négatif, ce sont des FN pour False Negative ;
• Parmi les données test qui s’avéraient être négatives (negative class) un certain nombre est prédit
comme positif, ce sont des FP pour False Positive ;
En sommant tous les nombres dans la matrice de confusion on doit retrouver l’ensemble des données
test. On définit l’exactitude e et la précision (en positifs ppos ou négatifs pneg ) de la manière suivante :

TP + TN TP TN
e= ; ppos = ; pneg =
TP + TN + FP + FN TP + FP TN + FN
Pour exploiter la matrice de confusion on peut l’obtenir textuellement en remplaçant la commande
appelant l’illustration de la matrice par :

1 # Affichage de la matrice de confusion


2 #plot_confusion_matrix(clf, X_test, y_test)
3 #plt.show()
4
5 predict_y = clf . predict ( X_test )
6 mat_conf = confusion_matrix ( y_test , predict_y )
7 print ( mat_conf )
8 >>> [[11 2]
9 [ 5 7]]

Algorithmes pour l’IA 10/12


TP informatique

Q14. Écrire une fonction MatriceConfusion(liste_noms_dossiers,liste_nb_images_dossiers,k)


qui prend pour entrées :
• liste_noms_dossiers : la liste contenant les noms des dossiers ;
• liste_nb_images_dossiers : la liste contenant le nombre d’images dans chaque dossier ;
• k le paramètre de l’algorithme kNN.
Cette fonction renverra la matrice de confusion sous forme de figure et de tableau. Faire le test pour
k = 5.

Remarque : vu le grand nombre de noms de dossiers source (8) et le faible nombre d’images par dos-
sier (5), il se peut que des lignes de la matrice de confusions soient nulles. Dans ce cas les fonctions
plot_confusion_matrix et confusion_matrix ne retrouvent pas tous les noms et n’arrivent pas à tra-
cer la matrice de confusion. On aidera les fonctions en rajoutant l’option labels=liste_noms_dossiers,
soit :

1 p lo t_ c on fusion_matrix ( clf , X_test , y_test , labels = liste_noms_dossiers )


2 confusion_matrix ( y_test , predict_y , labels = liste_noms_dossiers )

Q15. Écrire une fonction Exactitude(liste_noms_dossiers,liste_nb_images_dossiers,k) qui pos-


sède les mêmes entrées que dans la question précédente et qui renvoie l’exactitude de l’algorithme.

Q16. Écrire une fonction Precision(liste_noms_dossiers,liste_nb_images_dossiers,k) qui pos-


sède les mêmes arguments que dans la question précédente et qui renvoie une liste contenant la précision
pour chaque type de source.

Q17. Écrire une fonction PlotExactitude(liste_noms_dossiers,liste_nb_images_dossiers) qui


renvoie le graphe de l’évolution de l’exactitude en fonction de la valeur de k. On fera attention à la
plage de valeurs que peut prendre k.

Q18. Écrire une fonction PlotPrecision(liste_noms_dossiers,liste_nb_images_dossiers) qui


renvoie sur un même graphe de l’évolution de chaque précision en fonction de k.

Q19. Conclure vis-à-vis du cahier des charges.

Algorithmes pour l’IA 11/12


TP informatique

VIII Ouverture : augmentation du nombre de données source à disposition


On peut ajouter des panneaux dans le dossier Source, ou utiliser cet algorithme sur d’autres images.
Pour créer les images sources dans un dossier existant :
(1) ouvrir Paint (Windows), et y coller une image d’un panneau ;
(2) déplacer le panneau afin que ses bords soient collés en haut et à gauche, puis redimensionner
l’image par déplacement des côtés bas et droite pour finalement coller au panneau sur les 4 côtés ;
(3) utiliser l’outil « Sélectionner » puis « Sélection libre », détourer proprement les 4 zones à
supprimer suivi de « Suppr » ;
(4) utiliser l’outil « Redimensionner », cliquer sur « Pixels », vérifier que l’image est carrée (sinon,
refaire le cadre), mettre 100 en horizontal, et si besoin, décocher « Conserver les proportions »,
et mettre 100 en verticale ;
(5) Faire « Fichier » puis « Enregistrer sous », mettre le format BMP, et enregistrer l’image avec
un numéro (supérieur à 4 dans notre cas).
On peut aussi ajouter un nouveau dossier dans Source avec un nouveau type de panneau, mais les
images doivent toutes être de la même taille que dans les autres dossiers. On essaiera d’avoir aussi le
même nombre d’images dans chaque dossier.

Attention : Veiller à ne pas ajouter plusieurs fois la même image, cela fausserait les résultats.

Algorithmes pour l’IA 12/12

Vous aimerez peut-être aussi