POC Data : Réduire le gaspillage alimentaire grâce aux données utilisateurs
Comment réduire le gaspillage alimentaire grâce à l’extraction de données de tickets de caisse, via le traitement d’images et de texte ? Retour sur notre projet de Lab.
Chaque année en France, 29 kg de nourriture sont jetés par habitant. En effet, il arrive malheureusement souvent que des aliments pourrissent avant d’avoir été consommés. On oublie le contenu de notre frigo et de nos placards ou la date de péremption des produits qui s’y trouvent. Combien d’entre nous ont déjà retrouvé des aliments totalement périmés dans notre réfrigérateur, racheté des tomates en oubliant qu’on en avait déjà ou encore laissé s’abîmer un légume car on ne savait pas comment l’accommoder ?
Soucieux de réduire leur impact environnemental, trois de nos collaborateurs se sont donc penchés sur un moyen de contribuer à la réduction du gaspillage alimentaire des particuliers. Ce projet a réuni une équipe pluridisciplinaire, formée de : Abdelhadi Temmar — data scientist, Nicolas Hedoire — développeur Web, Constance Perez — chargée de communication, grâce à la cagnotte de jours de R&D alloués annuellement à chacun de nos collaborateurs.
Dans cet article, c’est Abdelhadi qui nous présente les étapes du POC réalisé et ses résultats, d’un point de vue Data Science.
Après une phase de recherche documentaire, nous sommes donc partis du postulat qu’une partie du gaspillage alimentaire était liée à l’oubli de certains produits alimentaires achetés et à la mauvaise gestion des délais de consommation.
Nous en avons donc déduit qu’avoir accès à l’inventaire de tous ses achats et de sa consommation permettrait de limiter ce gaspillage.
Avoir un inventaire des aliments à sa disposition, permettrait effectivement d’adapter ses repas en fonction, et ces informations pourraient également servir à alimenter une base de données de recettes dans le but de diversifier les plats préparés et d’optimiser leur consommation.
C’est pourquoi nous avons voulu développer une application permettant de savoir exactement quels aliments nous avons chez nous et ainsi proposer en fonction, des recettes adaptées à l’utilisateur.
Méthodes étudiées pour la récupération des données
Il n’est pas aisé de connaître en temps réel la liste exacte des produits alimentaires que l’utilisateur a chez lui.
Nous avons étudié 3 méthodes possibles pour mettre en place cet inventaire :
- Méthode 1 : scan du code-barre de l’ensemble des produits achetés par l’utilisateur.
- Avantages : sûr et facile à mettre en œuvre
- Inconvénient : très répétitif d’un point de vue utilisateur - Méthode 2 : prise de photo de l’ensemble des produits achetés par l’utilisateur et application d’un algorithme de reconnaissance d’images pour extraire la liste des produits.
- Avantage : facile à appliquer pour l’utilisateur, il lui suffit de disposer tous les produits sur une table et de prendre une photo de l’ensemble
- Inconvénient : le traitement des données est compliqué, car il faudrait s’assurer que tous les produits soient bien visibles sur l’image et avoir une base de données d’images avec ces mêmes produits - Méthode 3 : prise de photo du ticket de caisse des produits achetés par l’utilisateur et application des algorithmes d’OCR (reconnaissance de caractères) et de NLP (traitement du langage) pour extraire la liste des produits et les classifier.
- Avantage : facile pour l’utilisateur, il lui suffit de prendre en photo chaque ticket de caisse, et l’application se chargera de mettre à jour la liste des produits à disposition.
- Inconvénients : les tickets de caisses ne sont pas normalisés, ce qui signifie que chaque enseigne produit un ticket de format différent. L’OCR risque d’être difficile. Il en est de même pour les noms de produits. Un même produit peut apparaître écrit différemment sur le ticket de caisse d’une enseigne à l’autre. Par exemple des petits pois peuvent être écrits ‘PETIT POIS’ ou ‘PTIT POIS’.
Nous avons opté pour l’implémentation de deux méthodes différentes, laissant ainsi le choix à l’utilisateur entre : scan des codes-barres ou scan du ticket de caisse.
Nous nous sommes donc attaqués à la problématique du scan des tickets de caisse.
Cette solution est très intéressante, mais aussi très challengeante car elle nécessite d’utiliser des méthodes d’analyse et de traitement d’images combinés à des algorithmes de traitement de textes.
Pour constater la difficulté de la tâche, il suffit de voir la diversité des templates de tickets de caisse :
De plus dans cet exemple, les tickets ont tous le même fond mais il faut être conscient que le fond peut être très différent à chaque nouvelle photo.
Pour réaliser ce système d’analyse de tickets de caisses, nous avons alors défini la pipeline suivante :
Dans la suite de cet article, nous nous concentrerons uniquement sur les deux points suivants : la génération artificielle de données d’apprentissage et la classification des noms de produits.
Génération d’un dataset de tickets de caisse
Le premier problème majeur que nous avons rencontré fut le manque de données disponibles. En effet, les données sont essentielles pour entraîner des modèles d’apprentissage automatiques mais aussi pour tester nos modèles. Et nous avons réalisé qu’il est compliqué de trouver des tickets de caisse français sur Internet et encore plus de les trouver annotés. L’annotation est la clé de l’apprentissage automatique, si nous voulons par exemple tester un algorithme OCR (qui transforme une image en texte), car nous avons besoin pour chaque image de ticket, du texte correspondant.
Dans un premier temps nous avons donc essayé de créer un programme capable de générer une quantité importante de tickets de caisse artificiels qui se rapprochent visuellement de tickets de caisse réels.
La première étape pour générer des tickets de caisse artificiels est de pouvoir générer des noms de produits. Puis, notre programme doit aussi pouvoir générer différents templates (différents logos, différentes marges, différents ordres des informations, etc.). Et enfin, les tickets de caisse étant souvent chiffonnés et donc déformés, puis comme nous l’avons vu avec des fonds photo pouvant varier, notre programme devra aussi simuler ces déformations lors de la génération d’images.
Génération de noms de produits
Vous l’avez peut-être remarqué, les noms de produits inscrits sur les tickets de caisse sont souvent abrégés, et n’ont le plus souvent, plus rien à voir avec le nom de produit de départ.
Il nous faut donc utiliser un algorithme permettant de simuler les transformations appliquées. Nous y reviendrons plus en détail dans la suite de l’article.
Les étapes de génération de noms de produits sont les suivantes :
Génération de tickets de caisse
Après la génération de noms de produits, l’étape suivante est la génération de tickets de caisse, que nous avons réalisée selon le procédé suivant :
Quelques points importants sont à souligner :
- La déformation élastique appliquée est celle décrite dans Best Practices for Convolutional Neural Networks Applied to Visual Document Analysis. Cette méthode, qui déforme l’image en appliquant des déplacements aléatoires à chaque pixel, est très utilisée pour augmenter les données lorsqu’on entraîne un réseau de neurones convolutionnels. Dans notre cas, cette déformation est très importante, cela permet de simuler les nombreuses déformations que peut subir un ticket de caisse. La force de la déformation peut être contrôlée par un paramètre alpha. L’impact de ce paramètre sera étudié par la suite.
- Les fonds utilisés sont ceux téléchargés depuis Describable Textures Dataset
- L’angle de rotation et le padding (fait d’agrandir l’image en ajoutant des pixels aux bords de l’image) peuvent avoir des valeurs différentes à chaque génération. Ces deux paramètres sont essentiels pour simuler les différentes prises de vues possibles.
Quelques exemples de tickets de caisse générés artificiellement :
Test fonctionnel de notre générateur de tickets de caisse
Maintenant que nous avons notre générateur de tickets de caisse, il nous reste à vérifier s’il peut être utilisé pour entraîner des modèles d’apprentissage automatique, à défaut de tickets de caisse réels.
Pour ce faire, nous avons décidé d’entraîner un modèle capable de détecter précisément le ticket de caisse dans une image (segmentation d’images) en utilisant uniquement nos images artificielles lors de l’entraînement.
Nous testerons ensuite le modèle avec des images de ticket de caisse réels. Cela nous permettra de vérifier si notre générateur d’images de tickets de caisse suffit pour entraîner un modèle qui devra fonctionner avec des images réelles. Ce modèle servira comme preprocessing à la partie OCR. En effet, si l’on est capable de détecter le ticket de caisse, cela facilitera alors la transformation de l’image en texte.
Segmentation de l’image
Pour la segmentation, nous avons décidé d’utiliser Unet, une architecture basée sur des réseaux de neurones convolutionnels, conçue spécifiquement pour cette tâche. Cette architecture a fait ses preuves à de multiples reprises pour résoudre des problèmes de segmentation d’images et devrait convenir à notre projet.
Après avoir entraîné notre modèle, nous avons testé la segmentation à la fois sur des images artificielles et sur des images réelles. Pour connaître le paramètre alpha de déformation élastique le plus approprié, afin d’avoir des images le plus réalistes possible, nous avons entraîné deux modèles différents avec respectivement alpha = 2.0 (déformation moyenne) et alpha=4.0 (forte déformation).
Les résultats obtenus sont les suivants :
- Segmentation avec des tickets générés artificiellement
- Segmentation avec des tickets réels — Elastic alpha 2.0
- Segmentation avec des tickets réels — Elastic alpha 4.0
En regardant ces résultats, on s’aperçoit que le modèle de segmentation est capable de fonctionner correctement sur des images artificielles mais la segmentation n’est malheureusement pas aussi parfaite avec les images réelles.
On remarque également que varier le paramètre alpha ne permet pas de remarquer de différence notable dans les résultats.
D’après les résultats, il est évident que le générateur d’images artificielles n’est pas encore assez performant pour remplacer un vrai dataset de tickets de caisse. Cela peut s’expliquer par plusieurs choses :
- la déformation élastique n’est pas assez représentative des déformations réelles,
- les fonds utilisés ne sont pas assez représentatifs de fonds de la vie réelle.
Pour obtenir de meilleurs résultats, il convient donc de trouver une autre méthode permettant de mieux simuler les déformations que peut subir un ticket de caisse.
Bilan sur la génération de tickets de caisse artificiels
Avec du recul et au vu des résultats obtenus, nous pensons qu’il aurait été plus judicieux de réaliser un dataset basé sur des tickets de caisse réels. Cela nous aurait permis d’avoir un dataset fiable et des résultats plus représentatifs de la réalité.
En effet, bien que l’annotation manuelle puisse prendre quelques semaines, nous aurions pu nous baser sur un dataset fiable et utilisable pour tous types de modèles.
À noter que lors de la création d’un générateur d’images, il faut le tester et prouver son efficacité. Car même s’il est efficace sur une tâche spécifique, il peut ne pas l’être pour une autre.
Enfin, bien que la génération de données artificielles n’a pas été assez concluante pour cette tâche, elle peut s’avérer utile dans d’autres cas, comme ce fut le cas pour la génération de noms de produit.
Création d’un système de classification de nom de produit
Il est essentiel, si l’on souhaite faire l’inventaire automatique des achats effectués, de pouvoir attribuer une catégorie à chaque nom de produit présent dans le ticket de caisse.
Dataset de noms de produits
Pour résoudre cette problématique, nous avons besoin d’un ensemble de données qui répertorie des noms de produits et leur attribue une classe. L’ensemble de données doit être en français. Nous avons décidé dans un premier temps d’utiliser un outil français de données open source : OpenFoodFacts. Ce dataset, notamment utilisé par l’application Yuka, est continuellement alimenté par la communauté. C’est ce qui en fait sa richesse en terme de produits, mais qui peut également le rendre plus susceptible de faire de mauvaises classifications, des doublons, etc.
Nous avons tout de même utilisé OpenFoodFacts car il s’agit de la seule base de données open source disponible en français.
Les noms de produits présents sur OpenFoodFacts ne sont pas écrits de la même façon que sur les tickets de caisses. Vous l’avez peut-être remarqué, les noms de produits sur les tickets de caisse sont majoritairement abrégés et n’ont souvent plus rien à voir avec le nom d’origine du produit. Après analyse manuelle de plusieurs tickets de caisse, nous avons notamment remarqué plusieurs choses :
- les voyelles ont une forte chance d’être supprimés,
- les lettres sont la plupart du temps en majuscule,
- les noms de produits dépassent rarement 20 lettres.
Pour concevoir notre système de génération de noms de produits, nous avons donc utilisé la base de données OpenFoodFacts pour extraire des noms de produit, que nous avons ensuite normaliser selon différentes règles, afin de générer des noms de produits bruités qui ressemblent à ceux que l’on trouve sur les tickets de caisse.
Les normalisations appliquées sont les suivantes :
- enlever les caractères spéciaux : ces caractères-là sont très peu présents sur les tickets de caisse,
- mettre toutes les lettres en majuscule comme c’est le cas sur la plupart des tickets de caisse,
- n% des voyelles sont supprimées des tickets de caisse. Les enseignes utilisent souvent ce procédé car il n’y a tout simplement pas la place de tout écrire sur un ticket. Nous faisons varier n entre 0 et 30% pour créer une invariance aux différentes méthodes utilisées par les enseignes.
La génération de noms de produits a donc suivi ces différentes étapes :
Nous avons ainsi pu générer 320 000 noms de produits différents.
Tous les produits appartenants à des classes peu fréquentes (présentes moins de 10 fois) ne sont pas utilisés. Après avoir réalisé ce nettoyage, il reste 4197 classes.
L’ensemble de données a été séparé en 3 sous-ensembles :
- un ensemble d’entraînement contenant 260 000 noms de produits,
- un ensemble de validation contenant 30 000 noms de produits,
- un ensemble de test contenant 32 000 noms de produits.
Modèle d’attribution de classe à un nom de produit
Comme déjà expliqué, le but est d’avoir un modèle capable d’attribuer une classe à n’importe quel nom de produit présent dans un ticket de caisse, selon le procédé suivant :
Le modèle prend en entrée le nom de produit, puis un travail de préprocessing est réalisé, notamment avec la suppression de toutes les lettres qui ne sont pas des caractères alphanumériques. Ensuite nous transformons la représentation du nom de produit en utilisant le one hot encoding pour qu’il soit compréhensible et traitable par n’importe quel modèle de machine learning.
Pour réaliser le one hot encoding, il suffit d’encoder chaque lettre du nom de produit. Nous avons défini le nombre de lettres possible à 27 (26 lettres de l’alphabet + espace). Chaque lettre est donc représentée par un vecteur de taille 27 qui ne contient que des zéros, mis à part la position de la lettre correspondante où la valeur sera 1.
Le choix du modèle de machine learning s’est porté sur les modèles RNN (Recurrent neural network) notamment pour leur efficacité prouvée à de nombreuses reprises dans l’analyse de texte (ex : Analyse de sentiments dans un texte). Ces modèles sont le plus souvent utilisés pour analyser et traiter des données séquentielles/temporelles telles que le son et le texte. L’idée de ce réseau de neurones est de prendre en entrée des données dans un ordre spécifique et de produire une sortie correspondante (telle que la réponse à une question ou la classification d’un texte).
Nous avions également expérimenté les modèles LSTMS et GRUS, qui sont tous deux des réseaux de neurones récurrents. Nous avons obtenu de meilleurs résultats sur l’ensemble de validation en utilisant des GRUS. Pour plus d’informations sur ces modèles, je vous invite à lire cet excellent article.
Bilan sur la classification de noms de produits
Sur l’ensemble des tests réalisés à partir du dataset OpenFoodFacts, nous avons obtenu un score de 56 % d’accuracy. Cette métrique a été calculée en faisant en sorte que les 4197 classes retenues aient le même poids indépendamment du nombre de produits qu’elles contiennent.
Mais en regardant les résultats de plus près, on remarque que ceux-ci sont encore meilleurs que le score annoncé. Cela est dû au dataset OpenFoodFacts qui reste très hasardeux puisque n’importe quel utilisateur a la possibilité d’alimenter la base de données.
À titre d’exemple :
- Pour le nom de produit ‘SAUCISSES DE TULOUS’, le modèle prédit : ‘saucisses-de-toulouse-aux-lentilles’, alors que la bonne catégorie était ‘charcuteries à cuire’.
- Pour le nom de produit ‘PETT SALE UX LENTILL’, le modèle prédit la catégorie ‘petits-sales-aux-lentilles’ alors que la bonne catégorie (celle assignée par l’utilisateur) est ‘petit-sale’.
- Pour le nom de produit ‘GAZPACHO ROGE’, la bonne catégorie est ‘boissons-sans-sucre-ajoute’ alors que le modèle a prédit ‘gazpacho’.
Il y a beaucoup d’autres exemples de ce type qui montrent que le dataset n’est pas propre et les catégories non exclusives.
Le modèle nous permet tout de même de sortir une catégorie cohérente la plupart du temps et est donc potentiellement utilisable pour la recommandation de recettes.
En exemple, vous pouvez comparer dans ce tableau les prédictions de classification vs les bonnes classifications :
Pour avoir un modèle encore plus précis, plusieurs solutions sont envisageables :
- nettoyer la base de données openFoodFacts manuellement dans le but de n’avoir que des classes exclusives. Mais cela prendrait énormément de temps car on compte 700 000 produits et plus de 4000 catégories.
- Trouver une base de données beaucoup plus propre, en extrayant les informations automatiquement (scrapping) depuis des sites comme Carrefour et Auchan par exemple. Mais beaucoup de sites empêchent cette méthode aujourd’hui.
- Mettre en place un partenariat avec une entreprise pour récupérer ces données.
En conclusion, nous avons obtenu un bon modèle capable d’attribuer le plus souvent une classe correcte à un nom de produit. Cela peut donc être utilisé pour créer un moteur de recettes, si on arrive à associer chaque classe à un ingrédient d’un site de recettes. La meilleure solution reste de faire cette association manuellement pour chaque site de recette.
En revanche, en raison du nombre important de classes la tâche s’annonce ardue.
C’est pour cela qu’il serait intéressant de trouver une meilleure base de données.
Rétrospective du projet
En conclusion, ces deux POC nous ont permis de comprendre l’utilité mais aussi les limites de la génération de données artificielles dans l’apprentissage de modèles.
En effet, on a vu en première partie que même si cela peut être utile pour une application spécifique, la génération de données artificielles perdait en fiabilité dans notre cas. Il est donc important d’estimer en amont les avantages et inconvénients par rapport à la collecte et à l’annotation des données.
Et en deuxième partie, nous avons aussi pu remarquer les problématiques engendrées par une base de données publique et modifiable par tous.
Nous publions régulièrement des articles sur des sujets de développement produit web et mobile, data et analytics, sécurité, cloud, hyperautomatisation et digital workplace.
Suivez-nous pour être notifié des prochains articles et réaliser votre veille professionnelle.
Retrouvez aussi nos publications et notre actualité via notre newsletter, ainsi que nos différents réseaux sociaux : LinkedIn, Twitter, Youtube, Twitch et Instagram
Vous souhaitez en savoir plus ? Consultez notre site web et nos offres d’emploi.
L’auteur
Data Scientist @Linkvalue