Spaces:
Sleeping
Sleeping
File size: 5,345 Bytes
b510add 3020394 b510add | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | # Limites identifiées — modèle CRNN (§15 du cahier des charges)
## Précision actuelle
Le modèle CRNN (`crnn_vgg16_bn`, fine-tuné à partir des poids pré-entraînés
Mindee) livré dans `models/crnn_fuel_pump_best.pt` atteint **70.2% de
précision exacte par ligne** en validation (epoch 32, voir
`train/models/v2/history.json`) — en progression depuis la version initiale
à ~55% (`train/models/history.json`), grâce au correctif de redimensionnement
(voir point 3) et à l'ajout de 3 images avec des valeurs inédites au jeu
d'annotation. C'est encore en dessous du seuil de 90% visé initialement
(`IMPLEMENTATION_PLAN.md`), mais un progrès net et mesuré sur un vrai
jeu de validation (sans fuite train/val — voir point 4).
## Causes identifiées
1. **Diversité des valeurs quasi nulle dans le jeu de données.** 310
échantillons au total (155 images sources découpées en lignes), mais
seulement **30 valeurs distinctes** — 8 valeurs à elles seules
représentent ~89% du dataset (probablement des photos en rafale des
mêmes transactions). Le modèle a donc très peu d'occasions d'apprendre à
généraliser la lecture de chiffres inédits ; il est plus proche de la
mémorisation d'un nombre restreint de motifs que d'une reconnaissance de
caractères robuste.
2. **Découpage ligne-par-ligne imprécis pour 86% des images sources.**
`annotator/dataset_lines/split_report.json` montre que seulement 22/154
images ont utilisé la détection précise par projection de texte ; 132/154
sont tombées sur le repli "proportionnel" (division en bandes de hauteur
égale), qui peut couper à travers les chiffres ou inclure du bruit —
corrompant l'alignement image↔label pour la majorité de l'entraînement.
3. **Incohérence corrigée entre entraînement et inférence (resize).**
À l'entraînement, chaque crop était étiré de force à une largeur fixe de
256px sans préserver le ratio d'aspect (`train/finetune_doctr.py`,
`collate_fn`), alors qu'à l'inférence le ratio d'aspect était préservé
(`preprocess_crop`). Le modèle apprenait donc sur des chiffres déformés
différemment de ce qu'il voit réellement en production. **Corrigé** :
le redimensionnement d'entraînement préserve maintenant le ratio d'aspect
et complète par du padding, comme à l'inférence.
4. **Fuite train/val corrigée.** Relancer `split_lines.py` après avoir
ajouté des annotations réassignait des images entre train et val (le
split dépend d'un tirage aléatoire sur la liste complète), mais les
anciens fichiers n'étaient pas supprimés avant d'écrire les nouveaux —
une même image pouvait donc se retrouver à la fois dans train ET val,
gonflant artificiellement l'accuracy de validation. **Corrigé** :
`split_lines.py` et `prepare_doctr_dataset.py` nettoient maintenant les
dossiers de sortie avant de régénérer. Le 70.2% actuel est mesuré après
ce correctif — donc fiable.
## Toujours vrai malgré l'amélioration à 70.2%
Le facteur limitant reste le même : le dataset est petit et peu diversifié
en valeurs. 70.2% de lignes exactement correctes n'est pas suffisant pour
une mise en production telle quelle — voir §"Recommandations" ci-dessous,
qui restent d'actualité.
## Recommandations pour dépasser 70%
- **Collecter plus de transactions distinctes** (valeurs de prix/volume
variées, pas seulement plus de photos des mêmes tickets) — c'est le levier
le plus impactant, mais aussi le plus long à mettre en œuvre.
- **Revoir le découpage des lignes** : ajuster les seuils de
`annotator/split_lines.py::_detect_text_bands` (actuellement 86% des
images tombent sur le repli proportionnel), ou annoter directement les
bounding box par valeur plutôt que par écran complet.
- **Vérifier visuellement** `annotator/dataset_lines/review/review_sheet.jpg`
avant tout nouvel entraînement, pour écarter les crops mal découpés.
- Envisager de la **data augmentation** (légères rotations, variations de
luminosité/contraste) pour compenser partiellement le manque de diversité.
## Bug de classification qualité corrigé (flou vs sombre)
`app/quality.py` vérifiait le flou (variance du Laplacien) avant la
luminosité. Or la variance du Laplacien dépend elle-même du contraste, qui
s'effondre dans une image sombre même quand les contours sont nets : une
photo prise dans un environnement peu éclairé mais parfaitement stable
pouvait donc être classée à tort `"blurry"` ("reprendre la photo, image
floue") au lieu de `"dark"` ("reprendre la photo avec plus de lumière") —
deux diagnostics qui appellent un geste correctif différent côté
utilisateur. **Corrigé** : la luminosité (`dark`/`bright`) est maintenant
vérifiée avant le flou, qui n'est un diagnostic fiable que sur une image
déjà correctement exposée.
## Ce qui reste fiable indépendamment du modèle
La détection d'écran, le contrôle qualité (flou/luminosité), le moteur de
règles métier (cohérence montant/litres/prix, seuil de confiance, blocage)
et l'API ne dépendent pas de la précision du CRNN — ce sont des composants
séparés et testés indépendamment (voir `tests/`). Une amélioration future du
modèle de reconnaissance s'intègre donc sans changer le reste du pipeline.
|