« BottinBot3 » : différence entre les versions

De Wikipast
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
 
Ligne 28 : Ligne 28 :
Nous procédons dans un premier temps à un parcours entier du bottin afin de déterminer quelles entrées correspondent à une même personne en y appliquant la stratégie mentionnée auparavant. Concrètement, nous commençons par grouper les entrées par leur année. Puis nous parcourons les entrées de la plus petite année, et pour chacune de celles-ci, nous ajoutons une entrée à un dictionnaire de la forme suivante : nom -> [((job, rue), [index])]. Si le nom existe déjà dans le dictionnaire, alors nous ajoutons le tuple de job, rue et index à la liste des valeurs.
Nous procédons dans un premier temps à un parcours entier du bottin afin de déterminer quelles entrées correspondent à une même personne en y appliquant la stratégie mentionnée auparavant. Concrètement, nous commençons par grouper les entrées par leur année. Puis nous parcourons les entrées de la plus petite année, et pour chacune de celles-ci, nous ajoutons une entrée à un dictionnaire de la forme suivante : nom -> [((job, rue), [index])]. Si le nom existe déjà dans le dictionnaire, alors nous ajoutons le tuple de job, rue et index à la liste des valeurs.


Puis nous continuons le parcours des données avec celles des années suivantes, toujours dans l'ordre chronologique. A partir de cet instant, l'algorithme se complexifie un peu. Cette fois, si le nom existe déjà dans le dictionnaire, alors nous comparons la ligne actuelle avec la liste des valeurs du dictionnaire pour ce nom. Si alors un de ces tuples (job, rue) est similaire au tuple de la ligne actuelle, alors nous ajoutons simplement l'index à la liste d'index correspondante.
Puis nous continuons le parcours des données avec celles des années suivantes, toujours dans l'ordre chronologique. A partir de cet instant, l'algorithme se complexifie un peu. Cette fois, si le nom existe déjà dans le dictionnaire, alors nous comparons la ligne actuelle avec la liste des valeurs du dictionnaire pour ce nom. Si alors un de ces tuples (job, rue) est similaire au tuple de la ligne actuelle, alors nous ajoutons simplement l'index à la liste d'index correspondante et mettons à jour la valeur du tuple avec les données de la ligne actuelle.


Notre bot crée un dictionnaire et parcourt ces entrées dans l'ordre chronologique. Pour chaque personne, une entrée est créée contenant avec comme clé son nom, puis comme valeur une liste contenant un tuple avec son métier et sa rue qui sera utilisé pour comparer les personnes, ainsi qu'une liste d'index pour retrouver la personne dans notre jeu de données lors de la saisie finale sur wikipast. Si le nom de la personne existe déjà dans le dictionnaire, alors ses champs viennent être ajoutés à la clé correspondante.
Notre bot crée un dictionnaire et parcourt ces entrées dans l'ordre chronologique. Pour chaque personne, une entrée est créée contenant avec comme clé son nom, puis comme valeur une liste contenant un tuple avec son métier et sa rue qui sera utilisé pour comparer les personnes, ainsi qu'une liste d'index pour retrouver la personne dans notre jeu de données lors de la saisie finale sur wikipast. Si le nom de la personne existe déjà dans le dictionnaire, alors ses champs viennent être ajoutés à la clé correspondante.

Dernière version du 19 mai 2020 à 08:56

Résumé des fonctionnalités

Ce bot a pour but d'insérer des données sur Wikipast issues de l'extraction de 4 Million d'adresses des anciens annuaires de la ville de Paris qui fut réalisée par l'équipe du DHLAB en 2019.

Notre BottinBot3 traite un sous-ensemble de ces données correspondant aux années 1857 à 1864. Soit un total de 548704 entrées.

Stratégies

Afin de créer des pages cohérentes à partir de notre jeu de données, il nous a fallu dans un premier temps mettre en places des stratégies afin de regrouper les entrées correspondant aux mêmes personnes. De plus, ces stratégies doivent également dans une certaine mesure pallier aux erreurs d'extraction de texte.

Comparaison entre deux entrées

Afin de décider si deux entrées A et B correspondent à la même personne les conditions suivantes doivent être remplies:

  • Le nom de A et B doit être strictement identique
  • Les années de A et B doivent être différentes
  • Les champs de métier ou les champs de rue doivent être similaires

Cette dernière condition permet de non seulement pallier à certaines erreurs d'OCR (ex: "bronzos" au lieu de "bronzes") mais également d'autoriser une personne à avoir déménagé ou à avoir changé de métier. La similarité entre deux entrées est calculée en fonction du nombre totale de lettre que les deux champs partagent à l'aide de la classe SequenceMatcher du module difflib. Ce ratio de similarité est ensuite comparée à un coefficient que nous avons mis à 85%.

Cas d'homonymie (lors de l'ajout de la page)

Comme les données de l'annuaire contiennent forcément plusieurs personnes ayant le même nom, il est indispensable de gérer le cas des homonymes. Pour ce faire, nous utilisons la technique décrite ci-dessus afin de déterminer s'il s'agit de la même personne ou d'un de ses homonymes. Si nous concluons qu'il s'agit bien d'un homonyme, alors nous créons une nouvelle entrée pour cette personne et toute nouvelle apparition de ce nom dans le reste des données sera comparé avec toutes les entrées du même nom.

Au moment de créer les pages Wikipast, nous contrôlons alors combien de personnes ont le même prénom. Si une personne est seule à porter son nom, alors sa page peut être insérée avec uniquement son nom comme titre. Si en revanche un nom est portée par plusieurs personnes, alors la page est créée avec le titre ainsi que le métier comme titre.

Ne pas effacer des pages préexistante

Lorsque nous créons des pages pour nos entrées du bottin, nous devons être consciencieux de ne pas effacer des pages qui existeraient déjà. Non seulement les autres BottinBot ont peut-être déjà créer une page pour cette personne, mais on peut également s'imaginer que des personnes connues de Paris se trouvant dans nos données du bottin aient déjà leur page sur Wikipast. Pour pallier à ce problème, nous ne procédons véritablement à la création des pages que si une ayant le même nom n'existe pas déjà. Si tel est le cas, alors nous ajoutons de la précision au titre (le métier, puis la rue) et réessayons à chaque fois. Si toutefois après avoir ajouté assez de précision la page n'a toujours pas pu être ajoutée, alors nous abandonnons l'entrée.


Description technique

Les données extraites du bottin ont la forme suivante (avec l'URL rajouté évidemment par après):

directory, page, row, year, name, job, street, number, street_clean, street_only, url

Nous procédons dans un premier temps à un parcours entier du bottin afin de déterminer quelles entrées correspondent à une même personne en y appliquant la stratégie mentionnée auparavant. Concrètement, nous commençons par grouper les entrées par leur année. Puis nous parcourons les entrées de la plus petite année, et pour chacune de celles-ci, nous ajoutons une entrée à un dictionnaire de la forme suivante : nom -> [((job, rue), [index])]. Si le nom existe déjà dans le dictionnaire, alors nous ajoutons le tuple de job, rue et index à la liste des valeurs.

Puis nous continuons le parcours des données avec celles des années suivantes, toujours dans l'ordre chronologique. A partir de cet instant, l'algorithme se complexifie un peu. Cette fois, si le nom existe déjà dans le dictionnaire, alors nous comparons la ligne actuelle avec la liste des valeurs du dictionnaire pour ce nom. Si alors un de ces tuples (job, rue) est similaire au tuple de la ligne actuelle, alors nous ajoutons simplement l'index à la liste d'index correspondante et mettons à jour la valeur du tuple avec les données de la ligne actuelle.

Notre bot crée un dictionnaire et parcourt ces entrées dans l'ordre chronologique. Pour chaque personne, une entrée est créée contenant avec comme clé son nom, puis comme valeur une liste contenant un tuple avec son métier et sa rue qui sera utilisé pour comparer les personnes, ainsi qu'une liste d'index pour retrouver la personne dans notre jeu de données lors de la saisie finale sur wikipast. Si le nom de la personne existe déjà dans le dictionnaire, alors ses champs viennent être ajoutés à la clé correspondante.

Après avoir traité toutes les données, l'entrée pour le nom "Ollivier" correspond à:

"Ollivier" -> [[('café de la Redoute', 'Grenelle-SaintHonoré'), [47444]], [('limonadier', 'boulevard Beaumarchais'), [47447, 115747, 530253, 313487]], ... ]

Concrètement, cela signifie que le Ollivier travaillant au café de la Redoute n’apparaît qu'une seule fois dans le bottin alors que le limonadier apparaît 4 fois (cf. Ollivier café de la Redoute et Ollivier limonadier)


Enfin nous pouvons insérer les pages correspondantes sur Wikipast. Pour chaque année d'apparition d'une personne dans le dictionnaire, nous ajoutons une entrée de la forme suivante à sa page:

* [[year]] / [[Paris]], [[street_clean]] number. Mention de [[name]] avec la catégorie [[job]] [url]

Pour le titre de la page, nous regardons la taille de la liste des valeurs du dictionnaire pour un nom précis. Si la taille est de 1 alors nous utilisons le nom comme titre, sinon nous utilisons le nom et le métier. Comme précisé auparavant, nous ne créons la page que si celle-ci n'existe pas. Pour ce faire nous utilisons simplement le paramètre createonly=True lors de l'upload et, en cas d'échec, nous ajoutons de la précision au titre (dans un premier temps le job si celui-ci n'est pas déjà présent, puis la rue) et réessayons l'upload.

Évaluation des performances

  • La première phase du bot consistait à la création du dictionnaire. Pour ce faire, il nous a fallut approximativement 10 minutes. Il possède 164776 clés.
  • La deuxième phase consistait à la création des pages et à son insertion sur Wikipast. Plus de 10 heures ont été nécessaires pour réaliser ce travail. Il est à souligner que la création de toutes les pages prenait approximativement 3 minutes. Ceci implique que l'accès au site était la source de 99.995% du temps.
  • Plus de 200000 pages ont été créées.

Analyse critique

Un premier défaut de notre implémentation est que nous utilisons une égalité stricte pour le nom. Cela signifie que nous ne corrigeons pas d'erreurs d'OCR qui s'y seraient glissées et créons par exemple les pages Maillard fab. de billards et · Maillard alors qu'il s'agit vraisemblablement de la même personne. De plus BottinBot3 se contente d'ajouter de la précision au titre lorsqu'une page existe déjà pour une personne. A la place, celui-ci pourrait ajouter son contenu à cette page. Cela requérait toutefois de faire une requête supplémentaire vers Wikipast ce qui, compte tenu de l'évaluation des performances, pourrait potentiellement doubler le temps d'exécution. De plus, même si cela était réalisable, il faudrait que toutes les pages adoptent un format strict afin que nos données puissent être insérées au bon endroit. Un point critiquable est également que notre bot ne permet pas de faire la distinction entre 2 personnes ayant la même année le même nom et le même métier ou habitant la même rue.

Extensions

Nous avons tenté d'étendre notre BottinBot3 pour que celui-ci crée également des pages pour chaque rue et y recense les personnes y ayant habité durant quelles années. Malheureusement en raison de problèmes techniques nous n'avons pas pu générer toutes les pages. Une partie d'entre elles ont toutefois pu être générée (ex: Passage Choiseul, Rivoli, Bondy)

Exemples

Exemple de corrections d'erreurs d'OCR

Données initiales:

BottinBot3 Aaron.png

Entrée dans le dictionnaire:

{Aaron: [[('bronzes', 'passage Choiseul'), [0, 133152, 195814, 332171, 62461, 474299, 257014]]]}

Saisie finale sur Wikipast: voir Aaron

Exemple de déménagement

Voir Zurcher (Mme)

Exemple d'homonymes

Voir Sieurin estampes et Sieurin objets de religion

Code

Le code est disponible sur GitHub à cette adresse