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
```bash
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é :
```bash
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) :
```bash
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
```bash
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
```bash
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é.