====== Projet - Système de classification d'images par apprendissage profond ======
Nous allons utiliser l'outil PyTorch.
Torch est un ensemble de logiciels pour faire du deep learning.
Pytorch est principalement une interface python pour torch.
===== Installations (si vous souhaitez le faire sur vos machines, Linux) =====
Installation de l'installateur [[https://conda.io/miniconda.html|Miniconda]]. Choisir python 3.7 et 64 bits.
Installation de [[http://pytorch.org/|PyTorch]] :
conda install pytorch torchvision -c pytorch
Version istallée sur les machines de l'UFR sur le compte quenotg, inclure la ligne suivante dans votre .bashrc (ou l'entrer dans votre terminal) :
export PATH="/home/Public/quenotg/miniconda3/bin:$PATH"
Pour un effet immédiat, exécuter la commande :
source ~/.bashrc
Si nécessaire, installation de [[https://matplotlib.org/|matplotlib]] :
$ python -mpip install -U pip
$ python -mpip install -U matplotlib
===== Tutoriels =====
[[https://docs.python.org/3.5/tutorial/|Tutoriel Python]] \\
[[http://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html|Tutoriel débutants PyTorch]]
Pour ne pas télécharger inutilement les données CIFAR-10 (180 Mo) sur les machines de l'UFR, faire le lien symbolique suivant :
ln -s /home/Public/quenotg/data .
===== Pour commencer =====
Le TP2 en pytorch : \\
En python : [[http://mrim.imag.fr/georges.quenot/tp2/tgabor.py|tgabor.py]] \\
En jupyter notebook : [[http://mrim.imag.fr/georges.quenot/tp2/tgabor.ipynb|tgabor.ipynb]] \\
En jupyter notebook exécuté HTML : [[http://mrim.imag.fr/georges.quenot/tp2/tgabor.html|tgabor.html]] \\
En jupyter notebook exécuté PDF : [[http://mrim.imag.fr/georges.quenot/tp2/tgabor.pdf|tgabor.pdf]]
===== Mise en route =====
Faire le tutoriel **manuellement étape par étape** avec le réseau proposé jusqu'à l'entraînement pendant deux itérations et l'évaluation sur les données de test. \\
**Bien comprendre toutes les étapes et le rôle de chaque module ou fonction.** \\
Il ya beaucoup de choses "cachées" dans les différentes fonctions, il faut comprendre tout ce qui se passe.
**Utilisez les notbooks fournis dans le tutoriel.**\\
**Modifiez le code pour tourner sur GPU**
===== Instrumentation et évaluation "en continu" du système =====
Dans la partie entraînement du réseau CNN, lister les différentes couches et sous-couches. \\
Donner la taille des différents tenseurs de données Xn et de poids Wn le long du calcul. \\
Modifier le programme pour faire l'évaluation après chaque époque et aussi avant la première (faire une fonction spécialisée). Supprimer les autres affichages intermédiaires. \\
Modifier les fonctions pour calculer à chaque étape le nombre d'opérations flottantes effectuées, séparément pour les additions, les multiplications, les maximums et le total. \\
Afficher en fin de passe, en plus du taux d'erreur global, le nombre d'opérations effectuées, le temps d'exécution, et le nombre d'opérations par seconde.
Total number of parameters:
sum(p.numel() for p in model.parameters())
Parameter tensor sizes:
for p in model.parameters(): print(p.size())
Network summary:
from torchsummary import summary
summary(model, (3, 32, 32))
===== Modification du réseau =====
Modifier le réseau de manière cohérente : commencer par modifier la taille d'une ou plusieurs couche, plus de cartes (filtres ou plans) dans une couche de convolution ou plus de neurones dans une couche complètement connectée.
Essayer ensuite d'insérer une couche supplémentaire soit de convolution, soit complètement connectée, soit les deux.
Dans tous les cas, rester sur deux itérations seulement pour limiter le temps d'exécution et comparer les performances des différentes variantes. Dans un ou deux cas, laisser tourner l'entraînement jusqu'à ce que la performance jusqu'à ce que la fonction de coût (running loss) ne décroisse plus ou plus significativement. Comparer la performance finale du réseau du tutoriel et d'une de vos variantes.
Essayer ensuite des variantes de la fonction de coût (loss), de l'optimiseur et/ou de la fonction d'activation.
** Prendre systématiquement des notes pour le compte rendu final. **
===== Objectif final =====
Optimisation d'un réseau pour la tâche de classification CIFAR-10 sous les deux contraintes :
- Le nombre total de paramètres (c'est le nombre total de paramètres qui définissent le réseau et qui sont appris par la descente de gradient ; c'est la somme des paramètres pour chacune des couches ou sous-couches impliquées (pour celles qui ont des paramètres) ; on ne compte chaque paramètre qu'une seule fois, qu'il soit utilisé plusieurs fois, comme dans les couches de convolution, ou une seule fois, comme dans les couches complètement connectées) ne doit pas dépasser 256K (1 Moctet pour le modèle) ;
- Le temps d'entraînement sur un GPU de Grid'5000 ne doit pas dépasser une heure (à lancer en dehors des heures de TP).
Vous pouvez partir du réseau défini dans le tutoriel et faire toutes sortes de modification comme : nombre de couches, nombre de filtres dans les couches, essayer des branches parallèles (comme les modules inception), organiser une décroissance du taux d'apprentissage, etc. Il faut préparer une manip pendant le cours en mode interactif et la laisser tourner une heure en mode batch plus tard. La note ne portera évidement pas exclusivement sur la performance finale.
===== Suggestions =====
Utiliser des tailles de batch plus grandes que 4. L'effet est significatif sur le temps de calcul. Il faut utiliser des sous-multiples de 10000 pour ne pas avoir de problèmes liés à une taille différente pour le dernir batch. 16 est une bonne valeur. **Attention : ** la vitesse de calcul augmente en effet sensiblement avec la taille du batch mais la convergece est en contrepartie plus lente pour le même nombre d'époques en raison de l'affaiblissement de l'effet stochastique dans la descente de gradient. Il faut donc trouver le bon compromis entre le temps gagné sur le traitement d'une époque et le nombre d'époques requis pour atteindre la même performance finale.
Ajuster les tailles des différentes couches pour rester en dessous du budget paramètres fixé (256K).
Insérer un module de "batch normalization" (https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html) pour les coucbes de convolution (à insérer entre les fonction conv2d et les fonctions relu)
Insérer éventuellement un module de "dropout" (https://pytorch.org/docs/stable/generated/torch.nn.Dropout.html), pour les couches complètement connectées.
Attention, si vout utilisez des couches de "dropout" ou de "batch normalization", il y a un mode "train" et un mode "eval" à utiliser respectivement pour l'apprentissage et pour la mesure de performance. En pratique, le mode "train" ret par défaut et il faut exécuter "net.eval()" en début de la fonction d'évaluation et "net.train()" à la fin de celle-ci.
Augmenter les données. Utiliser (décommenter) les transformations aléatoires additionelles sur les images d'entrée (apprentissage seulement) :
transform_train = transforms.Compose(
[# transforms.RandomHorizontalFlip(),
# transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
Il n'y a pas toujours un gain et il peut falloir plus d'itérations pour l'avoir.
Mesurer le temps de calcul d'une passe (époque) et estimer le nombre de passes faisables en une heure. Faire une programmation du taux d'apprentissage avec trois palier, respectivement à 0.01, 0.001 et 0.0001 et pour 50%, 25% et 25% du nombre total de passes disponibles.
===== Accès aux GPUs sur Grid'5000 =====
Voir : [[Accès Grid'5000]]
Pour accéder à l'installation via conda (dans le terminal ou dans le .bashrc) :
export PATH="/srv/storage/irim@storage1.lille.grid5000.fr/anaconda3/bin:$PATH"
Pour ne pas recharger inutilement les données images, dans votre répertoire de travail :
ln -s /srv/storage/irim@storage1.lille.grid5000.fr/ens/data .
En dehors de ces créneaux, vous pouvez toujours lancer des jobs directement en mode interactif ou en mode batch, voir [[Accès Grid'5000]]. \\
Pas de job de plus d'une heure et pas plus d'un à la fois.
===== Evaluation du projet (note de CC) =====
Vous ferez un compte-rendu sur le projet uniquement (pas sur les TPs), à envoyer sous forme électronique à Georges.Quenot@imag.fr pour le **14 avril** au plus tard. Celui-ci doit comprendre un document expliquant ce que vous avez fait et le code PyTorch de votre meilleur système. Dans le compte-rendu, vous rappellerez succinctement l'objectif du projet et les différentes variantes que vous avez étudiées, en mentionnant leurs performances. Vous pouvez discuter des avantages et inconvénients des différents choix, faire des analyses par catégories pour le meilleur système, et d'une manière générale, faire des commentaires indiquant ce que vous avez compris et retenu en faisant ce projet.
Ce qui est attendu :
* Fonction spécifique pour le calcul de l'erreur (ou de la précision) globale sur l'ensemble de test
* Appel de cette fonction avant la première itération (époque) et après chaque itération
* Affichage de l'évolution de l'erreur (ou de la précision) globale en fonction des itérations
* Essais de modification de l'architecture du réseau (taille, nombre et/ou types des couches) ou de conditions d'apprentissage (augmentation de données)
* Description complète de votre réseau final avec : nombre de couches et sous-couches, identification de toutes les variables intermédiaires (les "Xn") de l'entrée à la sortie et en donnant leurs dimensions (tailles de tenseurs) ; identification de toutes les fonctions successives (les "Fn") avec leurs types ; et identification de tous les paramètres de ces fonctions (les "Wn"), en donnant leurs dimensions (tailles de tenseurs) et en précisant éventuellement s'ils sont nuls (pas de paramètres pour la fonction correspondante).
* Calcul du nombre d'opérations flottantes effectuées pour les passes avant (le nombre d'opérations pour les passes arrières, quand il y en a, est quasiment le même) pour une image ; on comptera une opération pour une addition, pour une multiplication ou pour un maximum, même si ces opérations sont de complexités différentes.
* Calcul du nombre total d'opérations pour une époque, incluant les passes avant et arrière pour les images d'entraînement et uniquement une passe avant pour les images de test.
* Même calcul pour l'entraînemenent et l'évaluation en continu sur l'ensemble des époques.
* Calcul en nombre total d'opérations flottantes par seconde sur la durée d'entraînement.
* Et, finalement, la meilleure performance obtenue avec les contraintes de nombre de paramètres et de temps d'entraînement.
La performance finale n'est pas un critère essentiel. Vous pouvez rapporter même les essais qui n'ont pas conduit à des améliorations de performance. Il n'est pas indispensable de tout faire.
Le rapport final pourra être sous la forme d'un notebook Jupyter (exécuté) ou d'un PDF avec le code exécutable en python simple de votre meilleur système.