Bienvenue à tous les Valentin dans le deuxième opus de la série des curieuses machines. Cette colonne me sert de vitrine virtuelle pour une machine conçue et fabriquée à l’Atelier. J’y explique en quoi elle consiste, ce qu’elle fait, et surtout à quoi elle peut bien servir !
14 février 2023 – Trouver les SIREN de mes clients
Le contexte : L’intégration d’une nouvelle société dans le Groupe
Cette machine a été conçue et fabriquée spécifiquement pour un client confronté à un problème imprévu.
Il vient en effet de faire l’acquisition d’une société et doit rapidement, pour répondre à ses obligations, être capable de suivre de près son activité commerciale. Il ne s’agit pas spécifiquement de mesurer la performance, mais bien de pouvoir analyser chacune des offres et des contrats pour éviter tout recouvrement avec son activité historique.
Dans ce contexte, plusieurs informations lui sont nécessaires. La première est évidemment l’identité des clients et prospects avec lesquelles la nouvelle société fait affaire.
Et c’est en posant la question que le problème est apparu : la société en question maintient bien, et fort proprement, la liste des clients, des offres et des contrats, mais n’a jamais jugé nécessaire de lier chaque client à un numéro d’identification unique que mon client puisse reconnaître !
Seuls les noms des clients et prospects sont disponibles.
Or, sans un moyen de comparer les clients et prospects historiques avec ceux de la nouvelle société, il est impossible d’éviter les recouvrements, alors que les deux sociétés doivent parfois éviter de travailler pour le même client.
Pour résoudre ce souci, nous avons estimé qu’il faudrait deux bonnes semaines de travail à une personne du service administratif pour identifier, grâce aux différents sites proposant ce service, les milliers de sociétés constituant la base client.
Alternativement, l’Atelier des Données pouvait construire une machine pour essayer de relier ces noms aux identifiants uniques, ce qui ne devrait pas prendre beaucoup de temps !
C’est l’histoire de cette machine, et la façon dont ce pas beaucoup de temps
s’est transformé en un programme puissant et polyvalent, dont je veux vous régaler aujourd’hui.
L’étrange machine
J’entre ici dans quelques détails techniques, à la fois sur la structure de la machine, mais aussi sur la nature des données qu’elle a dû traiter.
Il existe bien un numéro d’identification des entreprises, public et utilisable par tous ; en France, il s’agit du numéro SIREN, pour “Système Informatique pour le Répertoire des ENtreprises”, géré par l’Institut National de la Statistique et des Études Économiques (INSEE). C’est un nombre entier à neuf chiffres. Il sert de base à l’identification des établissements (numéro SIRET), et au numéro de TVA de l’entreprise à l’échelle Européenne.
La base de données des SIREN est disponible publiquement sur Internet, elle comprend plus de 20 millions d’entreprises. On peut la télécharger dans son intégralité, ou bien rechercher une entreprise directement sur une page internet.
Le problème consiste donc à relier le nom des prospects et clients à un numéro de SIREN.
Malheureusement, le “nom” de client ou de prospect utilisé par la société récemment acquise n’est pas forcément le nom officiel (ou “Raison Sociale”) des entreprises, ce qui n’étonnera pas les personnes familières avec ce type de problèmes. Pour une proportion importante des cas, il ne s’agit même pas du “nom usuel” des entreprise, que l’INSEE tient obligeamment à notre disposition lui aussi. Enfin, je ne peux m’empêcher de noter que certains de ces “noms” sont tout à fait fantaisistes, et ne se laisseront jamais mettre en regard d’une entreprise.
Nous avons donc une liste de textes représentant le “nom” d’entreprises, associé d’ailleurs à des informations d’adresse, que nous devons relier soit directement à des SIREN, soit à des Raisons Sociales, soit à des noms usuels d’entreprises.
La machine consiste donc en :
- Un module projetant la liste des Raisons Sociales et dénominations usuelles dans un espaces de n-grammes à environ un million de dimensions;
- Un module permettant de trouver la distance d’un “nom” de client ou prospect à chacun des Raisons Sociales et dénominations usuelles grâces au module précédent;
- Un module sélectionnant les quelques Raisons Sociales et dénominations usuelles les plus proches de chaque “nom” entre les deux listes
- Un module effectuant la sélection finale pour chaque “nom” avec un autre système pour comparer les noms, plus efficace sur des noms qui se ressemblent déjà un peu;
- Un module pour rapprocher finalement les “noms” des numéros SIREN correspondant à la meilleure pioche donnée par le module précédent.
Ce traitement ne doit avoir lieu qu’une seule fois, ainsi je n’ai pas ajouté à la machine de convoyeur ou de silo pour automatiser les entrées de “noms” et les sorties de SIREN.
La machine en fonctionnement
Je veux détailler ici un peu plus, pour ceux que le sujet intéressera, les outils de traitement.
La génération et le traitement des n-grammes se fait grâce à un flux de données de nettoyage des textes permettant d’enlever les caractères bizarres et les accents, puis un algorithme de vectorisation TF-IDF, c’est à dire la création d’un modèle de langage sur les dénominations de l’INSEE, puis son application à la liste des “noms” de clients et prospects.
Le calcul de distance entre les Raisons Sociales et dénominations usuelles d’une part et les “noms” de clients et prospects d’autre part est réalisé selon la mesure de la cosine similarity, appliquée à des matrices creuses, et limitée aux quelques meilleurs résultats.
La sélection finale peut être effectuée après l’étape du modèle de langage selon une variation de la mesure de distance de Levenshtein. Il n’apparaît pas clairement d’amélioration de la pertinence des scores, mais ce point peut permettre de rendre ces derniers plus facilement explicables.
L’ensemble du traitement prend environ 7 heures sur une machine portable moderne, en raison essentiellement de limitations de la mémoire vive.
Il est à noter que dans l’hypothèse où on ne prend que la meilleure correspondance du modèle de langage, il est beaucoup plus efficace de créer ce dernier sur les “noms”, bien moins nombreux. le traitement s’en trouve un peu raccourci, et le résultat est parfaitement identique.
Ce stratagème fonctionnerait aussi si l’on souhaitait “empiler les modèles”, c’est à dire retenir par exemple les 10 meilleures correspondances issues du modèle de langage, puis sélectionner ces finalistes grâce à une mesure de distance simple.
Les résultats
La liste des clients et prospects pourra être utilisée pour l’usage prévu.
Environ 50% des correspondances trouvées peuvent être utilisées telles-quelles (similarité cosine > 95%), et 25% supplémentaires nécessitent une validation rapide pour être validés. Quant aux 25% restant, il s’agit de ces “noms” sans rapport réel avec une société existante, qu’il sera impossible d’intégrer ou d’éliminer sans se plonger dans davantage d’informations dans les dossiers de la société.
L’outil me semble donc redoutable. La machine est à présent rangée, avec sa documentation et attend d’être invoquée une nouvelle fois.
Le cas d’usage, lui, me rappelle quelle aventure passionnante et frustrante est chaque découverte de jeu de données !
Références et bibliothèques utilisées
Ce travail a été largement inspiré par l’article d’Alina Zhang intitulé Fuzzy String Match With Python on Large Datasets and Why You Should Not Use FuzzyWuzzy
Par ailleurs, le lecteur avisé pourra explorer la bibliothèque créée par la Banque des Pays-Bas, name_matching
, décrite dans un article elle aussi. On peut remplacer une large part du travail exposé ici par l’utilisation de cette bibliothèque. Il sera simplement nécessaire de disposer d’une machine très puissante, puisque ce projet aurait pris au moins un mois de calcul avec cet outil !
Enfin, le lecteur plus informaticien qu’amoureux d’apprentissage automatique pourra décider d’utiliser l’API fournie par l’INSEE qui, pour touffue et rébarbative qu’elle est, permettrait probablement d’obtenir un résultat similaire en remplaçant le temps des essais et erreurs au milieu des gigantesques matrices par l’attente des résultats fournis par cet outil.
numpy – Harris, C.R. et al., 2020. Array programming with NumPy. Nature, 585, pp.357–362.
pandas – McKinney, W. & others, 2010. Data structures for statistical computing in python. In Proceedings of the 9th Python in Science Conference. pp. 51–56
scipy – Virtanen, P. et al., 2020. SciPy 1.0: Fundamental Algorithms for Scientific Computing in Python. Nature Methods, 17, pp.261–272.
scikit-learn – Pedregosa, F. et al., 2011. Scikit-learn: Machine learning in Python. Journal of machine learning research, 12(Oct), pp.2825–2830.
Levenshtein
sparse_dot_topn