mercredi 11 septembre 2013

Installer Apache UIMA Java (environnement d'exécution et de développement)

Il existe 3 implémentations concurrentes d'UIMA

  • UIMA Java (uimaj) (à préférer pour les débutants)
  • UIMA-AS (implémentation java à privilégier pour de l'asynchronous scaleout)
  • UIMA CPP (à préférer pour développer autrement qu'en Java)
Les outils Eclipse ne sont pas indispensables mais facilitent une activité de développement.

Installation le framework Apache UIMA Java et ses outils de développements

  1. Télécharger une archive d'un binaire de "UIMA Java framework & SDK" dans la section de téléchargement de UIMA (contient le nécessaire pour exécuter et développer des composants, des workflows et des applications UIMA en java)
  2. Désarchiver dans le répertoire d'installation de votre choix
  3. Fixer les variables d'environnement. Pour cela je suis les consignes du fichier README présent dans l'archive.
    1. Set JAVA_HOME to the directory of your JRE installation you would like to use for UIMA.
    2. Set UIMA_HOME to the apache-uima directory of your unpacked Apache UIMA distribution
      • export UIMA_HOME=/my/applications/apache-uimaj
    3. Afin d'exécuter les outils UIMA en ligne de commande, ajouter UIMA_HOME/bin to your PATH 
      • export PATH=${UIMA_HOME}/bin:$PATH
    4. Facultatif : afin de faciliter la configuration ultérieure des exemples, ajuster les exemples à votre répertoire d'installation (via l'exécution du script UIMA_HOME/bin/adjustExamplePaths.sh)
  4. Facultatif : Un test d'installation Afin de réaliser ce test consulter la page "Comment exécuter des chaînes de traitement avec UIMA " notamment la section "Exécution d'une chaîne de traitement en ligne de commande".

Installer les outils Eclipse pour assister le développement (via plugins)

  1. Indiquer à Eclipse, le site où récupérer des plugins liés à UIMA 
    • Help > "Software updates | Install New software" > Add 
    • Name : "Apache UIMA" ; URL http://www.apache.org/dist/uima/eclipse-update-site
  2. Indiquer lui ensuite le site avec lequel vous voulez travailler. Attendez quelques instants et le système vous proposera une liste proche de celle-ci
    • Apache UIMA Eclipse tooling 
    • Apache UIMA Ruta 
    • Apache UIMA-AS (Asynchronous Scaleout) Eclipse tooling
  3. Cocher les plugins que vous voulez ajouter puis "Next". Certains peuvent ne pas vouloir s'installer. Les Eclipse tooling sont la priorité. UIMA-AS tooling seulement si vous voulez faire du AS. Ruta si vous savez que vous voulez faire du Ruta.
    • Si vous rencontrez des problèmes : Commence une étape de résolution de dépendances, il est possible qu'il faille cocher plus de sites afin de permettre cette résolution, il est possible qu'il faille faire des install un à un des sites, et il est possible qu'il faille commencer par ceux natifs d'eclipse. Quelques refresh.
  4. Accept the licence
  5. Il se peut qu'il vous signale que vous voulez installer un "Unsigned content", accepter...

Configurer son environnement au sein d'Eclipse


  1. Définir la variable UIMA_HOME au sein d'Eclipse
    • Cliquer onglet Window > Preferences > Java > Build Path > Classpath Variables > Faire New (Name: UIMA_HOME et Path: Folder... > vers "applications/apache-uima") > Ok > Ok > Yes (rebuild)
  2. Importer le répertoire de codes exemples UIMA_HOME/examples au sein d'Eclipse
    • Cliquer onglet File > Import ; Sélectionner "General/Existing Project into Workspace" ; Cliquer "Next" ; Cliquer "Browse" et naviguer jusqu'au répertoire UIMA_HOME
  3. Facultatif : Un test d'installation au sein d'Eclipse Afin de réaliser ce test consulter la page "Comment exécuter des chaînes de traitement avec UIMA " notamment la section "Exécuter une chaîne de traitement au sein d'Eclipse". 

Installer les composants et les outils tiers présents dans la sandbox d'UIMA (addons et tools)


Références



Liens externes 

jeudi 13 juin 2013

Toward a Free French Treebank


One of my current objective is to develop a Free French treebank allowing to train statistical systems on common NLP tasks such as text segmentation, morphological analysis, chunking, parsing...
As part of this project, in [2] we show a way of doing it.

Download

Here you can download the current version of the Free French Treebank [0].

Licence 


The resource (i.e. annotations) is distributed under the terms of this Lesser General
Public License for Linguistic Resources (LGLP-LR) [1].
This means you can use it in the context you want, you can modify it, and
distribute it as long as you do the same with your contribution.
If you use this project to support academic research, then please cite the
following paper as appropriate [2].


Notes on the current release


The current version is based on the  frwikinews-20130110 articles dump [3].
It has 28000 news articles covering a period from January 2005 to now.
After filtering of sentences with less than 5 tokens the version has 87461
sentences and 2535396 tokens. Texts are available under Creative Commons
Attribution 2.5 (CC-BY 2.5) licence. Prior versions from September 2005 are in
public domain. The text format have been cleaned up by using a Java Wikipedia
 API  [4], then tokenized using a rule-/dictionary-based tokenizer [5], then
POS tagged by the Stanford tagger [6].
The resource contains
  * xml-bz2 XML source archive
  * txt raw text
  * txt-tok a sentence per line and whitespace-separated words
  * txt-tok-pos a pos tag is associated with each word and is separated from this one with an underscore


References


[0] https://docs.google.com/forms/d/1fSiEaAPeq3S4tF1P1vuWJXuDvMUMQvnQILP2b-58m7k/viewform
[1] http://infolingu.univ-mlv.fr/lgpllr.html
[2] @inproceedings{hernandez:2013:taln,
    title = {{Construction automatique d'un large corpus libre annot{\'e} morpho-syntaxiquement en fran{\c c}ais}},
    author = {Hernandez, Nicolas and Boudin, Florian},
    abstract = {{Cet article {\'e}tudie la possibilit{\'e} de cr{\'e}er un nouveau corpus {\'e}crit en fran{\c c}ais annot{\'e} morpho-syntaxiquement {\`a} partir d'un corpus annot{\'e} existant. Nos objectifs sont de se lib{\'e}rer de la licence d'exploitation contraignante du corpus d'origine et d'obtenir une modernisation perp{\'e}tuelle des textes. Nous montrons qu'un corpus pr{\'e}-annot{\'e} automatiquement peut permettre d'entra{\^\i}ner un {\'e}tiqueteur produisant des performances {\'e}tat-de-l'art, si ce corpus est suffisamment grand.}},
    language = {Fran{\c c}ais},
    affiliation = {Laboratoire d'Informatique de Nantes Atlantique - LINA},
    booktitle = {{Actes de la conf{\'e}rence TALN-RECITAL 2013}},
    address = {Sables d'Olonne, France},
    audience = {nationale },
    year = {2013},
    month = Jun,
    pdf = {http://hal.archives-ouvertes.fr/hal-00816350/PDF/TALN13.pdf},
}



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.