Affichage des articles dont le libellé est interoperability. Afficher tous les articles
Affichage des articles dont le libellé est interoperability. Afficher tous les articles

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.



samedi 10 décembre 2011

Mise en correspondance de vues via un Aggregate pour interconnecter des composants UIMA (view et sofa name mapping)

Après avoir rappelé quelques notions (que le lecteur averti peut ne pas lire), le post expose brièvement le problème et présente avec un exemple la mise en oeuvre d'une solution de mise en correspondance de vues au sein d'un Aggregate.

Bref rappel de quelques notions
Les chapitres 5 et 6 de la documentation UIMA tutorials_and_users_guides [1;2] rappellent les définitions des notions d'Artifact, Sofa et View.
Brièvement l'Artifact est la chose non structurée que l'on souhaite analyser. Le Sofa (Subject of Analysis) est une représentation de l'Artifact (e.g. HTML). Une annotation metadata est de l'information associée à un Sofa particulier pour en décrire une sous région. La notion de View simplifie les choses quand plusieurs versions de l'Artifact sont nécessaire à différentes étapes de l'analyse (e.g. une version sans balise d'un document XML). Les notions de Sofa et de CAS View sont liées. Dans l'implémentation Apache actuelle (2.4), à chaque Sofa est associé une seule View et à chaque View un seul Sofa. Le nom qui désigne une vue particulière est Sofa name pour des raisons historiques mais cela s'applique indifféremment à View aussi.
L'analyse d'un composant UIMA (AE - Analysis Engine) porte toujours sur une vue. Il peut y en avoir plusieurs. L'AE peut en créer. Les résultats d'analyse peuvent être associés sur les vues traitées ou bien sur les vues créées.
Un AE qui travaille seulement sur une seule vue est appelée "single-view component" et dans le cas contraire "multi-view/multi-sofa component".
Par défaut, si rien n'est spécifié il y a qu'une seule view et celle-ci a le sofa name de "_InitialView".

Problème d'interopérabilité pour interconnecter des composants développés indépendamment
Le développeur d'AE est libre de choisir le nom qu'il souhaite pour désigner ses vues d'entrée et ses vues de sortie.
Cela conduit naturellement à quelques petits soucis lorsque l'on veut interconnecter des composants ayant des noms de vue différents.

Le mécanisme de mise en correspondance des vues au niveau d'un Aggregate
La section 6.4 de la documentation explique et présente différentes situations de mises en correspondance : au sein d'un Aggregate, d'un CPE, d'une application UIMA, pour des services distants. Je rapporte et illustre la solution au sein d'un AE Aggregate.

Pour cela, j'utilise deux composants : l'XmlDetagger présent dans les exemples fournis avec Apache UIMA [4] et le Whitespace Tokenizer des addons de la Sandbox d'Apache UIMA [5].

L'XmlDetagger est un composant multiple vues qui retire les balises d'un document XML. Il lit l'XML d'une vue input nommée "xmlDocument". Le contenu textuel est écrit dans une nouvelle vue output appelée "plainTextDocument".
Le Whitespace Tokenizer est un composant simple vue qui travaille sur la vue par défaut (i.e.  "_InitialView") et qui ajoute à celle-ci des annotations de phrases et de tokens.

Rapidement, je mets en place un projet Java sous Eclipse. J'y ajoute la UIMA Nature, déclare les répertoires desc et resources dans le build path ainsi que les bibliothèques de UIMA [6]. Je rajoute au  le build path les bibliothèques uima-examples [10] et addon whitespace tokenizer [9] qui vont servir pour notre chaîne.

Je crée un descripteur d'AE Aggregate [7] et j'y ajoute by name en pipeline : d'abord l'XmlDetagger  puis le Whitespace Tokenizer (je déclare les bons types à produire en output dans les capabilities).

A la sauvegarde le message suivant s'affiche
Error in AE Descriptor
The Descriptor is invalid for the following reason:
ResourceInitializationException: The output Sofa "plainTextDocument" in component "XmlDetagger" is not mapped to any output Sofa in its containing aggregate, "demoSofaNameMappingAAE". (Descriptor path ...) 

Ce n'est pas réellement une erreur si l'on sait ce que l'on fait. Une vue qui n'est pas utilisée par exemple n'a pas besoin d'être mise en correspondance dans l'Aggregate.
En l'état si on exécute cet AE avec le DocumentAnalyzer [8] sur un document XML quelconque, on obtiendra l'erreur suivante :
org.apache.uima.analysis_engine.AnalysisEngineProcessException: Annotator processing failed. Caused by: org.apache.uima.cas.CASRuntimeException: No sofaFS with name xmlDocument found. 
Vraissemblablement ici il y a des vues qui requièrent d'être mise en correspondance et cela va se faire au niveau de l'Aggregate.

La première chose à faire est d'indiquer que la vue sur laquelle travaille en entrée XmlDetagger, à savoir xmlDocument, correspond à _InitialView dans l'Aggregate. Autrement dit, la vue d'entrée par défaut de l'Aggregate,  _InitialView, doit être mise en correspondance avec la vue d'entrée, xmlDocument, de l'XmlDetagger.
Au sein du descripteur de l'Aggregate, c'est dans la section capabilities que l'on déclare les vues sur lesquelles on travaille (sous section component capabilities) et celles entre lesquelles on réalise des mises en correspondance (sous section sofaMappings).
On ajoute d'abord la vue xmlDocument comme input (entrée) en faisant un add sofa dans la component capabilities.
Ensuite on indique dans la sous section sofaMappings que pour le composant (componentKeyXmlDetagger sa vue (componentSofaNamexmlDocument correspond à la vue dans l'aggregate (aggregateSofaName_InitialView.
Par les éléments componentKey et componentSofaName on désigne le composant et la vue souhaitée chez celui-ci comme devant intervenir dans un mapping. L'élément aggregateSofaName est la clé partagée entre les éléments sofaMapping.
Cette dernière opération doit se faire pour partie à la main en éditant le source (personnellement je n'y arrive pas via l'éditeur du formulaire). Cela donne
<capability>
...
  <inputSofas>
    <sofaName>xmlDocument</sofaName>
  </inputSofas>
  ...
et
  <sofaMappings>
    <sofaMapping>
      <componentKey>XmlDetagger</componentKey>
      <componentSofaName>xmlDocument</componentSofaName>
      <aggregateSofaName>_InitialView</aggregateSofaName>
    </sofaMapping>
  </sofaMappings>
Si on réexécute l'AE on se rend compte que ce n'est pas encore l'idéal car le Whitespace Tokenizer travaille sur l'_InitialView par défaut et traite donc ce qui correspond à l'xmlDocument au lieu du plainTextDocument.
On rajoute dans l'élément inputSofas
<sofaName>_InitialView</sofaName>
et l'élément suivant
  <sofaMapping>
      <componentKey>WhitespaceTokenizer</componentKey>
      <componentSofaName>_InitialView</componentSofaName>
      <aggregateSofaName>plainTextDocument</aggregateSofaName>
    </sofaMapping>
La vue plainTextDocument du XmlDetagger n'a pas été redéfinie dans l'Aggregate, il n'y a pas d'ambiguité. Ce que produit le XmlDetagger au sein de sa vue output plainTextDocument est accessible sous ce même nom au sein de l'Aggregate qui le met en correspondance avec la vue input du
WhitespaceTokenizer.   
L'exécution fonctionne comme attendu finalement.  

Quelques commentaires supplémentaires

Au niveau de l'Aggregate après mise en correspondance, le nom de la vue du componentSofaName
sera renommé en le nom de la vue déclarée dans aggregateSofaName.
Les vues avec leur nom précédent ne seront plus accessibles. Une fois sérialisée en XMI, on constatera sela en cherchant la valeur de l'attribut sofaID.
Les composants d'Apache OpenNLP sont des composants multiples vues et requièrent en général l'usage de mises en correspondance.


Liens

[1] 5. Annotations, Artifacts & Sofas
[2] 6. Multiple CAS Views
[3] 6.4. Sofa Name Mapping
[4] UIMA_HOME/examples/descriptors/analysis_engine/XmlDetagger.xml
[5] http://uima.apache.org/sandbox.html#whitespace.tokenizer
[6] Créer un projet Eclipse pour le développement d'un composant UIMA
[7] Construire une chaîne de traitement UIMA à partir de composants existants
[8] Exécuter un traitement ou une chaîne de traitement sous UIMA (avec UIMAJ et en local)
[9] UIMA_HOME/addons/annotator/WhitespaceTokenizer/lib/uima-an-wst.jar
[10] UIMA_HOME/lib/uima-examples.jar

dimanche 3 octobre 2010

UIMA Type mapping

Lorsque l'on souhaite développer un composant à l'aide de l'architecture Apache UIMA, celle-ci requiert de définir les types d'information que l'on souhaite manipuler ainsi que leur organisation ; on appelle cela définir son système de types. D'un point de vue conception de logiciel, cela permet notamment de réaliser un contrôle syntaxique des entrées et des sorties des composants.

Apache UIMA offre la liberté de définir son propre système de types et par conséquent plusieurs systèmes de types peuvent être proposés pour modéliser les mêmes informations. Cette liberté de définition de systèmes de types peut donc conduire à des problèmes d'interopérabilité entre des composants manipulant des informations conceptuellement identiques mais étant en pratique définies par des modélisations distinctes.
Par exemple, wordmot voire token sont des noms différents qui peuvent éventuellement être utilisés pour désigner le même type d'information.

Le uima-type-mapper est un composant qui offre un moyen de conversion d'annotations définies par un système de type donné (appelé type source) vers des annotations définies par un autre système de types (appelés types cibles). En pratique, il permet de faire le pont entre des composants manipulant des annotations ayant des types d'information conceptuellement identiques mais de noms distincts. Les annotations produites par un premier composant peuvent être utilisées en entrée d'un second via notre composant qui réalise la conversion.

Les conversions sont déclarées à l'aide de règles qui spécifient pour des types source donnés de réaliser une opération de création d'une ou plusieurs annotations de types cible aux offsets des annotations de type source rencontrées. Il est possible de spécifier des contraintes sur les caractéristiques de annotations de type source. La cohérence sémantique des types à convertir est laissée libre à l'utilisateur.
En pratique, l'implémentation repose sur
  • W3C XPath comme langage déclaratif d'expression des contraintes sur la structure des types des annotations source
  • Apache JXPath comme moteur qui implémente le traitement des règles
  • java.lang.reflect API pour rendre générique le composant en autorisant la désignation de tout type héritant de uima.tcas.Annotation pour faire l'objet de conversion
La fonction de spécification de contraintes sur les annotations à convertir peut conduire à utiliser ce composant comme un composant d'analyse à base de règles des structures sémantiques UIMA. En effet, le composant peut être utilisé pour réaliser de la reconnaissance de motifs d'annotations au sein d'une structure d'annotations UIMA et de la réalisation d'opérations sur les(/relativement aux) motifs reconnus telles que la création d'annotations, la mise à jour d'annotations, et la suppression d'annotations. Actuellement seule la première opération est gérée, mais les fonctions déjà implémentées dans le composant en font de lui une preuve de concept.

Si vous utilisez ce travail dans vos travaux de recherche, merci de citer l'article suivant 


Nicolas Hernandez, Fabien Poulard, Matthieu Vernier, Jérôme Rocheteau, "Building a French-speaking community around UIMA, gathering research, education and industrial partners, mainly in Natural Language Processing and Speech Recognizing domains", LREC 2010 Workshop 'New Challenges for NLP Frameworks', La Valleta : Malta 
Le code source du composant disponible sur http://code.google.com/p/uima-type-mapper/