YELY_AI_Module / docs /TRAINING.md
danielxdata's picture
Module IA YELY - CRNN fine-tune, API FastAPI, interface demo
b510add
|
Raw
History Blame Contribute Delete
7.43 kB

Entraîner, annoter, évaluer le modèle CRNN

Ce document explique comment lancer chacune des trois étapes : annoter de nouvelles images, ré-entraîner le modèle, évaluer sa précision. Les scripts utilisés vivent dans le dépôt d'origine (annotator/, train/ à la racine), pas dans yely_ai_module/ — ce dossier livrable embarque une copie de référence de train/ pour la reproductibilité (voir §"Où ça vit" plus bas).

Vue d'ensemble du pipeline data → modèle

1. Annoter          annotator/annotate.py
        │            (dessine le rectangle LCD + saisit prix/volume/prix_litre)
        ▼
   annotator/annotations/annotations.json  (+ crops dans annotations/crops/)
        │
2. Découper en lignes  annotator/split_lines.py
        │            (1 image = 3 valeurs → 3 sous-images mono-ligne)
        ▼
   annotator/dataset_lines/{train,val}/
        │
3. Convertir au format doctr  train/prepare_doctr_dataset.py
        ▼
   annotator/dataset_doctr/{train,val}/  (images/ + labels.json)
        │
4. Entraîner  train/finetune_doctr.py
        ▼
   train/models/crnn_fuel_pump_best.pt  (+ history.json)
        │
5. Évaluer  train/test_model.py

1. Annoter de nouvelles images

cd annotator
python annotate.py --images ../images/        # nouvelles photos
python annotate.py --images ../images/ --resume   # reprendre où on s'était arrêté
python annotate.py --review                    # voir un résumé des annotations existantes

Pour chaque image : dessiner un rectangle autour de l'écran LCD (clic + glisser), puis saisir dans le terminal les valeurs affichées (prix, volume, prix du litre). Voir annotator/README.md pour le détail des raccourcis.

Ce qui compte le plus pour améliorer le modèle (voir docs/LIMITATIONS.md) : annoter des photos avec des valeurs différentes de celles déjà présentes, pas juste plus de photos des mêmes tickets. Utiliser yely_ai_module/tools/check_seen_image.py pour vérifier qu'une photo candidate n'est pas déjà (quasi-)présente dans le jeu annoté :

python yely_ai_module/tools/check_seen_image.py chemin/vers/nouvelle_photo.jpg

2. Régénérer le dataset d'entraînement

Toujours dans cet ordre, et jamais pendant qu'un entraînement tourne (le chargement des images se fait à la volée pendant l'entraînement — les régénérer en même temps fait planter le script avec un FileNotFoundError, vécu concrètement pendant cette session) :

cd annotator
python split_lines.py              # annotations.json -> dataset_lines/

cd ../train
python prepare_doctr_dataset.py    # dataset_lines/ -> dataset_doctr/

Les deux scripts nettoient maintenant leur dossier de sortie avant de régénérer (corrigé cette session — une même image pouvait sinon se retrouver à la fois en train et en val d'un run à l'autre, faussant l'évaluation).

Vérification recommandée avant d'entraîner : ouvrir annotator/dataset_lines/review/review_sheet.jpg, qui montre un échantillon d'images découpées à côté du label attendu — permet de repérer un mauvais découpage avant de perdre du temps à entraîner dessus.

3. Lancer l'entraînement

cd train
python finetune_doctr.py                      # 80 epochs par défaut
python finetune_doctr.py --epochs 60 --patience 12
python finetune_doctr.py --from-scratch       # si pas de connexion internet (pas de poids pré-entraînés)
  • Le modèle est sauvegardé dans train/models/crnn_fuel_pump_best.pt à chaque fois que la perte de validation s'améliore (pas seulement à la fin) — s'arrêter en cours de route (Ctrl+C, crash) ne perd donc pas tout.
  • --patience N : arrête l'entraînement si la perte de validation ne s'améliore plus pendant N epochs (évite de continuer à surapprendre inutilement).
  • Sur CPU (pas de GPU disponible), compter 1.5-3 min/epoch sur le jeu de données actuel (270 échantillons train). Un entraînement complet peut donc prendre plusieurs heures — lancer en arrière-plan (... & ou un terminal dédié) plutôt qu'en bloquant.
  • À la fin (ou à l'arrêt anticipé), train/models/history.json contient la courbe complète (perte/accuracy par epoch) — sert de preuve pour le rapport de test (§15 du cahier des charges).

4. Évaluer le modèle

cd train
python test_model.py                          # évalue sur tout le set de validation
python test_model.py --image ../images/pompe.jpg   # teste une seule image

test_model.py calcule, sur le jeu de validation :

  • Exact-match accuracy : proportion de lignes lues à 100% correctement (c'est la métrique citée dans docs/LIMITATIONS.md).
  • CER (Character Error Rate) et WER : à quel point une prédiction fausse est "proche" de la bonne réponse (ex. "10000" lu "1O000" a un CER faible même si l'exact-match échoue) — plus informatif que l'accuracy seule pour juger si le modèle progresse.
  • La liste des erreurs (jusqu'à 15 affichées), utile pour repérer des motifs d'erreur récurrents (un chiffre systématiquement confondu, une ligne toujours mal découpée...).

Où ça vit (dépôt d'origine vs dossier livrable)

  • Annotation et préparation du dataset (annotator/) : uniquement à la racine du dépôt d'origine, pas dupliqué dans yely_ai_module/ (le jeu de ~155 images sources n'est volontairement pas inclus dans le livrable).
  • Entraînement (train/) : présent aux deux endroits. La copie dans yely_ai_module/train/ est une référence pour la reproductibilité (documentation technique) ; pour ré-entraîner réellement, utiliser la version à la racine du dépôt, qui a accès à annotator/dataset_doctr/.
  • Script train/infer.py : ancien script d'inférence autonome (antérieur à yely_ai_module/app/recognizer.py), gardé pour test rapide en ligne de commande. Avait le même bug de découpage à 2 lignes (au lieu de 3) que celui corrigé dans preprocessing.py — corrigé aussi. Pour tester le pipeline réellement livré (avec règles métier, API), utiliser yely_ai_module/app/, pas ce script.

Si le modèle donne de mauvais résultats en test manuel

Avant de conclure "le modèle n'est pas bon", vérifier dans l'ordre :

  1. Quel script a été utilisé ? train/infer.py et yely_ai_module/app/ ont des logiques de détection d'écran différentes (detect_lcd_region vs detect_screen_region) — l'un peut réussir là où l'autre échoue sur la même photo.
  2. La zone détectée est-elle la bonne ? Les deux scripts peuvent confondre le bandeau de marque ("Shell FuelSave...") avec l'écran LCD sur certaines photos (voir docs/PREPROCESSING.md) — sauvegarder et regarder le crop intermédiaire avant d'incriminer le CRNN.
  3. La photo est-elle inédite ou proche du jeu d'entraînement ? (tools/check_seen_image.py) — le modèle est attendu comme moins bon sur des valeurs qu'il n'a jamais vues, c'est documenté et mesuré (docs/LIMITATIONS.md), pas une surprise.
  4. Quelle précision réelle attendre ? 70.2% exact-match sur les lignes de validation (train/models/v2/history.json) — donc environ 3 lectures sur 10 avec au moins un caractère faux sont attendues à ce stade, pas un signe que quelque chose est cassé.