Boîte à Outils n°2

Dans cette deuxième BAO, il s'agit d'utiliser des outils d'annotation afin d'étiqueter les titres et descriptions récupérés précédemment. Les deux logiciels à notre disposition sont Cordial et TreeTagger.

Etiquetage via Cordial

Cordial est un logiciel de correction et d'analyse de données textuelles. Il prend en entrée des fichiers texte encodés en ISO-8859-1. La fonction permettant l'étiquetage de texte se situe dans l'onglet Syntaxe > Etiquetage de texte.

Une fenêtre permettant de choisir les paramètres d'étiquetage s'affiche : il faut alors désélectionner les nombreuses options cochées par défaut jusqu'à obtenir le résultat suivant :

Paramètres d'étiquetage Cordial

La tâche d'étiquetage se faisant manuellement, il faut donc répéter l'opération pour chaque fichier...ce que nous n'avons pas à faire avec TreeTagger !

Exemple de sortie

Les étiquetages de Cordial se composent en 3 colonnes : la première contient la liste des tokens, la seconde leur lemme et la dernière leur étiquette morphosyntaxique, incluant la catégorie grammaticale, le genre, le nombre ainsi que la personne pour les verbes.

Etiquetage via TreeTagger

L'avantage de TreeTagger par rapport à Cordial est qu'il peut s'utiliser en ligne de commande, et donc être intégré au programme de la BAO1. Voyons tout d'abord le fonctionnement du logiciel avant de savoir comment l'intégrer au programme :

Installation

Après le téléchargement de TreeTagger (sur le site du cours ou bien le site officiel), il faut placer les fichiers aux bons endroits :

  • Le répertoire bin : contient le programme tree-tagger.exe.
  • Le répertoire cmd : contient le fichier tokenise-fr.pl, servant à segmenter les textes (on pourra aussi y placer le programme treetagger2xml.pl fourni sur le site du cours).
  • Le répertoire lib : contient les librairies pour les langues (fichiers .par).

Le logiciel ne pourra être utilisable partout dans l'arborescence qu'en modifiant la variable d'environnement Path ou bien en créant un alias. Sinon, on peut toujours l'utiliser en répétant à chaque fois le chemin absolu.

Utilisation

Deux étapes sont nécessaires pour étiqueter les textes :

1. Segmenter en utilisant le programme tokenise-fr.pl :

perl tokenise-fr.pl fichier.txt > fichier_segmente.txt

2. Etiqueter le fichier segmenté, dans l'ordre : tree-tagger [fichier lib] [options] [fichier segmenté] :

tree-tagger french-utf8.par -lemma -token -no-unknown -sgml fichier_segmente.txt > fichier_etiquete.txt

L'option -lemma sert à indiquer les lemmes, -token à afficher les tokens, -no-unknown à ne pas indiquer si le token est inconnu, et -sgml à ne pas traiter les balises.

Voici un exemple d'étiquetage, en reprenant le même échantillon que celui utilisé pour Cordial (rubrique PLANETE) :

On remarque une première différence par rapport à l'étiquetage de Cordial dans l'ordre des colonnes, celle des étiquettes étant en deuxième position et les lemmes en dernier. Les étiquettes sont aussi différentes, et contrairement à Cordial, on note que le genre et le nombre ne sont pas précisés pour les noms.

Intégration au programme

(Télécharger les programmes bao2_regex.pl et bao2_RSS.pl)

La méthode est la même pour les deux programmes : on crée tout d'abord un répertoire Sortie/BAO2 (en suivant la même méthode que pour la BAO1) qui contiendra les nouveaux fichiers de sortie (OUTTAG):

foreach my $rub (@liste_rubriques) { my $output1 = $sortie.$rub.".xml"; my $output2 = $sortie.$rub.".txt"; my $output3 = $resBAO2.$rub."_tagged.xml"; if (!open (OUTXML,">:encoding(utf-8)", $output1)) { die "Can't open file $output1"}; if (!open (OUTTXT,">:encoding(iso-8859-1)", $output2)) { die "Can't open file $output2"}; if (!open (OUTTAG,">:encoding(utf-8)", $output3)) { die "Can't open file $output3"}; print OUTXML "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print OUTXML "<EXTRACTION>\n"; print OUTTAG "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"; print OUTTAG "<EXTRACTION>\n"; close(OUTXML); close(OUTTXT); close(OUTTAG); }

De même, on crée une variable $XMLtagged qui contiendra les titres et descriptions étiquetés, de la même façon que pour les fichiers XML de la BAO1 :

if ($encodage ne "" ) { my $texteXML="<file>\n"; $texteXML.="<name>$file</name>\n"; $texteXML.="<items>\n"; my $XMLtagged="<file>\n"; $XMLtagged.="<name>$file</name>\n"; $XMLtagged.="<items>\n"; ...

La phase d'étiquetage se fait après avoir vérifié qu'il n'y a pas de doublons, en appelant une fonction etiquetage :

if (!(exists $dicoTITRES{$titre}) and (!(exists $dicoDESC{$desc}))){ $dicoTITRES{$titre}++; $dicoDESC{$desc}++; my $titre_tag = &etiquetage($titre); my $desc_tag = &etiquetage($desc); $texteXML.="<item>\n<title>$titre</title>\n<description>$desc</description>\n</item>\n"; $XMLtagged.="<item>\n<title>$titre_tag</title>\n<description>$desc_tag</description>\n </item>\n"; print OUTTXT "$titre\n"; print OUTTXT "$desc\n"; }

Cette fonction se définit comme suit :

sub etiquetage { my $texte=shift; # fichier temporaire pour stocker le texte my $temp="fichier_temp.txt"; open(TEMP, ">:encoding(utf-8)", $temp); print TEMP $texte; close(TEMP); system("perl /cygwin/home/TreeTagger/cmd/tokenise-fr.pl $temp | /cygwin/home/ TreeTagger/bin/tree-tagger /cygwin/home/TreeTagger/lib/french-utf8.par -lemma -token -no-unknown -sgml > etiquetage.txt"); # treetagger2xml system("perl /cygwin/home/TreeTagger/cmd/treetagger2xml.pl etiquetage.txt"); open(TaggedOUT,"<:encoding(utf-8)","etiquetage.txt.xml"); my $texte_tag=""; while (my $ligne=){ $texte_tag.=$ligne; } close(TaggedOut); return $texte_tag;

La commande system() permet d'intégrer des commandes bash dans un programme Perl. La première commande combine la phase de segmentation et d'étiquetage en utilisant le pipe '|', et produit un fichier "etiquetage.txt". Celui-ci est ensuite utilisé pour convertir l'étiquetage TreeTagger en XML avec le programme treetagger2xml.pl.

J'ai effectué une légère modification sur ce programme en supprimant les fonctions "entete" et "fin", pour éviter les répétitions à chaque exécution du programme.

Résultat avec treetagger2xml

Comparaison des annotations

De manière générale, Cordial donne des informations plus précises dans ses étiquettes par rapport à TreeTagger. De plus, ce dernier semble faire plus d'erreurs concernant les mots commençant par une majuscule en début de phrase, en les étiquetant généralement comme noms propres.

Résultats

Après un peu plus de 8 heures de traitement, on obtient l'arborescence suivante :

Le dossier BAO1 contient pour chaque rubrique sa version texte brut et xml, tandis que BAO2 contient les fichiers xml produits par le programme treetagger2xml.pl
Ces fichiers possèdent la structure suivante :

<?xml version='1.0' encoding='utf-8'?> <EXTRACTION> <file> <name>[nom du fichier]</name> <items> <item> <title> <element> <data type="type">[classe grammaticale]</data> <data type="lemma">[lemme]</data> <data type="string">[token]</data> </element> [...] # plusieurs suites d'éléments </title> <description> <element> <data type="type">[classe grammaticale]</data> <data type="lemma">[lemme]</data> <data type="string">[token]</data> </element> [...] # plusieurs suites d'éléments </description> </item> [...] # plusieurs suites d'item </items> </file> [...] # plusieurs suites de fichiers </EXTRACTION>

Exemple de résultat : LIVRES_tagged.xml

Une fois nos fichiers étiquetés, nous pouvons passer à l'étape suivante : la recherche de motifs syntaxiques !