Practical session
Duration1h30Présentation & objectifs
L’objectif de cette séance est de mettre en pratique la programmation orientée objet dans le contexte de l’intelligence artificielle, en particulier avec les approches d’apprentissage supervisé.
Le but de cette séance est de vous aider à maîtriser des notions importantes en informatique. Un assistant de programmation intelligent tel que GitHub Copilot, que vous avez peut-être déjà installé, pourra vous fournir une solution à ces exercices uniquement à partir d’un nom de fichier judicieusement choisi.
Pour l’entraînement, nous vous conseillons de désactiver d’abord ces outils.
À la fin de l’activité pratique, nous vous suggérons de refaire l’exercice avec ces outils activés. Suivre ces deux étapes améliorera vos compétences à la fois de manière fondamentale et pratique.
De plus, nous vous fournissons les solutions aux exercices. Assurez-vous de ne les consulter qu’après avoir trouvé une solution aux exercices, à des fins de comparaison ! Même si vous êtes sûr que votre solution est correcte, veuillez les consulter, car elles fournissent parfois des éléments supplémentaires que vous auriez pu manquer.
1 — Implémenter un classifieur générique en utilisant la POO
Implémentez un objet qui sera un classifieur générique avec les méthodes fit
, predict
et score
.
La classe doit être définie dans un fichier nommé classifiers.py
et s’appeler GenericClassifier.
Le but de cet objet est de définir comment un classifieur doit se comporter, et nous utiliserons cette classe dans les prochains exercices pour implémenter effectivement des algorithmes d’apprentissage automatique.
- La classe doit avoir un constructeur sans paramètres.
- La méthode
fit
prend deux paramètresX
ety
(tous deux de typenp.ndarray
) et sera utilisée pour entraîner le modèle (ici, elle ne fait rien). - La méthode
fit
modifie un attribut booléen privéself._isfitted
de la classe pour indiquer que le modèle a été entraîné. - La méthode
predict
prend un seul paramètreX
(de typenp.ndarray
) et retourne les labels préditspredictions
. - La méthode
score
prend deux paramètresX
ety
(tous deux de typenp.ndarray
) et retourne la précision du modèle sur les données donnéesX
selon les labels de vérité terrainy
. - Les méthodes
predict
etscore
retournent une erreur si elles sont appelées alors que le modèle n’a pas encore été entraîné.
Ensuite, créez un fichier de test nommé test_classifier.py
qui teste les trois méthodes de la classe individuellement.
2 — Implémenter un classifieur $k$-NN en utilisant le classifieur générique
Implémentez le classifieur KNN codé dans la session algoS6 en utilisant une instance héritant de GenericClassifier.
La classe doit être définie dans un fichier nommé knn_classifier.py
et s’appeler KNNClassifier.
Le paramètre k
est spécifique à une instance de la classe.
- La classe doit avoir un constructeur héritant de GenericClassifier, et qui prend un seul paramètre
k
qui est le nombre de voisins à considérer. - La méthode
fit
prend deux paramètresX
ety
(tous deux de typenp.ndarray
) et entraîne le modèle en utilisant l’algorithme décrit dans la session algo 6. - La méthode
predict
prend un seul paramètreX
(de typenp.ndarray
) et retourne les labels prédits. - La méthode
fit
modifie un attribut booléen privéself._isfitted
de la classe pour indiquer que le modèle a été entraîné. - La méthode
predict
retourne une erreur si elle est appelée alors que le modèle n’a pas encore été entraîné. - Vous n’avez pas à réimplémenter la méthode
score
car sa définition est héritée de GenericClassifier.
Ensuite, créez un fichier nommé main.py
qui utilise la classe pour entraîner un modèle sur le jeu de données digits et afficher la précision du modèle sur le jeu de test.
Voici un extrait de code pour charger le jeu de données digits :
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
# Load the digits dataset
digits = load_digits()
# Split the data into a training and test set
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, random_state=0)
Idéalement, vous créez aussi un fichier de test nommé test_knn_classifier.py
qui teste les trois méthodes de la classe individuellement.
3 — Implémenter l’assemblage de modèles (model ensembling)
Maintenant que vous avez implémenté le classifieur, vous pouvez les utiliser pour créer un modèle ensembliste.
Codez une classe ModelEnsemble qui hérite de GenericClassifier, prend en argument une liste de classifieurs entraînés, et effectue un vote majoritaire de tous les classifieurs.
La classe doit être définie dans un fichier nommé model_ensemble.py
et s’appeler ModelEnsemble.
- La classe prend en argument une liste de classifieurs entraînés.
- À l’initialisation de la classe, elle lève une erreur si la liste fournie de classifieurs est vide.
- La classe doit implémenter une méthode
fit
qui vérifie que tous les classifieurs de la liste ont été entraînés auparavant. - La classe doit avoir une méthode
predict
qui prend un seul paramètreX
(de typenp.ndarray
) et retourne les labels prédits. Cette méthode retourne une erreur si les classifieurs de la liste n’ont pas été entraînés auparavant.
Ensuite, créez un fichier nommé main.py
qui utilise la classe pour entraîner un modèle ensembliste sur le jeu de données digits et afficher la précision du modèle sur le jeu de test. Comme modèle ensembliste, vous pouvez utiliser une liste de KNN avec différentes valeurs de K.
4 — Assemblage de modèles avec validation croisée
Analysez les performances du modèle ensembliste de la section précédente. La précision devrait être très élevée, et le modèle ensembliste n’est pas significativement meilleur que les modèles individuels.
Afin de mieux voir l’intérêt des modèles ensemblistes, et aussi pour montrer un cas d’usage plus réaliste de l’assemblage de modèles, nous allons simuler une situation dans laquelle chaque classifieur voit une répartition différente des données d’entraînement :
- Gardez le jeu de test
X_test,y_test
identique à celui de l’exercice précédent - Divisez l’ancien jeu d’entraînement
X_train,y_train
enP
sous-ensembles différents - Entraînez
P
algorithmes K-NN indépendamment sur chaque sous-ensemble, avec la même valeur de K. Comme les partitions sont différentes, chaque K-NN aura une performance légèrement différente sur le jeu de test. - Évaluez la performance sur un modèle ensembliste prenant tous les
P
K-NN.
Vous pouvez expérimenter avec ce cadre, en utilisant un nombre différent de partitions P
, et différentes valeurs de K. Nous suggérons de commencer avec P=5
et K=1
, mais n’hésitez pas à expérimenter.
5 — Optimisez vos solutions
Ce que vous pouvez faire maintenant est d’utiliser des outils d’IA tels que GitHub Copilot ou ChatGPT, soit pour générer la solution, soit pour améliorer la première solution que vous avez proposée ! Essayez cela pour tous les exercices ci-dessus, pour voir les différences avec vos solutions.
Pour aller plus loin
6 — Implémenter une recherche en grille avec validation croisée
Codez une classe CVGridSearch qui prend un jeu de données (données et labels), une plage d’un hyperparamètre (par exemple une plage de valeurs entières de K), divise en un jeu d’entraînement et de validation, et utilise le jeu de validation pour optimiser le meilleur hyperparamètre. Vous pouvez vérifier la validité sur votre implémentation KNN.
Pour aller encore plus loin
7 — Perceptron multicouche
Le perceptron multicouche (MLP) est un bloc de base très couramment utilisé dans les solutions d’apprentissage automatique basées sur le Deep Learning. Cette page utilise une définition de classe pour construire un MLP from scratch en utilisant numpy.
8 — Différentiation automatique
Une autre application intéressante (mais complexe) de la programmation orientée objet est donnée par pytorch, avec la notion de différentiation automatique. En résumé, pytorch effectue des opérations sur des tenseurs comme numpy, mais pytorch suit automatiquement l’historique et les dépendances entre tous les calculs et leurs gradients. Cela permet une implémentation très directe des architectures de Deep Learning. Plus d’informations peuvent être trouvées dans la documentation officielle de pytorch.
Vous pouvez aussi trouver un tutoriel complet pytorch ici