Spaces:
Sleeping
Sleeping
| # 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é. | |