Boîte A Outils 2
Cette deuxième étape utilise les sorties textuelles de la Boite A Outils 1. Maintenant que les fichiers RSS sont regroupés par rubrique et nettoyés, on passe à la phase d’étiquetage, qui en réalité comporte deux principes :
- la segmentation du contenu textuel en tokens
- l’étiquetage morphosyntaxique de chaque mot
La segmentation en tokens se fait sur la base de délimiteurs qui sont des caractères qui désignent la jonction entre deux 'mots' (par exemple l'espace, le saut de ligne, le point, la virgule...). Il y a un choix linguistique à faire par rapport à l'ensemble de caractères choisi – et ce n'est pas un choix facile ! Par exemple, segmenter systématiquement sur la base de l'apostrophe sépare bien l'article du nom dans "l'histoire" (ce qui peut être estimé comme un bon choix) mais sépare aussi les parties de "aujourd'hui" (ce qui est plus problématique). Le tiret pose également des problèmes. La solution ne sera pas parfaite (un découpage automatique de cette manière ne peut pas tenir compte de la sémantique) mais il faut essayer de faire globalement les meilleurs choix.
L'étiquetage morphosyntaxique nécessite d'avoir déjà segmenté le texte en tokens. C'est la projection d'informations relatives à la classification des mots : chaque forme est associée à un lemme et une catégorie syntaxique plus ou moins discriminante (Ex : nom ou nomMascSing).
Deux outils vont être utilisés pour la tâche d’étiquetage : Cordial et TreeTagger
Cordial
Certaines contraintes spécifiques au fonctionnement de Cordial rendent nécessaire une étape de prétraitement des fichiers :
- Le logiciel ne supporte pas les fichiers au-dessus d’une certaine taille et donc la répartition en rubriques sert aussi à assurer que les fichiers ne soient pas trop grands.
- Les fichiers à traiter sont uniquement les sorties TXT. Les balises dans les fichiers XML sont très utiles pour délimiter chaque morceau d'information. Hélas le fichier txt ne contient pas de tels délimiteurs et il ne faut pas oublier d'ajouter un point après chaque titre et chaque description (voir la BAO 1)
- Les fichiers doivent être en ISO-Latin. Il faut d’abord convertir les fichiers (qui ont été soigneusement encodés en UTF-8) en ISO-8859-1.
Transcodage
Sous linux, ceci se fait en quelques lignes dans un petit script bash :
#!/bin/bash
#---- Usage ---->
[[ -ne 2 ]] || [ ! ] || [ ! ] ;
-e "\nMerci d'indiquer deux arguments valides :"
-e "\nUsage: `basename $0` DossierEnEntree DossierEnSortie\n"
;
;
IN=${1%/};
OUT=${2%/};
#--- créer le dossier de sortie et supprimer le contenu --->
[ ! ];
;
/*;
;
#--- pour chaque fichier texte de la sortie de BAO1, convertir en ISO Latin -->
fichier `ls $IN`
{
| -q ".+\.txt";
;
( -f utf-8 -t iso-8859-1 "$IN/$fichier") > /
;
}
La même tâche peut être effectuée sous Windows (ou Linux) avec un script perl :
#/usr/bin/perl
use Encode;
die "Usage: $0 DossierEnEntree DossierEnSortie\n
Le programme prend en argument un dossier contenant des fichiers textes et un dossier sortie.
La conversion se fait de l'utf-8 vers de l'ISO-8859-1\n\n" if (@ARGV < 2) || (! -d $ARGV[0]) || (! -d $ARGV[1]);
#--- créer le dossier et supprimer le contenu existant --->
my $res=$ARGV[1];
$res=~ ;
if (! -e $res)
{
mkdir($res) or die ("Problème avec la création du répertoire de $rep");
}
else
{
print ("Supprimer les fichiers existants >>");
opendir(DIR, $res) or die "Erreur d'ouverture de repertoire: $!\n";
my @tobedeleted = readdir(DIR);
foreach my $scrubbed (@tobedeleted)
{
unlink $res.$scrubbed;
}
closedir(DIR);
print ("Done");
}
my $path="$ARGV[0]";
$path=~ ;
opendir(REP, $path) or die "Problème d'ouverture du répertoire : $!\n";
my @fichiers = readdir(REP);
closedir(REP);
#--- Pour chaque fichier txt conversion de l'utf-8 vers de l'ISO Latin --->
foreach my $fichier(@fichiers)
{
if ($fichier=~/\.txt$/) # uniquement les fichiers txt
{
if (!open(FILE,"$path/$fichier"))
{
die "Problème a la lecture du fichier $path/$fichier";
}
my $contenu="";
print "$fichier\n";
while (my $line=<FILE>)
{
$line=~;
$contenu.=$line;
}
close(FILE);
#--- décoder et ré-encoder --->
$contenu = decode("utf-8", $contenu);
$contenu=encode("iso-8859-1", $contenu);
#--- Ecrire dans le fichier de sortie en ISO-8859-1 --->
if (!open (FILE,">:encoding(iso-8859-1)","$res/$fichier"))
{
die "Problème a l'ouverture du fichier $res/$fichier.txt";
}
print FILE $contenu;
close(FILE);
}
}
L'utilisation de Cordial
Après avoir ouvert le logiciel, il suffit d'ouvrir le fichier texte à étiqueter et de sélectionner syntaxique > étiquetage. Les paramètres à appliquer sont les suivants :
Le Résultat
En selectionnant les paramètres ci-dessus, le fichier en sortie est un fichier .cnr contenant trois colonnes (séparées par des tabulations). La première colonne contient la forme du mot, la deuxième le lemme et la troisième la catégorie syntaxique.
Ligue Ligue NPFS
1 1 NCMIN
: : PCTFORTE
:
Lille Lille NPSIG
croit croire VINDP3S
de nouveau de nouveau ADV
au au DETDMS
titre titre NCMS
. . PCTFORTE
En en PREP
battant battre VPARPRES
Toulouse toulouse NCSIG
dimanche dimanche NCMS
à à PREP
domicile domicile NCMS
grâce à grâce à PREP
une un DETIFS
nouveau nouveau ADJMS
festival festival NCMS
d' de PREP
Eden Eden NPMS
Hazard Hazard NPI
...
Il y a quelques irrégularités dans le résultat, parmi lesquels :
- Une tokenisation suspecte - par exemple 'dans la course' traité comme un seul mot : 'dans la course dans la course ADV'
- Le mauvais choix de catégorie syntaxique à cause de la polysémie : 'coordonnés coordonné NCMP' pour la phrase 'Quelques centaines de manifestants coordonnées par le groupe belge...'
Tree Tagger
Utilisation de Tree Tagger
‘Treetagger’ est un logiciel qui sert à annoter du texte pour les catégories syntaxiques et les lemmes. Il est aussi disponible en ligne de commande – une fonctionnalité très intéressante qui permet d’intégrer l’étiquetage du corpus dans le programme du BAO1.
La syntaxe de treetagger en ligne de commande est la suivante :
treetagger.exe [options] <parameters> <texte_en_entree> <texte_en_sortie>
Il faut évidemment donner le bon chemin du programme TreeTagger (selon l’emplacement choisi par l’utilisateur). Les arguments (ce qu’il faut fournir à TreeTagger) :
- le chemin vers le fichier paramètre selon la langue (ici c’est french-utf8.par)
- le chemin vers le texte à étiqueter
- le chemin vers le fichier de sortie
Les options sont les informations à afficher :
- -lemma -> le lemme
- -token -> la forme du mot tel qu’il apparaît dans le texte
- -sgml -> les informations morphologiques associées à la forme
Une petite précision à faire est que le texte en entrée doit contenir un seul mot par ligne. La tokenisation de chaque fichier txt est simple avec l’aide d’un petit programme ‘tokenise-fr.pl’, qui prend le texte à découper en entrée et renvoie un texte avec un mot par ligne.
Un
document
révèle
l'étendue
des
fraudes
électorales
au
Kenya
.
Un
document
confidentiel
,
que
s'est
procuré
"
Le
Monde
"
,
trace
les
contours
du
désastre
entraîné
...
perl tokenise-utf8.pl Sorties\1_Sorties_PurePerl\ALAUNE.txt > Sorties\ALAUNE_tokenised.txt
Etant donné ce premier texte (ALAUNE.txt), voici la sortie produite par la commande suivante :
tree-tagger.exe french-utf8.par –lemma –token –sgml ALAUNE.txt ALAUNE_tokenised.txt
Le Résultat
Le fichier en sortie contient un mot par ligne. Chaque mot, comme avant, est décrit par trois colonnes, mais l'ordre des colonnes est différent : la forme, la catégorie syntaxique et le lemme.
Un DET:ART un
document NOM document
révèle VER:pres révéler
l'étendue VER:pper <unknown>
des PRP:det du
fraudes NOM fraude
électorales ADJ électoral
au PRP:det au
Kenya NAM <unknown>
. SENT .
Un DET:ART un
document NOM document
confidentiel ADJ confidentiel
, PUN ,
que KON que
s'est NOM <unknown>
procuré VER:pper procurer
" PUN:cit "
Le DET:ART le
Monde NAM Monde
" PUN:cit "
, PUN ,
trace VER:pres tracer
les DET:ART le
contours NOM contour
du PRP:det du
désastre NOM désastre
entraîné VER:pper entraîner
...
Il y a quelques irrégularités dans les résultats, notamment lorsqu'il s'agit de tirets ou d'apostrophes :
- 'd'un humain' où 'd'un' = nom et 'humain' = adj
- 'peut-il' traité comme un adjectif
- 'Est-ce' traité comme un nom
L'avantage est que Treetagger peut être intégré dans le script de la BAO 1 pour produire une sortie XML avec chaque mot étiqueté pour sa catégorie syntaxique et son lemme.
L'intégration de Treetagger se fait par une fonction &treetagger, qui convertit l'argument donné (un titre ou une description) et renvoie le résultat en XML. La fonction se compose de plusieurs étapes :
- La création d'un fichier temporaire dans lequel stocker le texte (puisque Treetagger prend en argument un fichier) :
open(temp, ">:encoding(UTF-8)", "./temp.txt");#fichier temporaire pour stocker le texte
print temp $texte;
close(temp);
- La tokenisation du fichier (pour mettre un mot par ligne) et son traitement subséquent par Treetagger :
system("perl tokenise-utf8.pl ./temp.txt | tree-tagger.exe french.par -lemma -token -no-unknown -sgml > treetagger.txt");
- La conversion du fichiers vers un fichier XML via le script "treetagger2xml-utf8.pl' fourni :
system("perl ./treetagger2xml-utf8.pl treetagger.txt utf-8 ")
- La lecture du fichier étiqueté et le renvoie de son contenu :
open(TaggedOUT,"<:encoding(utf-8)","treetagger.txt.xml");
my $xml_declaration=<TaggedOUT>;
my $tagged_text="";
while (my $l=<TaggedOUT>)
{
$tagged_text.=$l;
}
close(TaggedOut);
return $tagged_text;
L'écriture dans les fichiers de sortie est pareille que pour les sorties de la BAO 1 sauf que le dossier de sortie s'appelle '2_Sorties_Etiquetees', et au lieu de contenir les éléments titres et descriptions en format texte brut, les sorties contiennent les titres et descriptions étiquetés, comme suit :
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="BAO2html.xsl"?>
<PARCOURS>
<NOM>Bawden</NOM>
<CINEMA>
<file><name>2012/Apr/01/19-46-00/0,2-3476,1-0,0.xml</name><date>Sat, 31 Mar 2012 14:25:08 GMT</date>
<items>
<item>
<titre>
<document>
<article>
<element>
<data type="type">NAM</data>
<data type="lemma">Julie</data>
<data type="string">Julie</data>
</element>
<element>
<data type="type">NAM</data>
<data type="lemma">Delpy</data>
<data type="string">Delpy</data>
</element>
<element>
<data type="type">VER:pres</data>
<data type="lemma">récidiver</data>
<data type="string">récidive</data>
</element>
</article>
</document>
</titre>
<description>
<document>
<article>
<element>
<data type="type">DET:ART</data>
<data type="lemma">le</data>
<data type="string">Les</data>
Transformation vers du HTML
A l'aide d'une feuille de styles (ci-dessous), ces fichiers XML étiquetés peuvent être transformés vers du HTML :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" version="4.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/PARCOURS">
<xsl:variable name="rubrique" select="local-name(./*[preceding-sibling::NOM])"/>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="BAO2html.css"/>
<title><xsl:value-of select="$rubrique"/></title>
</head>
<body>
<div id="contenu">
<h1><xsl:value-of select="$rubrique"/></h1>
<table>
<xsl:apply-templates select="*/file"/>
</table>
</div>
</body>
</html>
</xsl:template>
<xsl:template match="file">
<xsl:if test="./items/item">
<xsl:if test="position() < 10">
<xsl:variable name="fullname" select="./name"/>
<xsl:variable name="name" select="substring-before($fullname, '.')"/>
<xsl:variable name="lengthname" select="string-length(./name)"/>
<xsl:variable name="filename" select="substring($name, $lengthname - 17, $lengthname)"/>
<tr>
<th colspan="2" class="fileheader"><xsl:value-of select="$filename"/><xsl:text> (</xsl:text><xsl:value-of select="date"/><xsl:text>)</xsl:text></th>
</tr>
<tr><th>Titre</th><th>Description</th></tr>
<xsl:apply-templates select="items/item"/>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:template match="item">
<xsl:if test="position() < 10">
<tr>
<td><xsl:apply-templates select="titre"/></td>
<td><xsl:apply-templates select="description"/></td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="titre|description">
<xsl:apply-templates select="document/article/element"/>
</xsl:template>
<xsl:template match="element">
<span class="forme"><xsl:value-of select="data[contains(@type, 'string')]"/></span>
<span class="small"><xsl:text>[</xsl:text>
<span class="type"><xsl:value-of select="data[contains(@type, 'type')]"/></span><xsl:text>/</xsl:text>
<span class="lemma"><xsl:value-of select="data[contains(@type, 'lemma')]"/></span>
<xsl:text>]</xsl:text></span><xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
CULTURE
Titre | Description |
La[DET:ART/le] poésie[NOM/poésie] d'Antonin[ADJ/d'Antonin] Artaud[NAM/Artaud] suintait[VER:impf/suinter] de[PRP/de] son[DET:POS/son] crayon[NOM/crayon] | Cinq[NUM/cinq] portraits[NOM/portrait] et[KON/et] autoportraits[NOM/autoportrait] mis[VER:pper/mettre] en[PRP/en] vente[NOM/vente] chez[PRP/chez] Sotheby's[NAM/Sotheby's] |
Loin[ADV/loin] d'Hollywood[NOM/d'Hollywood] ,[PUN/,] Cate[NAM/Cate] Blanchett[NAM/Blanchett] laisse[VER:pres/laisser] sans[PRP/sans] voix[NOM/voix] | La[DET:ART/le] comédienne[NOM/comédien] australienne[ADJ/australien] subjugue[VER:pres/subjuguer] en[PRO:PER/en] désaxée[VER:pper/désaxer] dans[PRP/dans] "[PUN:cit/"] Big[NAM/Big] and[VER:simp/and] Small[NAM/Small] "[PUN:cit/"] ,[PUN/,] de[PRP/de] Botho[NAM/Botho] Strauss[NAM/Strauss] ,[PUN/,] au[PRP:det/au] Théâtre[NAM/Théâtre] de[PRP/de] la[DET:ART/le] Ville[NAM/Ville] |
La[DET:ART/le] vente[NOM/vente] aux[PRP:det/au] enchères[NOM/enchère] d'instruments[NOM/d'instruments] de[PRP/de] torture[NOM/torture] est[VER:pres/être] suspendue[VER:pper/suspendre] | Le[DET:ART/le] ministre[NOM/ministre] de[PRP/de] la[DET:ART/le] culture[NOM/culture] ,[PUN/,] Frédéric[NAM/Frédéric] Mitterrand[NAM/Mitterrand] ,[PUN/,] avait[VER:impf/avoir] annoncé[VER:pper/annoncer] qu'il[NOM/qu'il] souhaitait[VER:impf/souhaiter] "[PUN:cit/"] très[ADV/très] fermement[ADV/fermement] "[PUN:cit/"] l'annulation[NOM/l'annulation] de[PRP/de] cette[PRO:DEM/ce] vente[NOM/vente] qui[PRO:REL/qui] regroupe[VER:pres/regrouper] 350[NUM/@card@] objets[NOM/objet] et[KON/et] documents[NOM/document] sur[PRP/sur] la[DET:ART/le] torture[NOM/torture] |
... | ... |
[ Cliquez sur le tableau pour le visualiser ]
ECONOMIE
Titre | Description |
Zone[NOM/zone] euro[NAM/euro] :[PUN/:] la[DET:ART/le] sortie[NOM/sortie] reste[VER:pres/rester] encore[ADV/encore] loin[ADV/loin]
|
Peu[ADV/peu] à[PRP/à] peu[ADV/peu] ,[PUN/,] les[DET:ART/le] pièces[NOM/pièce] du[PRP:det/du] puzzle[NOM/puzzle] européen[ADJ/européen] s'assemblent[VER:subp/s'assemblent] patiemment[ADV/patiemment] .[SENT/.] Le[DET:ART/le] renforcement[NOM/renforcement] du[PRP:det/du] "[PUN:cit/"] pare-feu[NOM/pare-feu] "[PUN:cit/"] destiné[VER:pper/destiner] à[PRP/à] protéger[VER:infi/protéger] les[DET:ART/le] pays[NOM/pays] fragilisés[VER:pper/fragiliser] et[KON/et] le[DET:ART/le] nouveau[ADJ/nouveau] plan[NOM/plan] d'austérité[VER:pper/d'austérité] en[PRP/en] Espagne[NAM/Espagne] ne[ADV/ne] provoquent[VER:pres/provoquer] pourtant[ADV/pourtant] pas[ADV/pas] un[DET:ART/un] optimisme[NOM/optimisme] exagéré[VER:pper/exagérer]
|
La[DET:ART/le] hausse[NOM/hausse] de[PRP/de] la[DET:ART/le] TVA[ABR/TVA] fragilise[VER:pres/fragiliser] les[DET:ART/le] libraires[NOM/libraire]
|
Le[DET:ART/le] passage[NOM/passage] de[PRP/de] l'impôt[NOM/l'impôt] de[PRP/de] 5,5[NUM/@card@] %[SYM/%] à[PRP/à] 7[NUM/@card@] %[SYM/%] dès[PRP/dès] le[DET:ART/le] 1er[NUM/1er] avril[NOM/avril] oblige[VER:pres/obliger] une[DET:ART/un] profession[NOM/profession] déjà[ADV/déjà] en[PRP/en] difficulté[NOM/difficulté] à[PRP/à] engager[VER:infi/engager] de[PRP/de] nouveaux[ADJ/nouveau] frais[ADJ/frais]
|
Les[DET:ART/le] salariés[NOM/salarié] de[PRP/de] Bekaert[NAM/Bekaert] en[PRP/en] grève[NOM/grève] contre[PRP/contre] l'augmentation[NOM/l'augmentation] de[PRP/de] salaire[NOM/salaire] du[PRP:det/du] patron[NOM/patron]
|
Bert[NAM/Bert] De[NAM/De] Graeve[NAM/Graeve] voit[VER:pres/voir] son[DET:POS/son] salaire[NOM/salaire] progresser[VER:infi/progresser] de[PRP/de] 30[NUM/@card@] %[SYM/%] au[PRP:det/au] moment[NOM/moment] où[PRO:REL/où] il[PRO:PER/il] engage[VER:pres/engager] une[DET:ART/un] restructuration[NOM/restructuration] d'une[VER:subp/d'une] ampleur[NOM/ampleur] historique[ADJ/historique] chez[PRP/chez] le[DET:ART/le] leader[NOM/leader] mondial[ADJ/mondial] du[PRP:det/du] fil[NOM/fil] d'acier[ADJ/d'acier] |
... | ... |
[ Cliquez sur le tableau pour le visualiser ]
Cliquer sur les liens pour télécharger les fichiers et les scripts.