Ré-entraîner un réseau pré-entraîné à la détection d'objets dans des images
Acquis d'apprentissage visés :
- Savoir modifier le fichier de configuration d'un réseau TOD pré-entrainé, pour l'adapter à ses besoins.
- Savoir continuer l'entraînement supervisé d'un réseau TOD pré-entraîné.
- Savoir exporter les poids du réseau entrainé dans un format utilisable.
Durée approximative : plusieurs heures (dépend des ressources CPU & RAM de ton ordinateur).
Plan de l’activité
Cette activité se décompose en 3 étapes :
- Modifier le fichier de configuration du réseau pré-entraîné pour décrire la configuration d’entraînement propre à ton travail.
- Lancer l’entraînement supervisé.
- Exporter les poids du réseau entrainé dans un format utilisable.
0. Préliminaires
Pour simplifier l’écriture des commandes Linux à taper dans le terminal, tu peux définir dans le fichier config_tf2
:
- la variable
PTN
(Pre-Trained Network) qui donne le nom du réseau pré-entraîné choisi<pre-trained_net>
, - la variable
PTN_DIR
qui donne le chemin d’accès au dossier<project>/training/<pre-trained_net>
Exemple
Avec le projet faces_cubes
et le réseau faster_rcnn_resnet50_v1_640x640_coco17_tpu-8
:
# From within tod_tf2
user@host $ echo 'export PTN=faster_rcnn_resnet50_v1_640x640_coco17_tpu-8' >> config_tf2
user@host $ echo 'export PTN_DIR=faces_cubes/training/$PTN' >> config_tf2
puis, après avoir sourcé le fichier config_tf2
, tu peux vérifier que les 2 variables sont bien définies :
# From within tod_tf2
user@host $ source config_tf2
user@host $ env | grep PTN # pour vérifier
PTN_DIR=faces_cubes/training/faster_rcnn_resnet50_v1_640x640_coco17_tpu-8
PTN=faster_rcnn_resnet50_v1_640x640_coco17_tpu-8
1. Modifier le fichier de configuration
Le fichier de configuration pipeline.config
présent dans le dossier pre-trained/<pre-trained_net>
doit être copié dans le dossier cible <project>/training/<pre-trained_net>
.
Avec le projet faces_cubes
et le réseau pré-entrainé choisi :
# From within tod_tf2
user@host $ cp pre-trained/$PTN/pipeline.config $PTN_DIR
- Il faut ensuite modifier les paramètres du fichier
$PTN_DIR/pipeline.config
pour les adapter à l’entraînement.
Exemple
Avec le projet faces_cubes
et le réseau faster_rcnn_resnet50_v1_640x640_coco17_tpu-8
:
Line | Parameter name | Description | Initial value | Value | Comment |
---|---|---|---|---|---|
010 | num_classes |
nombre de classe d’objets |
90 | 2 | les deux classes one et two |
077 | max_detections_per_class |
nombre max de détections par classe |
100 | 4 | 4 cubes max par image |
078 | max_total_detections |
nombre max total de détections |
100 | 4 | 4 cubes max par image |
093 | batch_size |
nombre d’images à traiter avant mise à jour des poids du réseau |
64 | 1, 2… | une valeur trop élevée risque de faire dépasser la capacité mémoire RAM de ta machine. À régler en fonction de la quantité de RAM de ta machine. |
097 | num_steps |
Nombre max d’itérations d’entraînement |
25000 | 1000 | une valeur trop grande donne des temps de calcul prohibitifs et un risque de sur-entraînement |
113 | fine_tune_checkpoint |
chemin des fichiers de sauvegarde des poids du réseau pré-entraîné |
‘PATH_TO_BE_CONFIGURED’ | ‘pre-trained/faster_rcnn_resnet50_v1_640x640_coco17_tpu-8/checkpoint/ckpt-0’ | se termine par /ckpt-0 qui est le préfixe des fichiers dans le dossier .../checkpoint/ |
114 | fine_tune_checkpoint_type |
Choix de l’algorithme : “classification” ou “detection” |
‘classification’ | ‘detection’ | -> détection d’objets |
120 | max_number_of_boxes |
Nombre max de boîtes englobantes dans chaque image |
100 | 4 | 4 faces de cubes dans une image |
122 | use_bfloat16 |
true pour lesarchitectures TPU false pour CPU |
true | false | choix du CPU |
126 | label_map_path |
chemin du fichier des labels |
‘PATH_TO_BE_CONFIGURED’ | ‘faces_cubes/training/label_map.txt’ | utilisé pour l’entraînement |
128 | input_path |
fichier des données d’entraînement au format tfrecord |
‘PATH_TO_BE_CONFIGURED’ | ‘faces_cubes/training/train.record’ | utilisé pour l’entraînement |
139 | label_map_path |
chemin du fichier des labels |
‘PATH_TO_BE_CONFIGURED’ | ‘faces_cubes/training/label_map.txt’ | utilisé pour l’évaluation |
143 | input_path |
fichier des données de test au format tfrecord |
‘PATH_TO_BE_CONFIGURED’ | ‘faces_cubes/training/test.record" | utilisé pour l’évaluation |
2 Lance l’entraînement
⚠️ Il est très important de bien vérifier le contenu du fichier $PTN_DIR/pipeline.configure
avant de lancer l’entraînement : une bonne pratique est de le faire vérifier par quelqu’un d’autre…
⚠️ Ne mettre des valeurs de batch_size
> 2 que si ton ordinateur possède un bon CPU avec au moins 6 Gio de RAM !
Exemple : pour une entraînement avec 15 images avec num_steps=1000
, sur un PC portable avec un processeur Intel core i7 et 8 Gio RAM :
batch_size=1
: le calcul prend environ 1h30 (~5.7 sec par step) et jusqu’à ~4 GiO RAMbatch_size=2
: le calcul prend environ 3h (~11 sec par step) et jusqu’à ~4.5 GiO RAMbatch_size=4
: le calcul prend environ 6h (~22 sec par step) et jusqu’à ~6 GiO RAM .
Copie le fichier models/research/object_detection/model_main_tf2.py
dans la racine tod_tf2
:
# From within tod_tf2
(tf2) user@host $ cp models/research/object_detection/model_main_tf2.py .
Maintenant lance l’entraînement avec la commande :
# From within tod_tf2
(tf2) user@host $ python model_main_tf2.py --model_dir=$PTN_DIR/checkpoint1 --pipeline_config_path=$PTN_DIR/pipeline.config
Les fichiers des poids entraînés seront écrits dans le dossier $PTN_DIR/checkpoint1
: si tu relances l’entraînement, tu peux utiliser checkpoint2
, checkpoint3
… pour séparer des essais successifs.
Le module tensorflow est assez verbeux et l’entraînement est long à démarrer…
Au bout d’un “certain temps” (qui peut être assez long, plusieurs dizaines de minutes avec un CPU ordinaire), les logs s’affichent à l’écran, en particulier les lignes qui commencent par INFO
montrant que l’entraînement est en cours :
...
...
INFO:tensorflow:Step 100 per-step time 11.094s
I0123 17:51:15.919782 140056729301632 model_lib_v2.py:705] Step 100 per-step time 11.094s
INFO:tensorflow:{'Loss/BoxClassifierLoss/classification_loss': 0.13388917,
'Loss/BoxClassifierLoss/localization_loss': 0.017869305,
'Loss/RPNLoss/localization_loss': 0.0029150385,
'Loss/RPNLoss/objectness_loss': 0.0007381027,
'Loss/regularization_loss': 0.0,
'Loss/total_loss': 0.15541162,
'learning_rate': 0.014666351}
I0123 17:51:15.920520 140056729301632 model_lib_v2.py:708] {'Loss/BoxClassifierLoss/classification_loss': 0.13388917,
'Loss/BoxClassifierLoss/localization_loss': 0.017869305,
'Loss/RPNLoss/localization_loss': 0.0029150385,
'Loss/RPNLoss/objectness_loss': 0.0007381027,
'Loss/regularization_loss': 0.0,
'Loss/total_loss': 0.15541162,
'learning_rate': 0.014666351}
...
INFO:tensorflow:Step 1000 per-step time 10.638s
I0123 20:30:50.425828 140056729301632 model_lib_v2.py:705] Step 1000 per-step time 10.638s
INFO:tensorflow:{'Loss/BoxClassifierLoss/classification_loss': 0.05049885,
'Loss/BoxClassifierLoss/localization_loss': 0.0066467496,
'Loss/RPNLoss/localization_loss': 0.0011727745,
'Loss/RPNLoss/objectness_loss': 0.0002043869,
'Loss/regularization_loss': 0.0,
'Loss/total_loss': 0.05852276,
'learning_rate': 0.0266665}
I0123 20:30:50.426177 140056729301632 model_lib_v2.py:708] {'Loss/BoxClassifierLoss/classification_loss': 0.05049885,
'Loss/BoxClassifierLoss/localization_loss': 0.0066467496,
'Loss/RPNLoss/localization_loss': 0.0011727745,
'Loss/RPNLoss/objectness_loss': 0.0002043869,
'Loss/regularization_loss': 0.0,
'Loss/total_loss': 0.05852276,
'learning_rate': 0.0266665}
En cas d’arrêt brutal du programme avec le message “Processus arrêté”, ne pas hésiter à diminer la valeur du paramètre batch_size
jusquà 2, voire 1 si nécessaire….
Même avec batch_size=2
, le processus Python peut nécessiter plusieurs Gio de RAM à lui tout seul, ce qui peut mettre certains portables en difficulté…
Dans l’exemple ci-dessus, on voit des logs tous les 100 pas, avec environ ~10.7 secondes par pas, soit environ 18 minutes entre chaque affichage et ~3h de calcul pour les 1000 pas. Ce calcul est fait avec batch_size=2
sur un CPU Intel i7.
Une fois l’entraînement terminé tu peux analyser les statistiques d’entraînement avec tensorboard
en tapant la commande :
# From within tod_tf2
(tf2) user@host:~ $ tensorboard --logdir=$PTN_DIR/checkpoint1/train
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.11.2 at http://localhost:6006/ (Press CTRL+C to quit)
...
tensorBOARD
lance un serveur HTTP en local sur ta machine, et tu peux ouvrir la page avec un navigateur pour voir les courbes d’analyse en faisant CTRL + clic avec le curseur de la souris positionné sur l’adresse http://localhost:6006/
:
On peut voir sur les figures suivantes l’influence de la valeur du paramètre batch_size
sur la qualité de l’apprentissage : un batch_size=2
donne de meilleures courbes de loss que’un batch_size=1
, mais le calcul est plus long et prend plus de mémoire :
Entraînement avec batch_size=1
, num_steps=1000
:
Entraînement avec batch_size=2
, num_steps=1000
:
Entraînement avec batch_size=4
, num_steps=1000
:
3. Exporter les poids du réseau ré-entraîné
Copie le script Python exporter_main_v2.py
situé dans le dossier models/reasearch/object_detection/
et lance le pour extraire le graph d’inférence entraîné et le sauvegarder dans un fichier saved_model.pb
. Ce fichier pourra être rechargé ultérieurement pour exploiter le réseau entraîné :
# From within tod_tf2
(tf2) user@host $ cp models/research/object_detection/exporter_main_v2.py .
(tf2) user@host $ python exporter_main_v2.py --input_type image_tensor --pipeline_config_path $PTN_DIR/pipeline.config --trained_checkpoint_dir $PTN_DIR/checkpoint1 --output_directory $PTN_DIR/saved_model1
...some stuff....
Le script Python créé le fichier saved_model.pb
dans le dossier $PTN_DIR/saved_model1/saved_model
:
# From within tod_tf2
(tf2) user@host:~ $ tree faces_cubes/training/
faces_cubes/training/
├── faster_rcnn_resnet50_v1_640x640_coco17_tpu-8
│ ├── checkpoint1
│ │ ├── checkpoint
│ │ ├── ckpt-1.data-00000-of-00001
│ │ ├── ckpt-1.index
│ │ ├── ckpt-2.data-00000-of-00001
│ │ ├── ckpt-2.index
│ │ └── train
│ │ └── events.out.tfevents.1635373645.pikatchou.30316.0.v2
│ ├── pipeline.config
│ └── saved_model1
│ ├── checkpoint
│ │ ├── checkpoint
│ │ ├── ckpt-0.data-00000-of-00001
│ │ └── ckpt-0.index
│ ├── pipeline.config
│ └── saved_model
│ ├── assets
│ ├── saved_model.pb
│ └── variables
│ ├── variables.data-00000-of-00001
│ └── variables.index
├── label_map.txt
├── test.record
└── train.record