« BottinBot3 » : différence entre les versions

De Wikipast
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
 
(14 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
== Résumé des fonctionnalités ==
== 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.
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 [https://drive.google.com/open?id=1gvN6Fq1z2cfIJA_IwWOgRubctOiYNEZT données groupe 3] correspondant aux années 1857 à 1864. Soit un total de 548704 entrées.
Notre [[BottinBot3]] traite un [https://drive.google.com/open?id=1gvN6Fq1z2cfIJA_IwWOgRubctOiYNEZT sous-ensemble de ces données] correspondant aux années 1857 à 1864. Soit un total de 548704 entrées.


== Description technique ==
== Stratégies ==
Le bottin contient des entrées de la forme suivante:
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.
directory, page, row, year, name, job, street, number, street_clean, street_only
=== 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%.


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.
=== 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.


Il se peut qu'une personne se retrouve d'années en années. Pour ce faire, nous comparons son nom, son travail et sa rue et s'il s'agit effectivement de la même personne, alors l'index de sa nouvelle apparition est ajoutée à la liste d'index.
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.


*Exemple d'une entrée du dictionnaire:
=== Ne pas effacer des pages préexistante ===
{"Ollivier" : [[('café de la Redoute', 'Grenelle-SaintHonoré'), [47444]], [('limonadier', 'boulevard Beaumarchais'), [47447, 115747, 530253, 313487]], ... }
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.  


Puis nous insérons les données 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:
<nowiki>* [[year]] / [[Paris]], [[street_clean]] number. Mention de [[name]] avec la catégorie [[job]] </nowiki>


== Stratégies ==
== Description technique ==
Dans le but de donner le plus de sens possible aux données, il a fallut mettre au point des stratégies afin de regrouper les mêmes personnes ensemble ainsi que pallier aux erreurs d'extraction.
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 basons nos comparaisons sur les entrées de la première année (soit 1857).
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.


=== Comparaison entre deux personnes ===
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.
Lorsqu'une entrée du bottin est lue , nous comparons si son nom est contenu dans le dictionnaire. Deux issues sont possibles:
* Le nom n'existe pas dans le dictionnaire: alors une nouvelle entrée est ajoutée au dictionnaire comme décrit précédemment.
* Le nom est dans le dictionnaire: alors la personne est comparée à toutes les personnes ayant le même nom. S'il existe une entrée avec le même nom, le même métier et la même rue, nous considérons que ces deux personnes sont les mêmes. Ce faisant l'index où elle a été trouvée vient être ajouté à la liste d'index. Si aucune des personnes ne lui ressemble assez, alors nous considérons qu'il s'agit d'une nouvelle personne.


Nous utilisons une fonction de comparaison entre les différents champs pour compenser les erreurs d'extraction. Typiquement 'passage Choiseul' et 'passage Choiseal' sont considéré assez proche pour être semblable. Nous laissons aussi la possibilité pour une personne de changer de métier, ou (exclusif) de rue d'habitation.
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]])


=== Cas d'homonymie (lors de l'ajout de la page)===
Lors de cas d'homonymie, nous suivons la stratégie suivante: Si la page existe déjà, nous tentons d'ajouter de plus en plus d'informations (dans l'ordre suivant : nom, métier, rue) jusqu'à que la page devienne unique. Si malgré cela nous n'arrivons pas à ajouter la page, nous abandonnons cette entrée.


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:
<nowiki>* [[year]] / [[Paris]], [[street_clean]] number. Mention de [[name]] avec la catégorie [[job]] [url]</nowiki>


Il est à souligner que nous tentons jamais de corriger les erreurs d'extraction.
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 ==
== Évaluation des performances ==
Ligne 42 : Ligne 47 :
*Plus de 200000 pages ont été créées.
*Plus de 200000 pages ont été créées.


== Critiques ==
== 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.
Une des critiques majeures pouvant être faite à notre travail est que nous corrigeons aucune des données issues de l'extraction du bottin.
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.


== Exemple ==
== 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:
Données initiales:


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


Saisie sur Wikipast finale:
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]]


[[Fichier:BottinBot3_Aaron_Wikipast.png|500px]]
== Code ==
Le code est disponible sur GitHub à cette [https://github.com/JanMaxime/bottinBot adresse]

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