Dataset utilisé
Ce projet utilise un dataset téléchargeable gratuitement sur Kaggle.
Special thanks to Samir Bhattarai for this amazing dataset !
Découvrir le Transfer Learning⚓
Principe
Voir également Découverte IA
Étape 1 : Réseau modifié
Matlab permet de charger un réseau pré-entraîné existant, et de le modifier pour l'adapter à nos besoins.
La modification se limite à modifier les deux couches
classification layer : remplacer la couche existante par une nouvelle couche de classification vierge avec en output size le nombre de classes à identifier
output layer : remplacer la couche existante par une nouvelle couche output vierge le nombre de classes à identifier
Étape 2 : Fichiers images
Les images sont le plus souvent organisées dans une arborescence. Sous Matlab nous pourrons utiliser les "imageDatastore", une variable qui regroupe les images situées dans un répertoire (avec ou non des sous-répertoires).
L'utilisation des imageDatastore ont plusieurs avantages intéressants
si il faut retailler les images pour les adapter au cnn, le datastore permet de retailler automatiquement chaque image avant le traitement
les images sont tirées une par une du datastore de façon transparente au moment du traitement, ce qui évite de charger toutes les images en mémoire
Matlab sait répartir les images pour avoir un ensemble pour le training et un ensemble pour le test
Étape 3 : options
On peut très bien lancer l'entraînement avec les options par défaut au début.
Étape 4 : entraînement et évaluation
Le temps de calcul peut être très long (plusieurs heures). Il faut donc penser à enregistrer le nouveau réseau en fin de calcul !
Après l'entraînement, le réseau peut être utilisé, on cherchera à contrôler la matrice de confusion pour valider la précision du réseau.
Comment faire ?
Explquer : datastore, imagedatastore, pool pour training / pour test etc...
Entraîner un cnn : epochs, iteration, mini-batch...
Explication des concepts
comment afficher la progression du training.
Exercice
Entraînement d'un réseau
Entraînement d'un réseau neuronal : ligne de commande⚓
Étape 1 : réseau modifié
% chargement du cnn googlenet
net = googlenet
% récupération des layers
lay = net.Layers
% voir les détails de la input layer
inLayer = lay(1)
% connaître le format d'image en entrée
inSize = inLayer.InputSize
% récupération des layers (structure du réseau)
lgraph = layerGraph(net);
% création d'une couche neuronale pour 38 classes
newFc = fullyConnectedLayer(38,"Name","new_fc");
% on remplace la couche existante par la nouvelle
lgraph = replaceLayer(lgraph,"loss3-classifier",newFc)
% création d'une couche output vierge
newOut = classificationLayer("Name","new_out");
% on remplace la couche existante par la nouvelle
lgraph = replaceLayer(lgraph,"output",newOut)
Attention : classification layer / output layer
La couche de classification est l'avant-dernière couche : elle attribue un score à chaque classe pour l'image traitée, c'est le réseau de neurones. Son type est "fully connected layer" car ce sont des neurones connectés.
La classe de sortie (output layer) traite les scores, les traduit en probabilités pour chaque classe, et donne en sortie la classe la plus probable. Son type est "classification output"
Il y a parfois ambiguïté entre la "output layer" et la "classification layer" car Matlab a attibué le type classificationLayer a la couche Classification Output.
Étape 2 : Image Datastore
% création du datastore à partir du répertoire "imgAll"
% les labels seront extraits des noms des répertoires
% le datastore prend "imgAll" et tous les sous-répertoires
imds = imageDatastore("imgAll", "IncludeSubfolders",true, "LabelSource","foldernames")
imds.Labels
% Répartition aléatoire des images,
% 70% pour le training
% 30% pour le test
[trainAllImgs, testAllImgs] = splitEachLabel(imds, 0.7, "randomized")
% augmentedDatastore permet d'ajouter une fonction de pré-traitement
% ici on adapte la taille de l'image au cnn
trainds = augmentedImageDatastore([224 224],trainAllImgs);
testds = augmentedImageDatastore([224 224],testAllImgs);
Etape 3 : Options
options = trainingOptions("adam",...
'InitialLearnRate', 0.01, ...
'LearnRateDropFactor',0.2, ...
'LearnRateDropPeriod',5, ...
'MaxEpochs',10, ...
'MiniBatchSize',64, ...
'Plots','training-progress',...
'Shuffle','every-epoch');
Pour plus de détails : Doc Matlab : trainingOptions
Etape 4 : Training et évaluation
% entraînement du cnn. Temps de calcul important !!
plantDiseasesNet = trainNetwork(trainds,lgraph,options)
% ne pas oublier de sauvegarder !!!!
save plantDiseasesNet
% calcule la classe prédite sur les images de test
predictions = classify(plantDiseasesNet,testds)
% Trace la matrice de confusion
confusionchart(testAllImgs.Labels, predictions)
Ré-utiliser le cnn
Matlab a enregistré le nouveau réseau ré-entrâiné (ici plantDiseasesNet.mat).
Ce réseau peut être réutilisé avec la commande
load plantDiseasesNet
Entraînement d'un réseau neuronal : avec le Deep Learning Designer⚓
Designer : charger le réseau à ré-entraîner
Créer un nouveau CNN. Le menu donne le choix entre
créer un réseau vide
charger un réseau existant (Alexnet,...)
charger un réseau depuis le workspace
On choisira le réseau que l'on souhaite modifier pour faire le transfer learning.
Modifiation de la couche 'fully connected"
En zoomant sur les couches finales, on peut voir la couche classifiante "fully connected".
Il suffit de glisser depuis la palette à gauche une nouvelle couche de type "fully connected"
Output size : doit correspondre aux nombre de classes
Il suffit ensuite de supprimer les flèches qui connectent la couche "fully connected" initiale et de connecter la nouvelle à la place
Modification de la couche de sortie
Même principe pour la couche de sortie
Suite du processus
Une fois le réseau importé modifié, il suffit de choisir "Export -> Workspace" : la structure "lgrah" est accessble depuis le workspace.
Il est possible de l'enregistrer mais ce n'est pas obligatoire.
Le graphe est ce qui permet de lancer la fonction "trainNetwork", en spécifiant en plus les images et les options. Le résultat sera le nouveau réseau ré-entraîné, qu'il suffira d'enregistrer.
Entraînement avec le Deep Designer
Il est possible de finaliser le processus avec le Deep Learning Designer
Spécifier les datas
Définir les options du training
Lancer le training
Ce n'est pas détaillé ici.
Le problème du temps de calcul⚓
Entraînement sur tout le dataset
Exécution d'un script avec transfer learning sur toutes les images du dataset (plus de 5000).
Presque 2h de calcul pour 13 Epochs (30 Epochs par défaut).
La fonction "train" est très gourmande en ressources et en particulier en temps de calcul. L'utilisation de GPU peut permettre de gagner du temps. Par rapport aux contraintes horaires, les élèves vont devoir proposer des solutions pour faire des tests (algorithmes, options, nb d'epochs, mini-batch etc.) avant de lancer le transfer learning sur toute la base des images.
Méthode : Limiter le volume des images d'entraînement
Limiter les images d'entraînement (ex : 500 pour le training, 150 pour le test)
Étudier les résultats (matrice de confusion, précision, temps d'exécution d'une classification)
Utiliser ces paramètres pour lancer le training sur tout le dataset
Entraînement sur un sous-ensemble des images⚓
Se limiter à un sous-ensemble des dossiers (exemple avec le maïs : 4 répertoires)
Utilisation de la fonction "subset"
Proposition de solution pour créer les deux sous-ensembles d'images : les images doivent être choisies de façon aléatoire et de façon équitable depuis tous les dossiers.
% Creation des datastores pour training et test du cnn
imds = imageDatastore("img", "IncludeSubfolders",true, "LabelSource","foldernames")
imds.Labels
[trainAllImgs, testAllImgs] = splitEachLabel(imds, 0.7, "randomized")
%pour travailler sur une partie des images et pas sur la totalité
nFiles = length(trainAllImgs.Files);
RandIndices = randperm(nFiles); %mélange aléatoire des indices des fichiers images
indices = RandIndices(1:500) % on ne prend que les 500 premières images (après mélange)
trainPartImg = subset(trainAllImgs,indices) %création d'un datastore extrait
%idem pour le datastore dédié au test du cnn
nFiles = length(testAllImgs.Files);
RandIndices = randperm(nFiles);
indices = RandIndices(1:200)
testPartImg = subset (testAllImgs, indices)
% si besoin de modifier la taille de l'image pour l'adapter
trainds = augmentedImageDatastore([224 224],trainPartImg);
testds = augmentedImageDatastore([224 224],testPartImg);
Les options de la fonction "train"
Référence : Doc Matlab : trainingOptions
Choix de l'algorithme "solver" : la matrice de confusion
Algorithme "adam"
Problème : toutes les images sont classées comme "healthy" !
Algorithme "sgdm"
Le réseau donne de très bons résultats !
Voir le code : Github dédié au projet