Dans cette troisième BAO, nous avons mis au point plusieurs moyens pour extraire des patrons à partir des sorties obtenues avec Cordial et TreeTagger. Nous nous sommes principalement intéressées au patron NOM ADJ.
Extraction de patrons à partir de la sortie XML
Pour extraire les patrons à partir de la sortie fournie par TreeTagger, nous avons utilisé XPath et XSLT.
XPath permet de trouver des ressources dans un document XML en faisant des requêtes. On peut lancer ces requêtes dans Cooktop, par exemple.
XSLT est un langage de transformation. Il transforme un document XML en un autre type de document. XSLT utilise XPath pour parcourir un arbre XML.
Pour ce travail, nous avons choisi de travailler dans Cooktop.
Avant d'obtenir la sortie voulue, nous sommes passées par plusieurs étapes.
Dans tous les cas, il est nécessaire d'ouvrir le fichier XML à traiter dans Cooktop, dans l'onglet : source (XML) (comme on le voit ci-dessous).
Cliquez sur l'image pour l'agrandir
A partir de là, on peut procéder de plusieurs manières pour extraire des patrons.
-- Entrer une requête XPath dans Cooktop --
On peut choisir de rentrer la requête XPath suivante dans Cooktop :
values:(//element[./data[contains(text(),'NOM')]]/following-sibling::element[1][./data[contains(text(),'ADJ')]]/data[3])|(//element[./data[contains(text(),'ADJ')]]/preceding-sibling::element[1][./data[contains(text(),'NOM')]]/data[3])
Cette requête permet d'accèder aux valeurs des éléments grâce au mot clef : values qui s'oppose à nodes. Elle permet de récupérer un élément de type NOM suivi d'un élément de type ADJ. following-sibling::element[1] permet de dire que le noeud qui suit le noeud NOM doit être de type ADJ et preceding-sibling::element[1] permet de dire que le noeud qui précède le noeud ADJ doit être de type NOM.
Cette requête ne fournit pas exactement la sortie voulue car on obtient une liste de noms et d'adjectifs qui se suivent.
Cliquez sur l'image pour l'agrandir
-- Utiliser une feuille de style XSL --
On peut aussi choisir d'utiliser une feuille de style XSL. Nous avons d'abord rédigé cette première feuille :
< xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/transform" version="2.0">
<xsl:template match="element">
<xsl:choose>
<xsl:when test="(./data[contains(text(),'NOM')]) and (following-sibling::element[1][./data[contains(text(),'ADJ')]])">
<font color="red">
<xsl:value-of select="./data[3]" />
</font>
</xsl:when>
<xsl:when test="(./data[contains(text(),'ADJ')]) and (preceding-sibling::element[1][./data[contains(text(),'NOM')]])">
<font color="purple">
<xsl:value-of select="./data[3]" />
</font>
<br />
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Cliquez sur l'image pour l'agrandir
Cette feuille de style ne donne pas exactement le résultat attendu. En effet, on extrait le patron attendu mais les noms et les adjectifs ne sont pas séparés par des espaces, comme on peut le voir ci-dessous.
Cliquez sur l'image pour l'agrandir
Nous avons donc modifié cette feuille de style afin qu'elle donne une sortie qui correspond exactement à nos attentes.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/transform" version="2.0">
<xsl:template match="element">
<xsl:choose>
<xsl:when test="(./data[contains(text(),'NOM')]) and (following-sibling::element[1][./data[contains(text(),'ADJ')]])">
<font color="red">
<xsl:value-of select="./data[3]" />
</font>
<xsl:text>
</xsl:text> < /xsl:when>
<xsl:when test="(./data[contains(text(),'ADJ')]) and (preceding-sibling::element[1][./data[contains(text(),'NOM')]])">
<font color="purple">
<xsl:value-of select="./data[3]" />
</font>
<br/>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Cliquez sur l'image pour l'agrandir
Cette feuille de style donne enfin le bon résultat. Mais comment fonctionne-t'elle?
La balise <xsl:template match="element"> indique qu'on applique des gabarits aux éléments définis, ici : element qui contiennent des noms ou des adjectifs.
La balise </xsl:choose> combinée avec </xsl:when> est utilisée pour construire des tests conditionnels. Dans notre cas, si on trouve un nom suivi d'un adjectif alors on choisit de sélectionner le troisième élément, c'est à dire le lemme et on met ce lemme en rouge. C'est la balise <xsl:value-of select="./data[3]" /> qui sélectionne le troisième élément. La balise <xsl:value-of> calcule la valeur textuelle d'un élément et l'insère dans le résultat. On effectue ensuite la même chose avec les adjectifs que l'on imprime, par contre, en violet.
La balise </xsl:text> génère le texte spécifié. Ici, cette balise s'applique entre les deux mots récupérés et c'est elle qui permet d'insérer l'espace manquant.
Voici le résultat obtenu :
Cliquez sur l'image pour l'agrandir
On remarque qu'il y a quelques patrons étranges comme : Mme Amara qu'on ne s'attend pas à voir ici. Cette bizarrerie est dûe au fait que TreeTagger, comme on l'a vu précedemment, fait parfois des erreurs dans l'étiquetage.
Extraction de patrons à partir de la sortie au format texte
Pour extraire les patrons à partir de la sortie fournie par Cordial, nous avons écrit un script Perl.
En entrée, ce programme prend deux fichiers :
- le fichier étiqueté avec Cordial
- le fichier qui contient les patrons que l'on veut extraire
On entre donc dans la ligne de commande : perl patron-avec-cordial.pl texteetiquetteavecCordial.cnr patrons.txt.
Voici le script que nous avons écrit :
#/usr/bin/perl #c'est le chibong!!
open (FICCORDIAL, "$ARGV[0]");
open(FILEOUT, ">NomAdjavecCordial.txt");
while (<FICCORDIAL>) { # variable par défaut correspondante : $_
next if ($_!~/\t/); # on saute les lignes dans lesquelles il n'y a rien
my $ligne = $_;
chomp $ligne; # pour enlever le caractère de retour à chaque fin de ligne
if ($ligne!~/PCT/) { # si la ligne ne contient pas de ponctuation
# MADE IN J-M DAUBE : $ligne=~/(\w+)\t(\w+)\t(\w+)\t/;
# ATTENTION cette ligne n'est pas satisfaisante pour les mots qui contiennent des espaces !! exemple : au moment de
# avec la bibliothèque locale (use locale) 'w' aurait aussi contenu les caractères accentués car on se place en France
@cutcut=split(/\t/, $ligne); #on utilise le fait que les mots sont séparés par des tabulations
push (@token, $cutcut[0]);
push (@lemme, $cutcut[1]);
push (@pos, $cutcut[2]);
$i++; #ça compte les pos
}
else {
#print "@token\n";
#print "appuie sur return pour continuer\n";
#my $reponse=<StdIN>;
open (PAtrONS, "$ARGV[1]"); # c'est le fichier des patrons qu'on veut trouver
while (<PAtrONS>) {
my $patron = $_; # on met dans la variable patron ce qui est contenu dans patrons.txt
chomp $patron; # pour enlever le caractère de retour à chaque fin de ligne
$compare=""; # on initialise $compare à vide
foreach my $element (@pos) { # pour chaque partie du discours
$compare=$compare."\t".$element; # on met à la suite toutes les parties du discours avec entre deux parties une tabulation
} # fin de foreach
# if ($compare =~/$patron/) { # si il y a une correspondance entre le patron et la suite des parties du discours
my $j = 0;
my $k = 0;
while ($compare =~/$patron/g) { #tant qu'on trouve le patron
$apres=$'; #on met dans $apres le contexte droit
$avant=$`; #on met dans $avant le contexte gauche
while ($avant =~/\t/g) {
$j++;
}
while ($apres =~/\t/g) {
$k++;
}
# print "there is a match!\n\n"; # on écrit "there is a match ! "
print FILEOUT "@token[$j-1..$i-$k-1]\n"; #on prend les mots qui ont les indices compris entre x .. y comme [a..z]
$j = 0 ;
$k = 0;
} # fin de if
} # fin de while
close PAtrONS; #on ferme PAtrONS
@token=(); #on remet la liste token à zéro
@lemme=(); #on remet la liste lemme à zéro
@pos=(); #on remet la liste pos à zéro
$i=0;
} # fin de else
} # fin de while
Au début, on ouvre le fichier étiqueté et on prépare le fichier de sortie : NomAdjavecCordial.txt. On lit chaque ligne du fichier en entrée. Si la ligne ne contient rien, on passe à la suivante. Pour accéder à chaque ligne, on peut utiliser la variable : $_. Puis, on met la ligne courante dans $ligne et on fait un chomp pour supprimer le retour à la ligne, en fin de ligne. Si la ligne ne contient pas de ponctuation, on fait un split de la ligne avec comme séparateur : des tabulations. Ainsi, on a séparé chaque colonne du fichier d'entrée. On met ensuite, grâce à la commande push chaque mot dans le tableau qui lui correspond : token, lemme, pos. Si la ligne contient une ponctuation alors, on ouvre le fichier qui contient les patrons et on compare chaque patron avec les suites de parties du discours qu'on a mis dans $compare. En effet, grâce à la boucle foreach on a concaténé toutes les parties du discours qu'on a trouvé avant de rencontrer la ponctuation. Si jamais il y a une correspondance entre le patron et les parties du discours que l'on vient de trouver alors on récupère les mots qui correspondent aux parties du discours du patron. On a ainsi récupéré les patrons qui nous intéressent.
La ponctuation est utilisée comme une frontière car on considère qu'un groupe nom-adj ne peut pas être séparé par un signe de ponctuation.
Le fichier de patrons contient les lignes suivantes :
NCMS ADJMS | pour les couples nom-adj au masculin singulier |
NCFS ADJFS | pour les couples nom-adj au féminin singulier |
NCMP ADJMP | pour les couples nom-adj au féminin pluriel |
NCFP ADJFR | pour les couples nom-adj au masculin pluriel |
NCMS ADJSIG | pour les couples nom-adj au masculin singulier avec un adjectif singulier mais invariant en genre |
NCFS ADJSIG | pour les couples nom-adj au féminin singulier avec un adjectif singulier mais invariant en genre |
NCFP ADJPIG | pour les couples nom-adj au féminin pluriel avec un adjectif pluriel mais invariant en genre |
NCMP ADJPIG | pour les couples nom-adj au masculin pluriel avec un adjectif pluriel mais invariant en genre |
NCPIG ADJMP | pour les couples nom-adj où le nom est au pluriel mais invariant en genre et l'adjectif au masculin pluriel |
NCPIG ADJFP | pour les couples nom-adj où le nom est au pluriel mais invariant en genre et l'adjectif au féminin pluriel |
NCSIG ADJMS | pour les couples nom-adj où le nom est au singulier mais invariant en genre et l'adjectif au masculin |
NCSIG ADJFS | pour les couples nom-adj où le nom est au singulier mais invariant en genre et l'adjectif au féminin singulier |
Cette énumération permet de prendre tous les couples nom-adj quel que soit le genre et le nombre des couples. Nous n'avons pas pris les couples qui contenaient ADJNUM (ex : deux hommes) car nous avons considéré qu'il ne s'agissait pas de la même chose.
Ce script a l'avantage d'être très facilement modifiable car il suffit de mettre d'autres catégories grammaticales dans le fichier : patrons.txt pour extraire d'autres patrons.
Comparaison des patrons obtenus avec Cordial et TreeTagger
Puisque nous n'avons pas utilisé les mêmes méthodes ni pour étiqueter les corpus (TreeTagger VS Cordial), ni pour extraire les patrons (Perl VS feuille de style XSL), nous nous attendons à trouver des différences entre les deux fichiers qui contiennent les patrons. Nous allons donc comparer les deux sorties.
La première chose que l'on remarque est que le fichier qui contient les patrons qui proviennent de l'étiquetage avec TreeTagger est beaucoup plus long (516 lignes, à raison de 1 patron par ligne) alors que le fichier qui contient les patrons qui proviennent de l'étiquetage avec Cordial est plus court (398 lignes, à raison de 1 patron par ligne).
Pour mieux comprendre les différences, nous avons travaillé sur les syntagmes dont le nom commence par un a. Le choix du a est arbitraire, mais il permet de travailler sur un échantillon. Après avoir supprimé tous les syntagmes ne commençant pas par un a et tous ceux qui étaient communs pour la lettre a aux deux parties, il nous reste les syntagmes suivants:
Mots présents dans l'étiquetage issu de Cordial et absents dans l'étiquetage issu de TreeTagger
1 | accords dits de | Erreur de Cordial : dits de n'est pas un ADJ |
2 | administrateur cité | Erreur de Cordial : cité n'est pas un ADJ |
3 | adolescents morts lors d' | Erreur de Cordial : morts lors d' n'est pas un ADJ |
4 | arrêt rendu | Erreur de Cordial : rendu n'est pas un ADJ |
Les quatre patrons présents dans l'étiquetage issu de Cordial et absents dans l'étiquetage issu de TreeTagger sont présents à cause d'erreurs de la part de Cordial.
Mots présents dans l'étiquetage issu de TreeTagger et absents dans l'étiquetage issu de Cordial
5 | action Yahoo | Erreur de TreeTagger : Yahoo n'est pas un ADJ |
6 | affaire Ioukos | Erreur de Treetagger : Ioukos n'est pas un ADJ |
7 | affaire Kerviel | Erreur de Treetagger : Kerviel n'est pas un ADJ |
8 | Amos Wako | Erreur de Treetagger : Wako n'est pas un ADJ |
9 | anciens parlementaires | Erreur de Treetagger : ancien n'est pas un NOM ici et parlementaire n'est pas un adjectif |
10 | Anne-Marie Idrac | Erreur de Treetagger : Idrac n'est pas un ADJ |
11 | autorités kosovares | Bonne analyse de Treetagger mais n'est pas trouvé par Cordial pour la raison suivante : Idrackosovares kosovares NCI => Erreur orthographique: kosovares => kodachromes |
En résumé, on peut dire que toutes les différences qui existent entre Cordial et Treetagger sont dues soit à un erreur de Cordial, soit à une erreur de Treetagger. Ainsi, seuls les patrons communs aux deux systèmes sont corrects.
Partant de cette constatation, nous avons voulu créer un script qui ne garde que les patrons corrects, c'est à dire, les patrons présents dans les deux listes. Voici donc ce programme (élaboré en grande partie grâce à l'aide de M. Fleury).
#!/usr/bin/perl
open(patronC,"$ARGV[0]"); # on ouvre le premier fichier qu'on va lire
open(patronT,"$ARGV[1]"); # on ouvre le deuxieme fichier qu'on va lire
open(FILEOUT, ">tripatrons.txt"); # on ouvre le fichier dans lequel on va écrire
$i=0;
$a=0;
$r=0;
while (<patronC>) {
my $ligne = $_;
chomp $ligne;
$ligne=~s/ +/ /g;
$tabC[$i]=$ligne;
$i++;
}
while (<patronT>) {
my $ligne = $_;
chomp $ligne;
$ligne=~s/ +/ /g;
$tabT[$a]=$ligne;
$a++;
}
foreach my $e (@tabC) {
foreach my $r (@tabT) {
if ($e eq $r){
$tabOK{$e}++;
}
}
}
foreach my $a (keys %tabOK) {
print FILEOUT "$a\n";
}
close(patronC); # on ferme le fichier en lecture
close(patronT); # on ferme le fichier en lecture
close(FILEOUT);# on ferme le fichier en sortie
Ce script prend en argument le fichier Cordial et le fichier TreeTagger et retourne en sortie un fichier qui contient la liste des bons patrons. Chaque ligne des patrons Cordial et des patrons TreeTagger est mise dans un tableau. Il y a un tableau pour les lignes de Cordial et un tableau pour les lignes de TreeTagger. Cependant, avant d'être mise dans un tableau, chaque ligne est modifiée. En effet, les espaces entre les noms et les adjectifs sont normalisés grâce à la ligne : $ligne=~s/ +/ /g;. Puis, dans la deuxième partie du programme, chaque ligne du tableau de Cordial est comparée à une ligne du tableau de Treetagger. Si les deux tableaux ont une ligne en commun, alors on écrit cette ligne en commun dans le tableau final. Sinon, la ligne n'est pas gardée. A la fin, le tableau qui ne contient que les lignes en commun est imprimé dans un troisième fichier.
Autres extractions
Dans le cadre du cours intitulé : "Perl pour les linguistes" que nous avons également suivi ce semestre, nous avons écrit différents scripts en Perl qui permettent d'extraire les patrons NOM ADJ et les patrons NOM PREP NOM. Ces scripts Perl fonctionnent à partir des sorties au format texte et des sorties au format XML. Nous les présentons ci-dessous.
-- A partir de la sortie au format XML --
Voici, tout d'abord, le script qui permet d'extraire le patron NOM ADJ :
open(FILE,"$ARGV[0]");
open (FILEOUT, "<extractNOMADJ-TreeTagger.txt");
#--------------------------------------------
# le patron cherché ici est du type NOM ADJ;
#--------------------------------------------
my @lignes=<FILE>;
close(FILE);
while (@lignes) {
my $ligne=shift(@lignes);
chomp $ligne;
my $sequence="";
my $longueur=0;
if ( $ligne =~ /<element><data type=\"type\">NOM<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
my $forme=$1;
$sequence.=$forme;
$longueur=1;
my $nextligne=$lignes[0];
if ( $nextligne =~ /<element><data type=\"type\">ADJ<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
my $forme=$1;
$sequence.=" ".$forme;
$longueur=2;
}
}
if ($longueur == 2) {
print FILEOUT $sequence,"\n";
}
}
close (FILEOUT);
Voici, maintenant, le script qui permet d'extraire le patron NOM PREP NOM :
open(FILE,"$ARGV[0]");
open (FILEOUT, "<extractNOMPREPNOM-TreeTagger.txt");
#--------------------------------------------
# le patron cherché ici est du type NOM PREP NOM;
#--------------------------------------------
my @lignes=<FILE>;
close(FILE);
while (@lignes) {
my $ligne=shift(@lignes);
chomp $ligne;
my $sequence="";
my $longueur=0;
if ( $ligne =~ /<element><data type=\"type\">NOM<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
my $forme=$1;
$sequence.=$forme;
$longueur=1;
my $nextligne=$lignes[0];
if ( $nextligne =~ /<element><data type=\"type\">PRP<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
my $forme=$1;
$sequence.=" ".$forme;
$longueur=2;
my $nextligne=$lignes[1];
if ( $nextligne =~ /<element><data type=\"type\">NOM<\/data><data type=\"lemma\">[^<]+<\/data><data type=\"string\">([^<]+)<\/data><\/element>/) {
my $forme=$1;
$sequence.=" ".$forme;
$longueur=3;
}
}
}
if ($longueur == 3) {
print FILEOUT $sequence,"\n";
}
}
close (FILEOUT);
Ce programme prend chaque ligne d'un fichier étiqueté avec Treetagger et la met dans la variable $ligne. Puis, si la ligne contient un NOM (dans le cas du patron NOM ADJ) alors ce nom est stocké dans la variable $sequence et on regarde la ligne suivante. Si la ligne suivante contient un ADJ (toujours dans le cas du patron NOM ADJ) alors la variable $sequence est complétée avec l'adjectif et le tout est imprimé.
Ce script est très facilement adaptable à d'autres patrons. Pour des patrons de deux mots, il suffit de reprendre le patron NOM ADJ et de remplacer les étiquettes NOM et ADJ par d'autres. Pour des patrons de trois mots, il faut reprendre le script utilisé pour le patron NOM PREP NOM. Il est également possible de créer des scripts pour des patrons de plus de trois mots.
-- A partir de la sortie au format texte --
Voici, en premier, le script qui permet d'extraire le patron NOM ADJ :
open(FILE,"$ARGV[0]");
open (FILEOUT, "<extractNOMADJ-Cordial.txt");
#--------------------------------------------
# le patron cherché ici est du type NOM ADJ;
#--------------------------------------------
my @lignes=<FILE; #on met tout le fichier dans une liste
close(FILE);
while (@lignes) { #tant qu'il y a quelque chose à lire
my $ligne=shift(@lignes); # on prend le premier élément de la ligne
chomp $ligne; # on enlève le retour chariot
my $sequence=""; # on initialise séquence à vide
my $longueur=0; # au début la longueur est 0
if ( $ligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) { # est ce que cette ligne correspond à NC
my $forme=$1; # si c'est un NC on récupère son token qui est en première colonne d'où $1
$sequence.=$forme; #on concatène dans la séquence finale
$longueur=1; # on dit que le nombre de mot dans la séquence est 1
my $nextligne=$lignes[0]; # comme on a vidé un élément, la ligne suivante est à l'indice 0
if ( $nextligne =~ /^([^\t]+)\t[^\t]+\tADJ.*/) { # est ce que cette ligne désigne un ADJ
my $forme=$1; # on récupère le token
$sequence.=" ".$forme; # on concatène dans la séquence finale qui contient un nom
$longueur=2; #maintenant la longueur vaut 2
}
}
if ($longueur == 2) { # si la séquence vaut 2 : c'est à dire qu'on a NOM + ADJ
print FILEOUT $sequence,"\n"; # on écrit le nom + le det
}
}
close (FILEOUT);
Voici, en second, le script qui permet d'extraire le patron NOM PREP NOM :
open(FILE,"$ARGV[0]");
open (FILEOUT, ">extractNOMPREPNOM-Cordial.txt");
#--------------------------------------------
# le patron cherché ici est du type NOM PREP NOM;
#--------------------------------------------
my @lignes=<FILE>; #on met tout le fichier dans une liste
close(FILE);
while (@lignes) { #tant qu'il y a quelque chose à lirev
my $ligne=shift(@lignes); # on prend le premier élément de la ligne
chomp $ligne; # on enlève le retour chariot
my $sequence=""; # on initialise séquence à vide
my $longueur=0; # au début la longueur est 0
if ( $ligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) { # est ce que cette ligne correspond à NC
my $forme=$1; # si c'est un NC on récupère son token qui est en première colonne d'où $1
$sequence.=$forme; #on concatène dans la séquence finale
$longueur=1; # on dit que le nombre de mot dans la séquence est 1
my $nextligne=$lignes[0]; # comme on a vidé un élément, la ligne suivante est à l'indice 0
if ( $nextligne =~ /^([^\t]+)\t[^\t]+\tPREP.*/) { # est ce que cette ligne désigne une PREP
my $forme=$1; # on récupère le tokenv
$sequence.=" ".$forme; # on concatène dans la séquence finale qui contient un nom
$longueur=2; #maintenant la longueur vaut 2
my $nextligne=$lignes[1]; # comme on a vidé un élément, la ligne suivante est à l'indice 0
if ( $nextligne =~ /^([^\t]+)\t[^\t]+\tNC.*/) { # est ce que cette ligne désigne un NC
my $forme=$1; # on récupère le token
$sequence.=" ".$forme; # on concatène dans la séquence finale qui contient un nom
$longueur=3; #maintenant la longueur vaut 3
}
}
}
if ($longueur == 3) { # si la séquence vaut 2 : c'est à dire qu'on a NOM + ADJ
print FILEOUT $sequence,"\n"; # on écrit le nom + le det
}
}
close (FILEOUT);
Ces deux programmes, bien qu'adaptés à Cordial, fonctionnent exactement de la même manière que les deux programmes utilisés avec TreeTagger. Ils sont également adaptables à d'autres patrons.
L'équipe
Sophie
Marion
<
Les scripts
Télécharger la requête XPAthTélécharger la feuille de style XSL
Télécharger la sortie obtenue avec la feuille de style XSL
Télécharger le script perl pour extraire les patrons
Télécharger le fichier patrons.txt
Télécharger la sortie obtenue avec le script Perl
Télécharger le script qui compare les deux listes et ne garde que les patrons corrects
Télécharger la liste qui ne contient que des patrons corrects
Télécharger le script Perl - autres extractions - patron NOM ADJ - TreeTagger
Télécharger le script Perl - autres extractions - patron NOM PREP NOM - TreeTagger
Télécharger le script Perl - autres extractions - patron NOM ADJ - Cordial
Télécharger le script Perl - autres extractions - patron NOM PREP NOM - Cordial
Télécharger la sortie - autres extractions - patron NOM ADJ - TreeTagger
Télécharger la sortie - autres extractions - patron NOM PREP NOM - TreeTagger
Télécharger la sortie - autres extractions - patron NOM ADJ - Cordial
Télécharger la sortie - autres extractions - patron NOM PREP NOM - Cordial