jeudi 17 octobre 2024
À quoi ça sert, au juste, tout cet effort
d’analyse des fichiers PDF? D’abord, bien
sûr, ça facilite la recherche, telle qu’implémentée dans
SÈRAFIM (un SystÈme de
Recherche Ad-hoc pour Fouiller dans les Informations
Municipales) puisqu’on est capable d’indexer chaque article et
chapitre individuellement - on peut ainsi comparer les dispositions
par rapport aux piétons dans l’aménagement des
stationnements
à travers quelques villes des Laurentides, par exemple.
Mais pas juste ça! Le fait d’avoir extrait les unités semantiques des
règlements nous permet d’ajouter plusieurs fonctionnalités pour en
faciliter la lecture et la compréhension, dont:
- L’ajout d’hyperliens. Par exemple, dans l’article
264
du règlement de zonage de Sainte-Adèle, on peut maintenant naviguer
vers le règlement de
construction
cité là-dedans ainsi que l’article
251
sur les aménagements piétonniers.
- La navigation structurée en-ligne. Au lieu d’avoir besoin de
télécharger le PDF pour trouver un chapitre ou section spécifique,
on peut voir tous les règlements dans une
arborescence et
expansionner pour obtenir rapidement le contenu recherché. Des
hyperliens vers la page spécifique du PDF sont aussi fournis.
- Mais surtout, ça nous permet d’utiliser… 🎉des grands modèles de
langage🎆
(oui, ces célèbres patentes qu’on appelle à tort de l’intelligence
artificielle) pour en faire des analyses automatiques, des résumés,
et d’autres manipulations.
L’analyse spécifique qu’on en fera ici est une analyse du plus proche
voisin
qui nous permettra de faire de façon plus efficace une analyse du type
mentionné ci-haut, c’est à dire, répondre à des questions du genre
«comment se comparent les dispositions par rapport à l’aménagement des
-stationnements entre Sainte-Adèle, Saint-Sauveur et Prévost». (si cela
vous semble une question hautement inutile, vous n’êtes sûrement pas
le public cible de ce blogue)
Pour ce faire, nous utiliserons la célèbre (ou pas) logithèque
SentenceTransformers pour calculer des
réprésentations vectorielles (embeddings) correspondant à chaque
unité sémantique dans l’ensemble des règlements. Par la suite, on
peut utiliser une multiplication matricielle très rapide pour obtenir
les proches
voisins
de chaque élément (c’est à dire les articles semblables dans d’autres
règlements ou d’autres villes). C’est vraiment très simple et
efficace! Par contre, pour des très grands corpus de documents, il
sera nécessaire d’utiliser un outil de référencement optimisé tel que
FAISS ou
RAGatouille.
Préalablement on aura téléchargé un ensemble de règlements avec
ALEXI. Pour faciliter la chose
on se limitera à trois règlements de zonage:
Les ayant téléchargés, on va les analyser avec ALEXI:
alexi extract *.pdf
Cela va prendre quelques minutes pour créer le répertoire export
avec plein de fichiers HTML et JSON (si vous voulez avoir plus
d’information sur ce qui se passe vous pouvez utiliser alexi -v extract *.pdf
). Par exemple, on voit que tous les articles du
règlement de zonage de Sainte-Adèle se trouvent maintenant sous
export/Rgl-1314-2021-Z-en-vigueur-20240823/Article
, chacun dans un
répertoire avec un seul fichier index.html
.
Le texte des unités sémantiques est maintenant converti d’une forme
graphique (des PDF) vers une forme moyennement sémantique (du HTML).
Ce qui nous intéresse, par contre, c’est le texte brut. On peut alors
utiliser BeautifulSoup ou
lxml pour l’extraire de nouveau et le
passer dans le modèle SentenceTransformers:
from bs4 import BeautifulSoup
def get_text(path) -> str:
with open(path) as infh:
soup = BeautifulSoup(infh)
return soup.article.text
articles = {path : get_text(path) for path
in Path("export").glob("**/Article/*/*.html")}
Réprésentation vectorielle et proches voisins
Pour générer les réprésentations vectorielles (embeddings) il nous
faut un modèle pré-entraîné. Il en existe plusieurs sur le site
HuggingFace qui sont spécialisés pour le français, qu’on retrouve
(avec plusieurs informations utiles sur leur performance) dans
l’espace
DécouvrIR.
Pour notre démonstration on utilisera la variété le plus simple et
rapide, un «Single-vector dense bi-encoder» de moins de 100M
paramètres. En cochant les cases on trouve que le meilleur à date est
biencoder-distilcamembert-mmarcoFR… on
y va!
import sentence_transformers as st
model = st.SentenceTransformer("antoinelouis/biencoder-distilcamembert-mmarcoFR")
Il nous reste qu’à transformer (lolle) les textes extraits en vecteurs
ou plus précisément en une matrice. Pour ce faire on va les énumérer
et retenir les indices pour faire la correspondance entre documents et
rangées de cette matrice:
artidx = {path: idx for idx, path in enumerate(articles)}
idxart = list(articles)
Par la suite on calcule les vecteurs:
embeddings = model.encode(list(articles.values()), convert_to_tensor=True,
show_progress_bar=True)
Sur une carte graphique GT1030, qu’on peut acheter usagée autour de 75
$, cela prend environ 30 secondes. Enfin, on utilise la fonction
semantic_search
pour trouver les plus proches voisins de chaque
rangée de la matrice (c’est instantané):
neighbours = st.util.semantic_search(embeddings, embeddings, top_k=20)
Pour voir ce que cela donne pour l’article
264
mentionné ci-haut, on va trouver le vecteur correspondant à cet
article, puis ensuite afficher les plus proches articles qui ne
viennent pas du même règlement:
import textwrap
# la rangée qui correspond à l'article 264 du règlement 1314-2021-Z
srcpath = Path("export/Rgl-1314-2021-Z-en-vigueur-20240823/Article/264/index.html")
idx = artidx[srcpath]
for n in neighbours[idx][1:]:
neighbour_idx = n["corpus_id"]
dstpath = idxart[neighbour_idx]
if dstpath.parts[1] == srcpath.parts[1]:
continue
print(idxart[neighbour_idx])
print(textwrap.fill(articles[idxart[neighbour_idx]].strip()[0:250]), "...")
print()
On voit que le modèle a bel et bien trouvé des articles pertinents:
export/RUD_T6_VR/Article/6.4.6.3/index.html
Article 6.4.6.3 Aménagement d’une aire de stationnement extérieure de
15 cases ou plus En plus des dispositions de l’article précédent, les
dispositions suivantes s’appliquent à toute aire de stationnement de
15 cases ou plus. L’aménagement d’une ai ...
export/RUD_T6_VR/Article/6.4.6.4/index.html
Article 6.4.6.4 Aménagement d’une aire de stationnement extérieure de
100 cases ou plus En plus des dispositions des articles précédents,
une aire de stationnement pour véhicule de 100 cases et plus doit
respecter les dispositions suivantes : 1° une ...
export/RUD_T6_VR/Article/6.4.9.1/index.html
Article 6.4.9.1 Nombre de cases de stationnement pour véhicule
automobile Tous les usages principaux doivent disposer d’un
stationnement hors rue d’une capacité minimale et maximale conforme
aux dispositions du présent article. Cette exigence est co ...
export/RUD_T6_VR/Article/6.4.5.1/index.html
Article 6.4.5.1 Aménagement d’une aire de stationnement extérieure de
moins de 3 cases ou allée de stationnement Une aire de stationnement
extérieure de moins de 3 cases ou une allée de stationnement doit
respecter les dispositions suivantes : 1° el ...
export/Reglement-2009-U53-fevrier-2024/Article/12.1.7/index.html
Article 12.1.7 Accès aux aires de stationnement (modifié, règlement
numéro 2011-U53-18, entré en vigueur le 2011-07-21) (modifié,
règlement numéro 2011-U53-21, entré en vigueur le 2011-12-15) Toute
case de stationnement doit être implantée de telle ...
Ce qu’on voit aussi est que la plupart des articles les plus
similaires viennent du règlement de Prévost. Ceci nous indique que le
règlement de zonage de Prévost (2024) serait plus similaire à
celui de Sainte-Adèle que celui de Sainte-Agathe (2009).
Recherche semantique
Bien sûr, rien nous empêche de comparer autre chose que des articles
des règlements. On peut également convertir des questions ou d’autres
documents en vecteurs. Si par exemple on voulait savoir quelles
articles ressemblent aux normes proposées par le CRE Montréal pour le
stationnement écoresponsable en matière de
verdissement… on
peut le faire! Il faut simplement télécharger et extraire le texte de
cette page:
import requests
r = requests.get("https://reglementaction.com/verdissement-du-stationnement/")
soup = BeautifulSoup(r.content)
Puis le transformer avec le modèle et faire semantic_search
sur les
règlements:
tvec = model.encode(soup.text)
for n in st.util.semantic_search(tvec, embeddings)[0][0:4]:
neighbour_idx = n["corpus_id"]
score = n["score"]
print(score, idxart[neighbour_idx])
print(textwrap.fill(articles[idxart[neighbour_idx]].strip()[0:500]), "...")
print()
Et on trouve des dispositions potentiellement intéressantes dans les règlements:
0.413027286529541 export/Rgl-1314-2021-Z-en-vigueur-20240823/Article/188/index.html
Article 188 Compensation de la surface végétalisée minimale par des
espaces de stationnements perméables La surface d’une portion d’un
espace de stationnement situé à l’intérieur du périmètre urbain conçu
à l’aide de pavés alvéolés ou de gazon renforcé avec dalle alvéolée
peut être comptabilisée dans le calcul de la surface végétale minimale
par un ratio de 50% (exemple : 100 m2 de stationnement en dalle
alvéolé peut donc représenter un crédit de 50 m2 de surface
végétalisée). La surface ainsi ...
0.38985273241996765 export/Rgl-1314-2021-Z-en-vigueur-20240823/Article/267/index.html
Article 267 Ilot de verdure Un espace de stationnement hors rue
extérieur comportant 20 cases ou plus doit être aménagé de façon à ce
que toute série de 20 cases de stationnement adjacentes soit isolée
par un îlot de verdure conforme aux dispositions suivantes : Un îlot
de verdure doit respecter les dimensions suivantes : une largeur
minimale de 2 mètres; une superficie minimale de 25 mètres carrés pour
les cases aménagées en rang double, soit dos-à-dos; une superficie
minimale de 13 mètres car ...
0.3851878046989441 export/RUD_T6_VR/Article/6.1.2.6/index.html
Article 6.1.2.6 Agrandissement majeur d’un bâtiment Un agrandissement
majeur représentant 25 % ou plus de la superficie de plancher du
bâtiment principal, mais moins de 100 % de cette superficie peut être
réalisé malgré l’existence d’un aménagement d’une aire de
stationnement dérogatoire pourvu que les conditions suivantes soient
respectées : 1° dans le cas d’une aire de stationnement extérieure de
15 cases et plus, l’aire de stationnement doit être réaménagée de
manière à respecter les exigenc ...
0.3690324127674103 export/RUD_T6_VR/Article/6.4.4.1/index.html
Article 6.4.4.1 Revêtement d’une aire de stationnement Une aire de
stationnement extérieure doit être recouverte par l’un des matériaux
de revêtement suivants qui peuvent être perméables ou non, le cas
échéant : 1° l’asphalte; 2° le béton; 3° le pavé d e béton; 4° le pavé
de béton avec alvéoles végétalisées ou remplies de poussières de roche
ou de pierres concassées. Une aire de stationnement située dans une
zone de type T1, T2 ou ZP.1 et ZP.3 peut être recouverte de gravier. ...
On peut également extraire les règlements modèles de la page et
chercher les articles similaires (ce qui marche mieux lorsqu’on a une
plus grande collection de règlements).
Conclusion
J’ai fait un survol très rapide de ce qu’on est capable de faire avec
une extraction sémantique et structurée du texte d’un PDF de
règlement, et comment c’est facile de faire des analyses en utilisant
SentenceTransformers.
Dans des futurs billets on regardera l’agglomération des articles, la
possibilité d’entraîner un modèle spécifique pour ce domaine, ainsi
que la possibilité de faire une comparaison quantitative entre
règlements pour des critères spécifiques par rapport à
l’environnement.
mardi 15 octobre 2024
Ce billet présente une module d’extraction
d’information pour les règlements
municipaux en format PDF, qui sert à alimenter un moteur de récherche.
Il est la troisième partie d’une série de billets qui détaillent la
conception et implémentation de celle-là.
Oui, ça fait longtemps depuis le dernier billet! Il y en aura un
autre plus étoffé mais pour le moment je voulais juste ajouter
quelques notes.
Bien que le format PDF soit utilisé très largement pour stocker,
archiver, et distribuer des documents textuels, il est très important
de comprendre qu’il est d’abord un format de présentation. Il n’y a
aucune garantie que les objets
textuels
trouvées dans un PDF correspondent à des mots, phrases, ou alinéas
d’une langue naturelle - par exemple, chaque caractère peut bien être
représenté individuellement, ou des mots peuvent être scindés entre
deux lignes, et ainsi de suite.
Par contre, il existe des fonctions dans le standard
PDF qui
permettent de superposer une structure logique par-dessus la
présentation. C’est d’ailleurs ce qui permet un lecteur PDF de
présenter une table des matières dans la barre latérale. Dans le cas
où cette structure existe, on n’a qu’à l’utiliser… euh, non.
Le problème est, très évidemment, que rien n’oblige l’auteur d’un PDF
ni son outil de réaction d’inclure cette structure logique, ni de la
spécifier de façon prévisible et consistante. Par exemple, si on
compare la structure (avec pdfplumber --structure-text
ou pdfinfo -struct-text
) des règlements
1314-2021-DM
et
1328,
on voit que les énumérations sont tantôt exprimées (correctement) avec
des éléments LI
, tantôt avec des éléments H5
:
H5 (block)
"5. Lorsque deux dispositions ou plus du présent règlement s’appliquent...
L (block):
/ListNumbering /LowerAlpha
LI (block)
LBody (block)
"a. La disposition particulière prévaut sur la disposition générale; "
ou avec des LI
seulement:
P (block)
"Les fins municipales pour lesquelles un immeuble peut être acquis par...
P (block)
" "
L (block):
/ListNumbering /Decimal
LI (block)
LBody (block)
"1. Habitation; "
Si on regarde le règlement de zonage, c’est dix fois pire, tout se
trouve dans des L
imbriqués à perte de vue!
Aussi, une fois qu’on a compris et correctement interpreté le très
compliqué
standard
pour indiquer la structure logique d’un PDF (ce que ne font que
partiellement les logiciels libres de PDF, à moins qu’on ait le goût
de s’inféoder à Adobe), il reste qu’on doit encore extraire et traiter
le contenu.
Finalement, rien n’assure que la structure sera présent à travers
multiples versions d’un document, puisque le fonctionnaire qui génère
le PDF doit se rappeler de cocher la case “Tagged PDF” ou “PDF/UA” en
le faisant et ne pas simplement “imprimer en format PDF”, et parce que
des outils de manipulation de fichiers PDF ont tendance à omettre la
structure lors des transformations.
Pour cette raison non seulement est-il impossible de se fier
complètement à la structure logique d’un PDF, mais il est aussi
dangereux même de l’utiliser pour alimenter un modèle
probabilistique. La démarche plus robuste est d’entraîner deux
modèles, l’un avec les traits structurels et l’autre sans, et choisir
le plus approprié selon la présence de structure ou pas.
Annotation des données (la suite)
À date, je n’ai jamais réussi à trouver un logiciel libre potable pour
faire l’annotation de séquences ou étendues de texte, peut-être parce
que l’annotation est un marché très lucratif - sans annotation, il n’y
a aucune « intelligence » artificielle après tout!
Le plus promettant qui existe est
Doccano mais j’avais jugé qu’il
prendrait trop de travail pour l’adapter au cas d’usage particulier
pour quelques raisons:
- Il est conçu pour annoter du texte
brut
ou des images
individuelles.
Soit on perdrait la mise en page, soit le travail deviendrait ardu à
force d’annoter des centaines de pages individuellement.
- Il faudrait convertir les données dans son format préféré puis
reconvertir les annotations à la sortie pour les aligner sur les
données extraites du PDF.
- Son
architecture
est quand même assez complexe alors qu’on a vraiment juste besoin de
mettre des catégories sur des lignes dans un fichier CSV…
Heureusement il existe un outil bien adapter pour l’annotation de CSV,
qui s’appelle tantôt LibreOffice
Calc, tantôt Microsoft
Excel, blanc bonnet, bonnet blanc… ça marche vraiment très bien
puisqu’il se rappelle des valeurs qu’on rentre dans une colonne, alors
une fois les tags (étiquettes) rentrés on n’a que taper quelques
lettres, puis on peut étendre une tag pour couvrir un segment entier
de texte en glissant la souris, par exemple:
Ce qu’il est important de comprendre, par contre, c’est que en tant
qu’application de fiche de calcul, Calc (et Excel aussi) ont tendance
a “interpreter” les données dans un CSV de façon inattendue. Alors,
il faut absolument, lors de l’ouverture d’un fichier CSV, s’assurer
dans le dialogue de conversion, que:
- Le jeu de caractères est réglé sur “UTF-8”
- Le type de colonne pour la colonne “text” est réglé à “Texte”
Pour ce faire, il faut dans le dialogue de conversion sélectionner la
colonne en cliquant sur son titre:
Puis sélectionner “Texte” dans le menu d’options:
Annotation et Correction avec ALEXI
Avec ALEXI on peut générer un CSV
de cette sorte pour une ou toutes les pages d’un PDF. Si par exemple,
on voudrait adapter le modèle d’extraction au nouveau règlement
d’urbanisme
durable
de la ville de Prévost, la procédure est:
- Télécharger le PDF (bien sûr) - par exemple (mon préféré) le titre
6: Mobilité durable et stationnement
écologique.
- Extraire un CSV préliminaire avec
alexi annotate RUD_T6_VR.pdf T6
. Ceci créera les fichiers T6.pdf
et T6.csv
- le premier
est une version du PDF original marqué avec des rectangles colorés
pour les éléments (alinéas, titres, items) identifiés dans le
texte, alors que le deuxième est la réprésentation CSV.
- Ouvrir le CSV dans un logiciel de fichier de calcul et corriger les
annotations en suivant la démarche ci-haut.
Pour revoir l’effet de changer le CSV sur les annotations, il suffit
de rouler de nouveau la commande alexi annotate
mais avec le CSV
corrigé: alexi annotate --csv T6.csv RUD_T6_VR T6
. On peut
également extraire le document avec les nouvelles annotations en
utilisant alexi export -o T6-html T6.pdf
puis voir le HTML extrait
en partant de T6-html/index.html
.
Dans un prochain billet, nous allons regarder le processus
d’identification des éléments du texte ainsi que l’entraînement de
modèles en intégrant les annotations corrigées.
mercredi 6 septembre 2023
Ce billet présente une module d’extraction
d’information pour les règlements
municipaux en format PDF, qui sert à alimenter un moteur de récherche.
Il est la deuxième partie d’une série de billets qui détailleront la
conception et implémentation de celle-là.
Analyse d’un règlement
Comme déjà mentionné, on se concentrera d’abord sur l’analyse d’une
sorte précise de document, les règlements
d’urbanisme
de la ville de Sainte-Adèle. Ces documents ont en théorie une
structure bien définie et énoncée explicitement dans leur premier
chapitre:
Dans l’abstrait on peut alors considérer cela comme une instance
d’analyse
syntaxique. En
partant d’un grammaire (essentiellement la rubrique ci-haut) il faut
simplement trouver l’arborescence correspondant aux titres et
textes dans un document spécifique. Comme on verra, il y a plusieurs
détails qui rendent cela un peu plus compliqué mais c’est grosso modo
la démarche à suivre.
On n’utilisera pas pour autant une logithèque existante d’analyse
(parsing) puisque celles-ci sont habituellement conçues pour
fonctionner au niveau des mots et sont limitées à des textes assez
courts. À sa place, on passera par une phase d’analyse textuelle pour
identifier les étendues de textes (titres, alinéas, etc) pertinentes,
puis on construira par la suite l’arborescence avec quelque chose qui
ressemble à l’analyse
ascendante.
Au merveilleux pays des PDF
Comment alors identifier ces fameuses étendues de textes? C’est ici
que ça se complique! Comme vous savez peut-être, le PDF est un format
de présentation, c’est à dire que c’est la forme visuelle d’un
document qui y est représentée et pas la forme textuelle. Un PDF
(numérisé par exemple) peut même ne contenir aucun texte. Souvent, un
PDF contient à la fois l’image numérisé du document et un texte
“invisible” provenant d’une reconnaissance optique des caractères -
c’est ce texte qu’on voit lorsqu’on fait un copier-coller d’un
paragraphe. On peut le voir dans ce
règlement
par exemple.
On ne fera pas de OCR ici, on présume à la base qu’il existe une forme
textuelle accessible dans les fichiers PDF. Ce n’est pourtant pas
tout à fait simple d’extraire ce
texte.
Il en existe plusieurs logiciels
libres plus ou moins
performants, mais mon choix s’est arrêté sur
pdfplumber, ce qui peut
sembler illogique puisqu’il n’est pas le plus performant. Si vous
voulez tout simplement extraire le texte en soi avec la plus de
fidelité il est conseillé d’utiliser plutôt
pypdf ou
pypdfium2 qui
fournissent des fonctions rapides et simples à utiliser. L’avantage
de pdfplumber
est que, en plus d’extraire le texte, celui-ci est
relié à sa mise en page, qu’on utilisera pour mieux identifier les
titres et faire le lien entre le texte et les images.
L’autre avantage est que le code source de pdfplumber
est facilement
compréhensible, ce qui nous permet d’y ajouter de la fonctionalité.
Par exemple, ce n’est pas tout à fait vrai qu’il n’y a pas de
structure logique dans un PDF - en fait, il peut y en avoir, mais
encore, les autres logithèques ne permettent pas de facilement le
mettre en relation avec le texte. J’ai fini par contribuer des
fonctionalités qui le
permettent, et qui se trouvent pour l’instant dans une version
modifiée.
Chaîne de traitement
Comme est l’habitude des projets en traitement automatique de texte,
le processus est décomposé dans une chaîne d’étapes successives (ou
pipeline) qui rajoutent de l’analyse au texte brut. Ceci nous
permet de tester et optimiser chaque sous-analyse séparément. Cette
chaîne comprend, notamment:
- La conversion de PDF en séquence de mots, figures, et tableaux
avec leur mise en page.
- La segmentation du flux de mots en blocs de texte (des titres, des
alinéas, des listes et des tableaux).
- L’identification automatique des types de blocs.
- L’extraction de faits saillants du texte de chaque bloc (les
numéros d’articles, sections et chapitres et les dates d’adoption de
règlements)
- L’analyse syntaxique qui donne une structure textuelle.
On va se concentrer sur les trois premières fonctions pour le moment.
Annotation des données
Parce que les documents sont d’une taille assez importante et
l’analyse en est de nature inexacte, il nous prend d’abord un
sous-ensemble sur lequel on pourra en vérifier la précision en
développant l’algorithme, puis un échantillon indépendant pour tester
celui-ci afin de vérifier sa capacité de traiter des nouveaux
documents. On est bien sûr dans une méthodologie typique de
l’apprentissage automatique, mais même si on en utilise pas, on aura
besoin d’un ensemble de données annotées.
Ceci nécessite qu’on définisse notre schéma d’annotation et les traits
(features) d’entrée pour la chaîne de traitement. Ce qui nous
fournisse pdfplumber
est une liste de tous les caractères pour
chaque page d’un document, avec leur positions, tailles, noms de
police, et couleurs. Il est également possible d’extraire les mots
d’un page (ou ce qui pourrait ressembler à des mots) avec la fonction
extract_words
.
Pour le moment, on va utiliser extract_words
au lieu de faire une
tokenisation nous-même en partant des caractères, mais celle-ci est
aussi une option à regarder afin de profiter de modèles du type
Transformer tel que CamemBERT, qui
agissent sur des sous-séquences de caractères plutôt que des mots
complets.
Les traits tels que fournis par pdfplumber
sont trop détaillés dans
certains aspects, alors on en fera un post-traitement avant de les
écrire dans des fichiers CSV. Ceci nous permettra d’en faire
l’annotation tout simplement avec un logiciel de feuille de calcul,
puisqu’il ne semble pas exister une meilleur solution à la fois libre
d’accès et gratuit pour cette tâche. Puisque Excel et LibreOffice ont
une fonction saisie automatique basée sur les autres valeurs d’une
colonne, il est assez facile de rentre les annotations, puis de les
« étirer » pour couvrir les mots adjacents.
Pour le schéma d’annotation, comme mentionné ci-haut, on se limite à
des blocs de texte. Par contre, puisque l’identification sera faite
sur ces mêmes blocs de texte, on peut aussi marquer le type de chaque
bloc. Nous allons faire l’annotation dans le format IOB
,
c’est-à-dire, le premier mot de chaque bloc est marqué avec B-
suivi
par le type de bloc, les mots subséquents avec I-
suivi par le type
de bloc, et les mots à exclure complètement (il n’y en a pas beaucoup)
avec O
. Voir par exemple, un exemple de fichier CSV
complété ici.
Les types de blocs annotés sont:
TOC
: Les tableaux de matières sont marqués au complet avec cette
annotation. Pour le moment, on va les ignorer et simplement
extraire la structure du texte lui-même.
Titre
: Les titres qui ne correspondent pas à un élément structurel
spécifique sont marqués ainsi.
Chapitre
, Section
, SousSection
, Article
: pour les titres
d’éléments spécifiques. Si nécessaire il est possible de les
transformer en Titre
pour évaluer la segmentation toute seule.
Alinea
: Les alinéas sans mise en page particulière.
Liste
: Les éléments de listes (soit des énumérations ou des
définitions). Chaque élément est marqué avec son propre bloc (c’est
à dire avec B-Liste
au premier mot et I-Liste
pour les
subséquents)
Tete
, Pied
: Les en-têtes et pieds de pages. On ne les marque
pas avec O
tout simplement puisque, même s’ils ne font pas partie
du texte, ils peuvent contenir des informations utiles et faciles
d’identifier, comme le titre du document ou le chapitre.
Dès qu’un document (ou même une partie d’un document) est annoté, il
est possible d’entraîner un modèle là-dessus et l’utiliser pour
accélérer l’annotation des documents suivants. Le prochain billet
décrira un peu plus en détail le processus d’annotation en utilisant
les outils ALEXI.