Introduction à l'apprentissage automatique - TP6 exercice 2

Classification d'images au XXIème siècle: CNN et transfer learning


Remarque préliminaire: il s'agit plus d'un tutoriel que d'un exercice. Vous n'avez pas de code à écrire, mais passez y suffisamment de temps et assurez-vous de bien comprendre.


Dans cet exercice, nous mettons en oeuvre des réseaux de neurones convolutifs. Nous allons utiliser la bibliothèque Tensorflow par l'intermédiaire de l'API Keras qui simplifie la manipulation des réseaux. Notez les nombreuses ressources pédagogiques sur la page web de Tensorflow, qui pourront vous être utiles en stage, pour un projet, etc.

Commencez par prendre connaissance des pages suivantes:


Installez Tensorflow et Keras si ce n'est déjà fait:


Notre exercice est partiellement une adaptation simplifiée de cette page du blog de François Chollet, papa de Keras. Lisez cette page à la fin du TP, notamment ce qui concerne la génération d'images synthétiques pour augmenter la base d'apprentissage, que nous n'abordons pas dans cet exercice par souci de simplification. Par ailleurs, le problème chiens et chats du blog ne concerne que deux classes alors que le nôtre est multiclasses (6 classes à identifier):

0. Préparatifs

On commence par charger quelques bibliothèques et définir la fonction display_test (comme dans l'exercice précédent).

On charge à présent les données. Cette fois, nos classifieurs vont admettre directement les images en entrée, et pas des descripteurs comme les histogrammes de l'exercice 1. Comme les réseaux de neurones utilisés exigent des images de taille identique en entrée, il va falloir redimensionner les images de la base de données avant de les stocker dans les tableaux X_train et X_test. On choisit une taille de redimensionnement de $150\times 100$ pixels (150 colonnes et 100 lignes), ce qui a l'avantage de ne pas trop déformer la majorité des images (l'"aspect ratio" est globalement conservé).


1. Classification par un réseau convolutif

Nous allons tester le premier réseau étudié dans le blog de F. Chollet, inspiré des réseaux convolutifs comme LeNet5 proposés par Yann Le Cun dans les années 1990.

Le réseau est formé des couches suivantes.

Partie "définition de descripteurs" ( features ):

Partie "classification", qui ressemble au perceptron multi-couches de l'exercice précédent:

Ce modèle nécessite l'apprentissage de 725 414 paramètres... Par exemple, la seconde couche de convolution nécessite l'estimation de 9248 paramètres. En effet, elle effectue 32 convolutions de taille $3 \times 3 \times \text{(épaisseur de la sortie de la couche précédente)}$, soit: $(9\times 32+1)\times 32 = 9248$ paramètres (la couche précédente effectue 32 convolutions, et +1 car il faut ajouter le terme de biais).

Remarquez que les couches convolutives "rognent" les bords (à cause du traitement des effets de bord lorsque le noyau de convolution "dépasse" des bords du domaine où il est appliqué). Cela explique pourquoi la première couche part d'images de taille $100\times 150$ et aboutit à un résultat de taille $98\times 148$.


L'apprentissage proprement dit se lance dans la cellule suivante. Notez la taille des batches utilisés ainsi que le nombre d'epochs. Les données de validation ne sont pas utilisées pour l'apprentissage, seulement à titre indicatif pour surveiller un surapprentissage potentiel, comme expliqué en cours.

Constatez que ce réseau convolutif présente de meilleures performance que le meilleur modèle de l'exercice 1 (si ce n'est pas le cas, vous n'avez pas eu de chance: relancez l'apprentissage...)

Vérifiez le rôle du dropout: commentez la ligne model.add(Dropout(0.5)) dans ce qui précède, et relancez la construction puis l'apprentissage du réseau. Vous allez voir le réseau apprendre "par coeur" la base d'apprentissage (accuracy=1) mais une performance moindre sur la base de test.

Remarque: il ne faut pas perdre de vue que notre base de données est assez petite: deux erreurs sur la base test font baisser le score de classification ( accuracy ) de 1%.


La cellule suivante permet de calculer la sortie du réseau (predict). Il s'agit des probabilités a posteriori de chaque classe, on assigne donc chaque observation à la classe de probabilité maximale, selon le principe MAP. Seuls quelques papillons semblent encore poser problème...