mercredi 19 décembre 2012

Apache UIMA HMM Tagger FR Models

Download here: Models for the Apache UIMA Hidden Markov Model Tagger Annotator [1] (from the sandbox UIMA Addons)

The models concern the following tasks:
* Part of speech tagging (POS)
* Grammatical subcategorization (Subcat)
* Morphological inflection analysis (Mph) 
* Lemmatization(canonical form) 
* Ee analysis (POS + Subcat + Mph)

Models have been built with the addon's version 2.4 using the French Treebank corpus [2] (version 2010). The ftb licence does not prevent to distribute analysis results under whatever licence but it mentions that the ftb should be used only for research purpose.Consequently we restrict the use of these models only for research purposes.

To get the '.dat', unzip and have a look to the '/HMMTrainerTagger/french/' dir

[1] http://uima.apache.org/sandbox.html#tagger.annotator
[2] For more on the French Treebank, see Abeille, A., L. Clement, and F. Toussenel. 2003. `Building a treebank for French', in A. Abeille (ed) Treebanks , Kluwer, Dordrecht. http://www.llf.cnrs.fr/Gens/Abeille/French-Treebank-fr.php

Apache OpenNLP FR Models


Download here: the last version of the models for processing several common Natural Language Processing tasks in French with Apache OpenNLP  [1]

The models concern the following tasks: Sentence segmentation, Word tokenization, Part-of-Speech Tagging, Morphological inflection analysis*, Lemmatization*, Chunking, Person|Organization|Location Name Entity recognition**

Except for Named Entity models, models have been built using the French Treebank corpus [2] (version 2010). Its licence does not prevent to distribute its analysis results under whatever licence but it mentions that the ftb should be used only for research purpose. Consequently we restrict the use of these models only for research purposes. 


* To be used with the tagger 

** Named Finder Models have been built by Olivier Grisel. See for more detail [3]. 

To get the '.bin' files, unzip and have a loot at the '/opennlp/models/fr/' dir. 

[2] For more on the French Treebank, see Abeille, A., L. Clement, and F. Toussenel. 2003. `Building a treebank for French', in A. Abeille (ed) Treebanks , Kluwer, Dordrecht. http://www.llf.cnrs.fr/Gens/Abeille/French-Treebank-fr.php 

UIMA AS (Asynchronous Scaleout) Tutorial?


At the bottom of the Getting Started: Apache UIMA Asynchronous Scaleout [1] page, you find the following mention
See the README file [3] in the top level directory for instructions on deploying and testing standard UIMA example annotators as UIMA AS services.
Download for example the binary version of UIMA AS [2] and you fill find out the README in the top level directory. It contains various information for Installation and Setup, and examples for Starting the ActiveMQ Broker,  Deploying an Analysis Engine as a UIMA AS Asynchronous Service, Calling a UIMA AS Asynchronous Service, Migration from CPM to UIMA-AS...

Again the direct link to this README file [3].

[1]: http://uima.apache.org/doc-uimaas-what.html
[2]: http://uima.apache.org/downloads.cgi
[3]: http://svn.apache.org/repos/asf/uima/uima-as/trunk/README

mercredi 21 novembre 2012

Accéder et gérer des ressources externes au sein d'un UIMA Analysis Engine

Ce post s'appuie notamment sur la section 1.5.4 du guide utilisateur [1] (Managing and accessing External Resources).
Des exemples de descripteurs et de code Java d'analysis engine mettant en oeuvre l'accès et la gestion à des ressources externes sont fournis dans l'exemple 6 du tutoriel de uima-examples.

De quoi parle-t-on ?

On exploite régulièrement des ressources au sein de composants (analysis engine) de traitement de la langue. Il peut s'agir par exemples de dictionnaires que l'on accède en lecture ou bien d'objets que l'on accède en écriture (et lecture) pour stocker des informations sur le sujet d'analyse du moment. 
Concernant ce deuxième cas, cela peut par exemple consister en le nombre de fois où un élément des données (une instance) avec un label x est classée avec un label y, ce qui permettra par la suite de construire une matrice de contingence pour évaluer les résultats d'un processus de classification. On peut imaginer plusieurs instances d'un même traitement qui comptent en parallèle différents documents... Un autre exemple peut consister en compter les occurrences de formes candidates (e.g. ngrams) en vue de calculer ultérieurement le tf.idf de ces formes pour un extracteur de termes par exemple. Dans ces deux exemples le calcul ultérieur peut être envisagé au sein de la méthode collectionProcessComplete()d'un analysis engine. 
Pour l'exemple sur le comptage de la classification des instances on peut imaginer qu'un objet ayant un attribut de type Map String to Integer pourrait parfaitement nous convenir. Les clés string seraient "truePositive", "trueNegative", "falsePositive" et "falseNegative". Remarquons qu'une Map String to String pourrait très bien convenir aussi pour un dictionnaire qui associe une forme lexicale avec son lemme.

Qu'entend-t-on par gestion et accès à une ressource ?

La gestion d'une ressource est souvent plus "facile" et plus "rapide" à mettre en oeuvre lorsque la définition de celle-ci est au sein même du composant que l'on développe.  Elle nécessite généralement que la connaissance de l'API du langage de programmation (Java) et du modèle de données de la ressource (induit du format du dictionnaire ou bien du phénomène que l'on observe) pour la manipuler. 
Externaliser les ressources de type dictionnaire et spécifier le chemin (e.g. sur le système de fichier ou sur le web) pour y accéder par la définition de paramètres des composants, sont un début de bonne pratique. Il en coûte quelques lignes de codes supplémentaires (gestion de fichiers et du parcours du format de stockage).  C'est un premier pas pour faciliter la maintenance et le partage de de ressources en lecture entre plusieurs composants.
Le chemin peut même désigner une ressource publique ou un chemin relatif plus facilement portable.
Néanmoins cette solution ne répond pas au problème de multiplication des instances de ressources en mémoire (une pour chaque instance de composant qui souhaite accéder à la ressource) ni au besoin d'accès concurrent en écriture sur la ressource. Pour cela il faut se plonger davantage dans la maîtrise du langage de programmation et écrire encore "quelques" lignes de codes supplémentaires.
Par ailleurs il est souvent intéressant de découpler l'API d'accès d'un objet de son implémentation afin de ne pas rendre dépendant le composant à l'implémentation.

UIMA met à disposition ce qu'il appelle un RessourceManager pour permettre de 
  • partager la même instance d'un objet entre plusieurs composants (soit des composant distincts soit plusieurs instances d'un même composant)
  • éventuellement initialiser au démarrage les objets à partir du contenu d'un fichier pointé par une URL (ou éventuellement un chemin sur le système de fichiers local)
  • d'externaliser l'implémentation de l'API de manipulation de l'objet en en fournissant une de base pour traiter l'objet comme un flux et en offrant la possibilité d'en spécifier de plus ad hoc et d'en fournir une implémentation

Comment déclarer l'identifiant utilisé dans le code du composant pour désigner la ressource externe (on parle aussi de clé) et comment spécifier l'interface qui déclare les manipulations que l'on peut réaliser sur l'objet ?  

Pour ce faire, on utilise le "component descriptor editor", onglet "Resources", section de gauche "Resource Dependencies" (correspond à externalResourceDependency dans le code source).

La valeur de la clé permet au code du composant d'identifier cette ressource. Elle est par conséquent unique au niveau de ce composant. Par contre d'autres composants peuvent utiliser cette valeur pour signifier d'autres ressources.

La spécification d'une interface est optionnelle. Pour rappel l'interface permet de dissocier l'implémentation de la manipulation de la ressource de son interface afin de pouvoir faire évoluer indépendamment le code du composant et celui de la gestion de la ressource. Sans nom d'interface spécifié, il sera possible d'accéder directement au contenu de la ressource par le biais d'une ImputStream (obtenu via une URL (éventuellement un chemin sur le système de fichiers local)). 
Cela signifie que le parsing de la ressource ne sera pas externalisé. Mais parfois si le format est simple, il n'est pas utile de définir une interface particulière.

Comment accède t on à la ressource au sein du code du composant ?

L'accès à la ressource ne peut que se faire si on a lié (binding) la clé que l'on a déclaré avec une définition de ressources externes, laquelle spécifiera l'URL pour accéder à la ressource. Cette opération sera vue ultérieurement.

Au sein du code on accède à la ressource à l'initialisation de l'analysis engine, c'est-à-dire que l'on accède à la ressource via le UimaContext fourni disponible au sein de la méthode initialize.

Lorsqu'aucune interface n'est définie lors de la déclaration de la clé désignant la ressource (onglet "Ressources" section "Resource Dependencies" ), on peut accéder à la ressource comme cela :
InputStream stream = getContext().getResourceAsStream("MaCleDesignantLaRessource");
ou bien comme cela si l'on souhaite déterminer la localisation du fichier ressource : 
URI uri = getContext().getResourceURI("MaCleDesignantLaRessource");

Lorsqu'une interface est définie on utilisera la méthode getResourceObject 
qui retourne un objet qui implémentera l'interface déclarée dans la section "Resource Dependencies" (onglet "Ressources" ) :
MyResourceTypeImpl mMyResourceTypeImpl = (MyResourceType)getContext().getResourceObject("MaCleDesignantLaRessource");

Comment définir une nouvelle ressource externe ?

Globalement une définition de ressource consiste à
  1. déclarer un nom de ressource pour l'identifier ultérieurement (afin de la lier avec des clés qui permettent aux composants d'identifier une ressource particulière au sein du code)
  2. indiquer une url pour trouver la ressource 
  3. et optionnellement spécifier une implémentation de l'interface pour accéder à la ressource lorsqu'une interface a été déclarée
La définition s'opère à l'aide du "component descriptor editor", onglet "Resources", section de gauche "Resources needs, Definition and Binding" (correspond à resourceManagerConfiguration dans le code source).

Indiquer dans le champ name (e.g. SharedResourceName) un nom servant à identifier cette définition de ressource. Lorsque vous lierait la ressource avec une clé utilisée par le code du composant, le nom sera automatiquement repris.

Indiquer dans le premier champ URL un chemin valide vers la ressource à charger. Si la ressource est locale indiquer un chemin relatif plutôt qu'un chemin absolu. Il n'y a pas de lieu de stockage spécifique requis pour une ressource. 
Personnellement je les place dans le répertoire resources de mon projet courant et j'ajoute le répertoire dans mon build path afin que les chemins relatifs soient accessibles dans celui-ci.

Dans le cas où votre ressource n'est pas de type dictionnaire et qu'il s'agit d'un objet partagé créé au fur et à mesure de l'analyse des documents traités, il faut tout de même spécifier un chemin vers une ressource existante. Créer par exemple un fichier vide defaultSharedResource.tmp dans un sous répertoire (external) (package) du répertoire resources du projet (n'oubliez pas d'ajouter ce répertoire dans le build path). Le chemin sera alors external/defaultSharedResource.tmp

Lorsqu'une interface a été spécifiée lors de la déclaration de clé ("Resource Dependencies" ), c'est sous cette section ("Resources needs, Definition and Binding") que l'on déclare la classe qui implémente l'interface.

If no implementation class is specified, then the getResource method returns a DataResource object, from which each annotator instance can obtain their own (non-shared) input stream; so threading is not an issue in this case.

Comment associer une clé à une définition d'une ressource externe ?

A l'aide du "component descriptor editor", onglet "Resources", 
  1. cliquer ensuite la clé que vous souhaitez dans la section de droite  ("Resource Dependencies" )
  2. cliquer sur la ressource définie que vous souhaitez dans la section de gauche ("Resources needs, Definition and Binding")
  3. puis cliquer sur "bind"

Lorsque l'on définit une interface d'accès à la ressource, que doit contenir la classe qui l'implémente ?

La classe qui implémenter l'interface de manipulation de la ressource doit implémenter aussi l'interface org.apache.uima.resource.SharedResourceObject. Concrètement cela signifie que l'on doit surcharger la méthode load(DataResource data) qui permet d'avoir accès à la ressource et qui va se charger de la parser pour initialiser l'instance de l'objet souhaité à retourner.
Cela doit globalement ressembler à cela
public class MyResourceTypeImpl implements MyResourceType_interface, SharedResourceObject {

public MyResourceTypeImpl() {
  super();
}

@Override
public void load(DataResource data) throws ResourceInitializationException {
}

}
Si il n'y a pas de ressources à charger, il suffit de laisser vide le code de la méthode.

Pour être instancié par le framework, l'implémentation doit être public et doit avoir un 0-argument constructor.

Comment partager une ressource entre plusieurs composants (ou comment bénéficier d'une seule définition de la ressource) ?


Les descripteurs de chaque composant doivent contenir la déclaration d'une dépendance pour la ressource partagée avec une valeur de clé qui leur est propre.
Seul l'un des composants spécifie une définition de la ressource (en donnant un nom et une URL pour accéder à la ressource). Ce composant là peut lier cette ressource à sa clé. 
Il n'est pas possible d'opérer le binding au sein des descripteurs des autres composants. Si la ressource est requise pour ces composants, ceux-ci ne pourront fonctionner normalement.

Pour partager la ressource il faut utiliser un descripteur aggregate qui va réunir les descripteurs de différents composants. Dans la section Resources, celui-ci spécifiera le binding entre la ressource souhaitée et les clefs affichés des composants.

Qu'en est il de la sûreté d'accès à la ressource quand celle-ci est partagée ?

La documentation indique que "If an implementation class is specified in the external resource, only one instance of that implementation class is created for a given binding, and is shared among all annotators. Because of this, the implementation of that shared instance must be written to be thread-safe - that is, to operate correctly when called at arbitrary times by multiple threads."

Le contrôle d'accès à des méthodes sensibles peut être une solution pour permettre un accès concurrentiel en écriture à la ressource.
public synchronized int increment() {
        return nextValue++;
    }

If no implementation class is specified, then the getResource method returns a DataResource object, from which each annotator instance can obtain their own (non-shared) input stream; so threading is not an issue in this case.

mardi 25 septembre 2012

Génération et correction automatique de QCM

Auto Multiple Choice est un ensemble d'utilitaires permettant de créer, gérer et corriger automatiquement des questionnaires à choix multiples (QCM). C'est un logiciel libre distribué sous la licence GPLv2+.


http://home.gna.org/auto-qcm/



Les sujets de QCM sont préparés par LaTeX, ce qui permet d'y écrire (éventuellement) toutes sortes de formules mathématiques.
AMC permet de changer de manière aléatoire l'ordre des réponses à l'intérieur de chaque question, ainsi que l'ordre des questions, de sorte que chaque sujet se présente différemment. Il est ainsi plus difficile pour les étudiants de copier sur leurs voisins...
À la suite de l'examen, les copies scannées peuvent être corrigées de manière automatique par AMC, grâce à une reconnaissance optique de marques (OMR). Si l'on ne dispose pas de scanner, ou pour les copies pour lesquelles la correction automatique aurait mal fonctionné, une correction manuelle assistée est aussi possible : il suffit de cliquer à la souris sur les cases cochées par chaque étudiant sur la reproduction du sujet affichée à l'écran.
Il est possible de choisir le barème par défaut, ou de fixer un barème de manière fine pour chaque question du QCM. AMC fabrique un fichier OpenDocument rassemblant les notes de tous les étudiants, directement utilisable par LibreOffice.org ou OpenOffice.org.

Logiciel de génération d'emplois du temps open source


FET is open source free software for automatically scheduling the timetable of a school, high-school or university. It uses a fast and efficient timetabling algorithm. It is licensed under GNU GPL.
Usually, FET is able to solve a complicated timetable in maximum 5-20 minutes. For simpler timetables, it may take a shorter time, under 5 minutes (in some cases, a matter of seconds). For extremely difficult timetables, it may take a longer time, a matter of hours.

http://lalescu.ro/liviu/fet/




vendredi 27 juillet 2012

Example uima-connectors CAS to CSV

Using uima-connectors to serialize some CAS annotations into CSV-formatted files.
  1. This is performed in two steps: First, create a text view formatted in CSV with the information you wish serialize. 
  2. Second, write the views on the file system. The second step is optional, you do whatever you want with your view.


The first step is performed by the CAS2CSVAE. Each line of the '_CSVView', created at the first step, will contain some feature values of n annotation whose type have been configured via parameter. Columns of the lines contain the values of the features of the annotation type. They are also configured via parameters. 
The second step is performed by the ViewWriterAE. This AE requires the presence of org.apache.uima.examples.SourceDocumentInformation annotations in each CAS which results from using the FileSystemCollectionReader or using any tools from the apache uima SDK (like the DocumentAnalyzer). This is used to name the exported views in the file system.


Requirement
uima-connectors library is available here http://code.google.com/p/uima-connectors.
It requires the uima-common lib http://code.google.com/p/uima-common/.


Example of use
In the example eclipse project you will see how to turn TokenAnnotations with coveredText, posTag, stem which result from apache uima  addons analysis, into CSV formatted files.
See the descriptor desc/xample-apacheAddons-uimaConnectors/example-apacheAddons-uimaConnectors-CAS2CSV-ViewWriter-AAE.xml
In particular have a look at the aggregate and the parameter settings tabs.
The example project assumes you have installed the apache-uima and apache-uima-addons binaries. Check the build path before using it.

mercredi 20 juin 2012

Extraire le texte de documents HTML en créant des annotations à la place des balises

Traiter du SGML (e.g. HTML) ou du XML (i.e. SGML davantage contraint) est une activité commune dans nos chaînes de traitement TAL (Traitement Automatique des Langues). Par ailleurs, souvent les traitements que nous souhaitons réaliser (segmentation en phrases, en mots, étiquetage morpho-syntaxique, reconnaissance d'entités nommées...) ne fonctionnent que sur du texte simple (plain text).

1. Tika MarkupAnnotator vs. uima-connectors XML2CAS

A ma connaissance, il y a au moins deux composants UIMA "librement" disponibles pour 
  1. extraire le texte d'un document SGML sans en modifier ses offsets 
  2. transformer les balises d'un document SGML en annotations UIMA au dessus des zones de texte couvertes.
Il s'agit du Tika MarkupAnnotator [1] et du uima-connectors XML2CAS [3]. 
  • Pour chacun d'eux l'on peut spécifier la vue à analyser et la vue dans laquelle il faut produire le texte.
  • Chacun d'eux produit des annotations correspondantes aux balises. Le système de types est évidement différent dans sa forme même si l'on retrouve globalement dans le fond la même information. 
  • XML2CAS travaille seulement avec de l'XML et vous autorise à spécifier les noms des éléments que vous voulez transformer en annotations afin de restreindre la taille du CAS
  • MarkupAnnotator offre la possibilité de traiter de l'XML mal formée (i.e. du SGML et en particulier HTML). Cela relativement simplement en ajoutant la bibliothèque du TagSoup parser dans le classpath [5].
Le premier est disponible dans les Annotator addons de Apache UIMA [2] et le second requiert de récupérer la bibliothèque uima-common pour fonctionner (au final [3] et [4]).


2. Quelques détails sur mon test
Personnellement j'ai testé les deux au sein d'un projet java Eclipse en déclarant les dépendances  suivantes dans mon classpath (en plus de celles de UIMA):
  • UIMA_HOME/addons/annotator/TikaAnnotator/lib/tika-core-0.7.jar
  • UIMA_HOME/addons/annotator/TikaAnnotator/lib/tika-parsers-0.7.jar
  • UIMA_HOME/addons/annotator/TikaAnnotator/lib/uima-an-tika.jar
  • chemin/vers/votre/lib/uima-common-v120111.jar
  • chemin/vers/votre/lib/uima-connectors-v111205.jar
  • chemin/vers/votre/lib/tagsoup-1.2.1.jar
J'ai ajouté la UIMA nature au projet et ajouté le répertoire desc aux build path pour me faciliter la tâche. J'ai créé un descripteur d'Analysis Engine que j'ai changé en aggregate afin de rajouter, les composants que je souhaitais tester, dans ma pipeline (section aggregate du descripteur) : 
MarkupAnnotator et connectors.xml.XML2CASAE.
J'ai surchagé les paramètres des deux composants (section parameter) et n'ai pas oublié de les configurer (section parameter settings). 
Puis j'ai déclaré les types en sortie (section capabilities).
Enfin j'ai lancé ma chaîne à l'aide du Document Analyser. Lorsque j'ai testé sur du HTML je n'avais pas retiré le composant XML2CAS de ma pipeline.



jeudi 12 avril 2012

Sujet de thèse en Traitement Automatique des Langues et Multilinguisme

English version below.

-------------------------------------------------------------------------------

Sujet de thèse en Traitement Automatique des Langues et Multilinguisme

L'équipe du Traitement Automatique du Langage Naturel (TALN) du Laboratoire
Informatique de Nantes Atlantique (LINA UMR CNRS 6241) à l'Université de Nantes
propose un sujet de thèse en Informatique dans les domaines du Traitement
Automatique des Langues et du Multilinguisme.

*Titre:*
Analyse des structures discursives des textes et alignement de terminologies
multilingues en corpus comparables ; pour une modélisation discursive de la
notion de contexte.

*Résumé : *
La traduction automatique est l'une des activités de recherche les plus
ambitieuses de notre temps. Ce travail de thèse propose de s'attaquer à l'un de
ses enjeux, à savoir l'"alignement de terminologies multilingues" en corpus
comparables, et ce en explorant de nouvelles méthodes de mise en correspondance
des termes, à savoir à l'aide d'"analyses des structures discursives des
textes". L'approche état de l'art consiste à établir une mise en correspondance
des termes en mesurant la similarité de leurs contextes d'apparition à l'aide
de dictionnaires bilingues préexistants. Les problèmes fondamentaux de cette
approche sont qu'elle repose sur une modélisation très pauvre du contexte
d'apparition d'un terme (un sac de mots apparaissant autour des termes
analysés) et qu'elle présuppose l'existence de ressources lexicales bilingues
pour être réalisée.
Ce travail a pour objectif d'expérimenter des contextes de termes définis sur
la base de résultats d'analyses du discours ainsi que réfléchir à la définition
d'une notion de contexte discursif plus en adéquation avec la tâche.
Ce sujet émerge dans la continuité du projet européen TTC et du projet ANR
MeTRICC dont l'équipe TALN assure les coordinations.

*Mots clefs :*
Traduction, Alignement de terminologies multilingues, Analyse et modélisation
des structures du discours, Corpus comparables

*Profil et compétences recherchés: *
M2 Recherche informatique ou école d'ingénieurs
Bon niveau en anglais
Bonnes notions en apprentissage automatique
Bonnes connaissances en programmation Java/Python
Affinités avec le logiciel libre et le développement collaboratif

*Procédure de candidature* :
La date butoir de réception des candidatures est  le 20 Avril 2012 mais
la position restera ouverte jusqu'à ce qu'elle soit attribuée.
La thèse démarrera en Octobre 2012 et sera financée par une allocation ministérielle.
Les candidats intéressés sont invités à prendre contact le plus tôt possible
et à envoyer les informations suivantes : une lettre de motivation incluant votre
positionnement par rapport aux compétences attendues, un CV, un relevé
de notes avec classement au Master (au moins pour la période écoulée), un
lien vers un site web présentant le programme de votre master et des lettres
de recommandations de vos encadrants scientifiques.
Cette thèse pourra être précédée d'un stage de master recherche financé
sur le même thème. Prendre contact.

*Contact : *
Nicolas Hernandez et Emmanuel Morin (prenom.nom à univ-nantes.fr)

*Plus d'information sur le sujet de thèse :*
http://www.edstim.fr/these/sujets-de-these/informatique
http://e.nicolas.hernandez.free.fr/pub/rec/12 




-------------------------------------------------------------------------------
Researcher  position available: PhD in Natural Language Processing

The University of Nantes (West coast of France) offers an opening for a 3-year
PhD position at the LINA Computer Sciences Laboratory in the NLP Team (TALN).

LINA TALN leads research in several NLP domains such as term extraction,
syntactic and semantic analysis, and develops several applications (e.g.
machine translation, opinion mining, plagiarism detection).
LINA TALN participates in various projects founded by regional, national
and European sources.
http://www.lina.univ-nantes.fr/

*Subject:*
Discourse structure analysis and multilingual terminology alignment from comparable corpora.
Toward a discourse definition of the notion of context

*Brief description: *
Multilingual terminology alignment from comparable corpora is one of the major
issue of the automatic translation problem. To tackle this issue, the baseline
approach proposes to align terms whose contexts are considered as similar
thanks to bilingual dictionaries. This approach presents some drawbacks since
the context model is quite simple (a bag of words occurring around the
considered term) and because it requires external resources for performing.
The current study aims at exploring a new approach for building term contexts.
The idea is to use a more linguistically inspired approach: in particular to
use discourse analysis both for providing semantically delimited text area
around term occurrences and rhetorically dependent utterances in relation to
the utterance where a term occurs. The work will start by trying out
state-of-art discourse analysis methods, then it will go into the definition of
a discourse context notion related to the task in depth. This research will
pursue the works accomplished in the national and European projects MeTRICC
and TTC.

*Topics :*
Machine translation, Multilingual terminology alignment, Discourse analysis,
Comparable corpora

*Qualifications:
The ideal candidate would have:
- (or soon receive) a Master degree in computer science/engineering
- a background in NLP and/or machine learning
- programming skills in JAVA/Python
- experience in open source development (appreciated)
- good English proficiency and ability to learn French (if appropriate)

*Application procedure:*
The application deadline is April 20, 2012 , but consideration of candidates
will continue until the position is filled. It is expected to start on October 2012.
Candidates interested in the position are asked to contact Nicolas Hernandez
and Emmanuel Morin (firstname.lastname at univ-nantes.fr) with the following
documents: A letter of motivation outlining your interest in the specific project,
a curriculum vitae, at least two recommendation letters from a senior
researcher/professor who can judge your potential as a future PhD student.

The program will be funded by a grant from the French government.
Median annual earnings are between 20,000 and 24,000 Euros.

*More information on:*
http://www.edstim.fr/these/sujets-de-these/informatique
http://e.nicolas.hernandez.free.fr/pub/rec/12 

Master Informatique spécialité ATAL : Apprentissage et Traitement Automatique de la Langue

A la rentrée 2012/2013 ouvrira à l'université de Nantes un Master Informatique spécialité ATAL (Apprentissage et Traitement Automatique de la Langue).

Le Master ATAL viser à former des spécialistes de l'apprentissage automatique aux particularités des applications informatiques relevant du traitement automatique de la langue (TAL). Il s'agit notamment de pouvoir mettre en oeuvre des nouvelles applications prenant en compte des masses de données complexes et hétérogènes.

La formation se veut pratique et fondamentale. Le but est de former en deux ans des étudiants issus de filières informatiques à un ensemble de techniques d'apprentissage automatique et de traitement automatique de la langue qui sont au coeur des applications en ingénierie des langues (comme en recherche d'information, en aide à la traduction, en analyse d'opinions).

La formation s'inscrit dans une dynamique internationale en s'appuyant sur des personnalités scientifiques reconnues dans leurs domaines de compétences.

Plus d'information sur atal.univ-nantes.fr

jeudi 8 mars 2012

Sélection d'articles de ACL'2011 et EMNLP'2011

Les articles suivant ont été sélectionnés pour leurs accointances avec le traitement automatique du discours.

Le programme de ACL'2011 est disponible à
http://aclweb.org/anthology-new/P/P11/

  • P11-1100 [bib]: Ziheng Lin; Hwee Tou Ng; Min-Yen Kan Automatically Evaluating Text Coherence Using Discourse Relations

et EMNLP'2011 http://aclweb.org/anthology-new/D/D11/

  • D11-1002 [bib]: Li Wang; Marco Lui; Su Nam Kim; Joakim Nivre; Timothy Baldwin Predicting Thread Discourse Structure over Technical Web Forums
  • D11-1015 [bib]: Lanjun Zhou; Binyang Li; Wei Gao; Zhongyu Wei; Kam-Fai Wong Unsupervised Discovery of Discourse Relations for Eliminating Intra-sentence Polarity Ambiguities
  • D11-1028 [bib]: Amit Dubey; Frank Keller; Patrick Sturt A Model of Discourse Predictions in Human Sentence Processing

mercredi 22 février 2012

Listes de diffusion en TAL et disciplines cousines

Ce post sert de complément et de correction à la liste que j'avais constituée des listes de diffusion en Traitement Automatique des Langues (TAL) et disciplines cousines (Ingénierie des connaissances, ingénierie du document, sciences cognitives et linguistiques) : Corpora-list, Elsnet-list, LN, LN-FORUM, RTP-DOC, Info-ic, parislinguists, RISC, Bull-I3, ARTIST, Orbital, Discours, Linguist

RTP-DOC


EGC - extraction et de la gestion de connaissances
  • http://www.egc.asso.fr/13-FR-Liste_de_diffusion

RISC  - relais d'information sur les sciences de la cognition
  • http://www.risc.cnrs.fr 
  • Cette liste est modérée. Pour envoyer un message à la liste. : Pourinfos [ à ] risc.cnrs.fr 

chercheurs_sdl - sciences du langage
  • abonnement https://listes.univ-metz.fr/wws/info/chercheurs_sdl 
  • https://listes.univ-metz.fr/wws/compose_mail/chercheurs_sdl

lundi 16 janvier 2012

Animation des rencontres "Outils et instruments logiciels pour le TAL" au sein de l'équipe TALN

Depuis septembre 2010, j'anime au sein de l'équipe des rencontres "Outils et instruments  logiciels pour le TAL" connues aussi sous le nom de "réunions logiciels".

J'utilise ce post pour rappel du principe et les commentaires pour présenter les différentes interventions qui ont lieu.

La motivation de ces rencontres sont l'échange de connaissances
et l'entraide pour la prise en main d'un nouveau logiciel.

L'objectif pour le présentateur est simple : faire connaître un
logiciel et donner un aperçu de l'utilisation de celui-ci. La présentation prend la forme d'une
démonstration d'un cas d'utilisation. Suivant le logiciel, cela prend
15 à 30 minutes questions comprises.

Il faut prendre logiciel (au sens très large) [2] : cela peut concerner un
développement personnel, une bibliothèque, une application, un analyseur
particulier de données...

Je vous invite à vous proposer pour présenter un logiciel que vous pensez être
pertinent pour l'équipe (même si vous n'en connaissez que quelques fonctions),
ainsi qu'à émettre des demandes de démonstration. Je me propose de
coordonner pour trouver un intervenant dans le cas de demandes. On pourra
discuter plus tard sur les modalités d'ouverture de ces réunions à des
participants hors équipe.

Les rencontres sont au rythme d'une demi-heure tous les mois voire toutes les 6 semaines.
Elles sont planifiées sur l'agenda de l'équipe (aussi consultable en ligne sur [1]).

[1] Agenda des réunions de l'équipe TALN
[2] Instrument, outil, utilitaire et ressource
http://www.revue-texto.net/Corpus/Publications/Habert/Habert_Portrait.html#2.1.

jeudi 5 janvier 2012

Définition d'un descripteur primitif d'Analysis Engine



La dernière étape consister à créer un descripteur indiquant au framework UIMA comment utiliser le composant. En particulier il définit la classe métier de l'Annotator, le Type System manipulé, les Types qui sont utilisés comme input et ceux qui seront des output. C'est aussi ici que sont déclarés les paramètres et les ressources partagées utilisés si il y a lieu.

La création du descripteur du composant est facilitée à travers Eclipse et les plugins installés. Dans le répertoire desc/opinionRecognizer du projet (ou seulement desc si vous n'avez pas packagé votre projet) :
  • Créer le fichier descripteur du composant, opinionRecognizerAE.xml en cliquant dessus avec le bouton droit et New - Other - UIMA - Analysis Engine Descriptor File.
  • Sur la première page (onglet Overview accessible au bas du cadre) spécifier le nom de la classe qui implémente votre code métier (i.e. opinionRecognizer.OpinionRecognizerAE).
  • Sous l'onglet Type System, ajouter (Add) par nom (by name) le type system défini pour votre composant (i.e. desc/opinionRecognizer/opinionRecognizerTS.xml).
  • Enfin sous l'onglet Capabilities, spécifiez les types des annotations qui doivent apparaître en sortie (i.e. SentenceAnnotation, TokenAnnotation et Opinion).
Si en cliquant sur ce fichier pour l'ouvrir, vous n'accédez qu'à son contenu XML, alors demandez d'ouvrir avec le Component Descriptor Editor en cliquant sur le fichier avec le bouton droit.

Implémenter le code métier d'un composant Analysis Engine


La seconde étape correspond au développement du code métier du composant.

Le code métier d'un AE est à minima constitué d'une classe dite Annotator qui étend la classe JCasAnnotator_ImplBase du framework UIMA. En particulier, on trouve le code métier dans une méthode surchargée appelée process qui est automatiquement appelée à l'exécution pour chaque CAS traitée. La méthode process a accès au CAS et via l'API d'UIMA elle peut manipuler l'artifact ou les (index d') annotations qui ont été précédemment ajoutées ou bien en ajouter de nouvelles.

La classe JCasAnnotator_ImplBase est une implémentation par défaut de la classe AnalysisComponent. Cette implémentation par défaut implémente toutes les méthodes exceptée la méthode process. En général on travaille directement à partir de celle-ci quitte à surcharger les méthodes déjà implémentées. 
La classe AnalysisComponent a plusieurs méthodes dont les plus importantes sont initialize, process et collectionProcessComplete. La méthode initialize est appelée une fois par le framework UIMA à la création de la première instance de la classe Annotator ; elle sert par exemple à récupérer la valeur de paramètres ou à charger des ressources qui seront partagées par les différentes instances de la classe. La méthode process est donc appélée une fois par item traité. La méthode collectionProcessComplete est appelée quand l'entière collection a été traitée et sert à produire des résultats relatifs à toute la collection.

Dans cet exercice, vous n'aurez besoin que d'implémenter la méthode process.

Création de la classe Annotator
  1. Dans le répertoire src, créer le package opinionRecognizer.
  2. Au sein du package, créer la classe OpinionRecognizerAE. Par convention les classes Annotator se termineront par le suffixe AE.
  3. Faire étendre la classe de JCasAnnotator_ImplBase
  4. et surcharger la méthode process.
Cela doit donner quelque chose comme :
package opinionRecognizer;
import
org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
import org.apache.uima.jcas.JCas;
import opinionRecognizer.types.*;
public class OpinionRecognizerAE extends JCasAnnotator_ImplBase{
    public void process(JCas aJCas)  {
        // Faire quelque chose
    }
}
Création du code métier au sein de la méthode process

La méthode process reçoit en argument une instance de JCas laquelle constitue le document analysé ainsi que toutes les annotations qui y ont été associées lors d'éventuelles précédentes analyses. Le JCas fournit une approche JNI (Java Native Interface) pour la manipulation des objets CAS et de leur propriétés (i.e.~avec des new, des getter/setter, ... Le framework UIMA se charge de passer le CAS d'un composant à un autre.

Pour cet exercice, l'analyseur devra ajouter une nouvelle annotation Opinion délimitée aux offsets (begin et end) de toutes les phrases SentenceAnnotation contenant des mots TokenAnnotation qui sont des verbes (posTag débutant par "vb" égal à "bez") ou dont la forme de surface coveredText est "we" ou "our". On ajoutera aussi le nombre de mots contenu dans l'opinion length.

L'algorithme que je propose d'implémenter est le suivant :
  1. récupération d'un index de phrases SentenceAnnotation
  2. parcourir l'index de phrases et pour chacune, 
    1. récupérer un sous index de mots TokenAnnotation
    2. parcourir l'index de mots et pour chaque mot
      1. définir un booléen à vrai si un mot a son trait posTag débutant par "vb" égal à "bez"
      2. définir un booléen à vrai si un mot a son trait forme de surface coveredText est "we" ou "our".
      3. incrémenter un compteur de mots
    3. si les deux booléens sont vrais alors
      1. créer une nouvelle annotation Opinion aux offsets (begin et end) de la phrase courante
      2. initialiser les valeurs begin, end et length de cette annotation
La récupération d'un index de phrases SentenceAnnotation peut se réaliser à l'aide de la méthode getAnnotationIndex appliquée au JCas et qui prend en argument le type d'annotation souhaité. Le parcourir de l'index de phrases peut se réaliser à l'aider d'un Iterator
Cela doit donner quelque chose comme :
AnnotationIndex<annotation>  aSentenceAnnotationAnnotationIndex = aJCas.getAnnotationIndex(SentenceAnnotation.type);
Iterator<annotation> aSentenceAnnotationIterator = aSentenceAnnotationAnnotationIndex.iterator(); 
while (aSentenceAnnotationIterator.hasNext()) { 
    SentenceAnnotation aSentenceAnnotation = (SentenceAnnotation) aSentenceAnnotationIterator.next();
    // Faire quelque chose
}
L'ajout du précédent code lève des erreurs de dépendances non importées (AnnotationIndex, Iterator, SentenceAnnotation).  Elles se résolvent très facilement par un left-click sur la petite croix rouge dans la marge de gauche au niveau de chaque erreur détectée et en optant pour le bon import.
Cette action sera à reproduire avec le code à venir.

La récupération d'un index d'annotations couvertes par une autre annotation peut se faire à l'aide de la méthode subiterator qui s'applique sur un index d'annotations et qui prend en argument l'annotation recouvrante.
Elle requiert la création d'un index d'annotations. Pour notre besoin, un index de mots TokenAnnotation peut suffire. Il se construit comme l'index de phrases vu ci-dessus. On décide de récupérer l'index de toutes les annotations pour varier les plaisirs. Il faudra alors ne considérer que les annotations mots qui nous intéressent.
L'instruction suivante réalise cela. On la place au même niveau que la construction d'index de phrases.

AnnotationIndex<annotation> anAnnotationIndex = aJCas.getAnnotationIndex();


A l'intérieur de la boucle, pour chaque phrase on récupère un FSIterator (qui est un iterator un peu spécial sur ce type de structure) sur les annotations couvertes par la phrase courant aSentenceAnnotation.
Cela donne 
FSIterator<annotation> anySubSentenceAnnotationFSIterator = anAnnotationIndex.subiterator(aSentenceAnnotation);
while (anySubSentenceAnnotationFSIterator.hasNext()) {
   Annotation aSubSentenceAnnotation = (Annotation) anySubSentenceAnnotationFSIterator.next();
   // Faire quelque chose
}
Si l'annotation couverte courante aSubSentenceAnnotation est un TokenAnnotation alors on teste si un mot a son trait posTag débutant par "vb" égal à "bez" et si un mot a son trait forme de surface coveredText est "we" ou "our" et l'on compte le mot.
Cela correspond au code ci-dessous

if (aSubSentenceAnnotation.getClass().getName().equalsIgnoreCase("org.apache.uima.TokenAnnotation")) {
    TokenAnnotation aWord = (TokenAnnotation) aSubSentenceAnnotation;
    if (aWord.getPosTag().toLowerCase().startsWith("vb") || aWord.getPosTag().equalsIgnoreCase("bez")) {
        containsAVerb = true;
    }
    if (aWord.getCoveredText().equalsIgnoreCase("our") || aWord.getCoveredText().equalsIgnoreCase("we")) {
        containsAKeyword = true;
    }
    wordCounter++;
}

Pour que ce code fonctionne il faut rajouter quelques déclarations de variables avant la boucle de parcours des annotations couvertes par l'annotation phrase courante.

boolean containsAVerb = false;
boolean containsAKeyword = false;
int wordCounter = 0;
Pour chaque phrase aSentenceAnnotation parcourue on teste si les présences d'un mot clef et d'un verbe sont confirmées. Dans la positive, on créer une nouvelle annotation Opinion. On définit ses traits begin et end en fonction des begin et end de la phrase courante. On définit aussi la longueur length de l'opinion. Et au final on ajoute l'annotation ainsi créée à l'index des annotations à l'aide de la méthode addToIndexes.
Ce qui donne le code suivant :
if ((containsAKeyword) && (containsAVerb)) {    Opinion aOpinion = new Opinion(aJCas);    aOpinion.setBegin(aSentenceAnnotation.getBegin());    aOpinion.setEnd(aSentenceAnnotation.getEnd());    aOpinion.setLength(wordCounter);    aOpinion.addToIndexes();}

Définir les types de données (type system) à manipuler au sein d'un composant UIMA


La première étape pour développer un composant est de définir les types de données qu'il va manipuler. 

Création du descripteur et des types de données à manipuler 

En lien avec notre exercice, nous allons définir le type d'annotation opinionRecognizer.types.Opinion qui correspondra au type des annotations produites par notre composant d'analyse. On lui ajoutera un trait (featurelength qui indiquera le nombre de mots contenu dans l'annotation Opinion courante. Par simplicité nous ne rappellerons pas par la suite le nom de package (opinionRecognizer.types) qui précède le nom du type.

D'abord créons le fichier descripteur :
Les fichiers descripteurs de systèmes de types et d'AE se placent dans le répertoire desc. Pour s'y retrouver ultérieurement parmi les descripteurs qui seront disponibles dans le CLASSPATH, je vous conseille de créer un sous répertoire portant le nom de votre projet (en respectant les conventions de nommage Java), par exemple ici : opinionRecognizer.
  1. Faire un clic-droit sur le répertoire desc (ou sur le sous-répertoire que vous venez de créer si vous avez suivi mon conseil).
  2. Choisir le menu 'New'-'Other...'-'UIMA'-'Type System Descriptor File'.
  3. A l'écran suivant, donner un nom au fichier descripteur de types par exemple opinionRecognizerTS.xml. Là encore par convention et pour s'y retrouver plus tard je vous conseille d'utiliser le suffixe TS pour vos noms de fichier descripteur de systèmes de types.
Ensuite, une fois le fichier créé, ajoutons le type désiré  opinionRecognizer.types.Opinion : 
  1. Dans l'onglet Type System du descripteur, ajouter un type avec le bouton Add Type.
  2. Donner lui le nom de opinionRecognizer.types.Opinion
  3. Le faire hériter du type uima.tcas.Annotation défini par le framework UIMA et qui permet d'hériter des traits beginend et coveredText. Le trait coveredText est un trait un peu particulier parce que l'on ne peut y accéder qu'en lecture. Il retourne le texte de l'artifact couvert entre les offsets délimités par les valeurs entières begin et end.
Ajoutons aussi une feature au type :
  1. En sélectionnant le type, cliquer sur le bouton Add...
  2. Donner lui le nom de length qui indiquera le nombre de mots contenu
  3. Faire hériter du type simple Integer.
Puisque nous manipulons aussi les types mot, org.apache.uima.TokenAnnotation, et phrase, org.apache.uima.SentenceAnnotation, qui sont des uima.tcas.Annotation et le trait posTag (String) du type TokenAnnotation dont les annotations auront été produits par les composants de prétraitement, il nous faut aussi ajouter ces types. Le faire.

Génération automatique des l'API JAVA du système de types

Une fois le fichier de descripteur de systèmes de type créé et sauvé, une API java permettant de manipuler les types (et les traits) est automatiquement générée. 

Si jamais vous craignez que cette API ne soit pas générer ou que vous vouliez forcer sa re-génération, cliquer sur le bouton JCasGen présent dans l'éditeur du fichier Système de Type.

Les fichiers Opinion.java et Opinion_Type.java sont générés dans le sous répertoire  opinionRecognizer.types du répertoire src du projet. 
Le fichier  Opinion.java  contient le constructeur de type. Noter la présence d'accesseurs pour modifier la valeur des attributs du type Opinion (par exemple les méthodes getLength() et  setLength(int v)).

mercredi 4 janvier 2012

Développer son premier composant UIMA : l'Analysis Engine (AE)

Objectifs 
Ce post présente ce qu'est le composant élémentaire de toute chaîne de traitement d'analyse UIMA à savoir l'Analysis Engine (AE). Il explique de quoi il se compose techniquement, et comment développer ses différentes parties.
Il s'agit entre autres de prendre en main l'API et les outils UIMA pour réaliser des opérations classiques : telles que définir des types d'annotation, générer automatiquement l'API pour manipuler les types d'annotations définis, récupérer des annotations posées par d'autres annotateurs, consulter et définir les valeurs de traits d'une annotation, créer une nouvelle annotation, créer un fichier XML descripteur et tester un composant.
Pour illustrer cet exercice de développement on cherchera à développer la fonction de reconnaissance de phrases qui expriment une opinion. On posera l'hypothèse qu'une phrase qui contient des verbes et des mots dont la forme de surface comme "we" ou "our" est une expression d'opinion... On utilisera pour cela quelques AE disponibles dans les Apache Uima Addons. On testera l'AE sur les textes présents dans le répertoire UIMA_HOME/examples/data notamment Apache_UIMA.txt. De fait nous travaillerons sur l'anglais pour cet exercice.


Prérequis

Il est nécessaire d'avoir réaliser les tutoriels suivant :
Tel que l'explique ces précédents posts, il faudra avoir au préalable construit et avoir à disposition une chaîne que nous appellerons de pré-traitement et qui sera composée des Apache UIMA addons suivant : 
  • WhiteSpaceTokenizer qui découpe en mots, TokenAnnotation, et phrases, SentenceAnnotation, un texte fourni en entrée
  • Tagger qui rajoute un trait posTag aux TokenAnnotation
Qu'est ce qu'un composant UIMA de type Analysis Engine et à quoi cela sert ?
Un Analysis Engine (AE) est le composant élémentaire d'une chaîne de traitements UIMA. Il a généralement pour objet une tâche d'analyse (par exemple reconnaître si une phrase est une expression d'une opinion) sur ce que l'on appelle un artifact (par exemple un texte). Il reçoit les résultats d'analyse de précédents composants (par exemple un découpage en phrases, en mots, la reconnaissance des étiquettes grammaticales (nom, verbe, adjectif...)) qui lui servent de base pour ses traitements afin qu'il puisse à son tour associer à l'artifact le résultat d'analyse qu'il produit (par exemple les opinions). On appelle les résultats d'analyse, des meta-données ou des annotations. L'ensemble formé par l'artifact et les méta-données constitue la structure commune d'analyse (CAS ou Common Analysis Structure) et est LA structure de donnée qui transite d'un composant à un autre.

De quoi est constitué un composant UIMA ?
Un composant UIMA est logiquement constitué de trois éléments :
  • la définition des types des données que le composant manipule (lit et crée), on appelle cela le système de types (TS ou type system),
  • le code métier qui réalise la fonction souhaitée,
  • un descripteur indiquant au framework UIMA comment utiliser le composant.
Le système de types et le descripteur du composant sont des fichiers XML que l'on peut éditer avec des interfaces graphiques via les plugins Eclipse de UIMA. La définition du système de type entraîne la génération automatique d'une API pour manipuler les types de données définis au sein du code métier.

L'ensemble de ces éléments doit se trouver accessible via le CLASSPATH de l'application qui exécute. En général, on encapsule ces éléments au sein d'une même archive Jar.

Préparer un projet Java sous Eclipse pour accueillir le développement de votre composant

Il vous faut un projet Java sous Eclipse pour accueillir le développement de votre composant. Différentes options : 
  • vous pouvez utiliser celui précédemment créé pour la chaîne de prétraitement 
  • ou bien vous créez un nouveau projet comme indiquer ici mais il vous faudra alors déclarer une dépendance vers soit le projet qui contient votre chaîne de prétraitement soit vers le jar que vous aurez exporté à partir de celle-ci. Pour déclarer la dépendance au projet, Click droit sur le projet, Build path, Configure build path, Onglet Projects, Add les projets, Ok, OK...

Exécuter votre AE au sein d'un Aggregate

Au sein du répertoire desc/opinionRecognizer créer un descripteur aggregate qui ajoute en pipeline le descripteur de pretraitement et le descripteur de votre AE. N'oubliez pas de changer les capabilities.
Et exécutez le.


Pour aller plus loin
  • la création et la récupération de vues,
  • la définition des paramètres au sein du descripteur et leur accès au sein du code, 
  • la déclaration et la manipulation de ressources partagées par plusieurs instances d'un même AE,
  • le parcours d'index d'annotations à l'aide de contraintes
Remerciement
Le contenu décrit sur cette page s'inspire, adapte, étend le support créé pour le tutoriel qui a eu lieu à UIMA@RMLL'09 ainsi que le tutoriel Getting started de la documentation d'Apache UIMA.
Je vous invite à consulter ces différentes sources pour des informations complémentaires