Categorías
OpenNLP

Tutorial de OpenNLP

La biblioteca Apache OpenNLP es un juego de herramientas basado en aprendizaje automático para el procesamiento de texto en lenguaje natural. Incluye un detector de oraciones, un tokenizador, un buscador de nombres, un etiquetador de partes del discurso (POS), un fragmento y un analizador. Tiene muy buenas API que se pueden integrar fácilmente con un programa Java. Sin embargo, la documentación contiene información no actualizada.

En este tutorial, le mostraré cómo usar Apache OpenNLP a través de un conjunto de ejemplos simples.

0. Descargar archivos Jar y configurar el entorno

Antes de comenzar con los ejemplos, debe descargar los archivos jar necesarios y agregarlos a la ruta de compilación de su proyecto. Los archivos jar necesarios se encuentran en «apache-opennlp-1.5.3-bin.zip» que se puede descargar aquí.

Accedido en marzo de 2014, la página de descarga tiene el siguiente aspecto:

Descomprima el archivo .zip y copie los 4 archivos jar en el directorio «lib» a su proyecto. Además, necesitará descargar algunos archivos de modelo más adelante en función de lo que desee hacer (que se muestra en los ejemplos a continuación), que se pueden descargar aquí.

1. Detector de frases

El detector de oraciones sirve para detectar los límites de las oraciones. Dado el siguiente párrafo:

Hi. How are you? This is Mike.

El detector de oraciones devuelve una matriz de cadenas. En este caso, la matriz tiene dos elementos como se muestra a continuación.

Hi. How are you? 
This is Mike.

Código de ejemplo:

public static void SentenceDetect() throws InvalidFormatException,
		IOException {
	String paragraph = "Hi. How are you? This is Mike.";
 
	// always start with a model, a model is learned from training data
	InputStream is = new FileInputStream("en-sent.bin");
	SentenceModel model = new SentenceModel(is);
	SentenceDetectorME sdetector = new SentenceDetectorME(model);
 
	String sentences[] = sdetector.sentDetect(paragraph);
 
	System.out.println(sentences[0]);
	System.out.println(sentences[1]);
	is.close();
}

2. Tokenizer

Los tokens suelen ser palabras separadas por espacios, pero hay excepciones. Por ejemplo, «no es» se divide en «es» y «n’t, ya que es un formato breve de» no es «. Nuestra oración se divide en los siguientes tokens:

Hi
.
How
are
you
?
This
is
Mike
.

Código de ejemplo:

public static void Tokenize() throws InvalidFormatException, IOException {
	InputStream is = new FileInputStream("en-token.bin");
 
	TokenizerModel model = new TokenizerModel(is);
 
	Tokenizer tokenizer = new TokenizerME(model);
 
	String tokens[] = tokenizer.tokenize("Hi. How are you? This is Mike.");
 
	for (String a : tokens)
		System.out.println(a);
 
	is.close();
}

3. Buscador de nombres

Por su nombre, el buscador de nombres solo busca nombres en el contexto. Consulte el siguiente ejemplo para ver qué puede hacer el buscador de nombres. Acepta una matriz de cadenas y encuentra los nombres en su interior.

Código de ejemplo:

public static void findName() throws IOException {
	InputStream is = new FileInputStream("en-ner-person.bin");
 
	TokenNameFinderModel model = new TokenNameFinderModel(is);
	is.close();
 
	NameFinderME nameFinder = new NameFinderME(model);
 
	String []sentence = new String[]{
		    "Mike",
		    "Smith",
		    "is",
		    "a",
		    "good",
		    "person"
		    };
 
		Span nameSpans[] = nameFinder.find(sentence);
 
		for(Span s: nameSpans)
			System.out.println(s.toString());			
}

4. Etiquetador POS

Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NNP

Código de ejemplo:

public static void POSTag() throws IOException {
	POSModel model = new POSModelLoader()	
		.load(new File("en-pos-maxent.bin"));
	PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
	POSTaggerME tagger = new POSTaggerME(model);
 
	String input = "Hi. How are you? This is Mike.";
	ObjectStream<String> lineStream = new PlainTextByLineStream(
			new StringReader(input));
 
	perfMon.start();
	String line;
	while ((line = lineStream.read()) != null) {
 
		String whitespaceTokenizerLine[] = WhitespaceTokenizer.INSTANCE
				.tokenize(line);
		String[] tags = tagger.tag(whitespaceTokenizerLine);
 
		POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
		System.out.println(sample.toString());
 
		perfMon.incrementCounter();
	}
	perfMon.stopAndPrintFinalResult();
}

5. Chunker

Es posible que Chunker no sea una preocupación para algunos usuarios, pero vale la pena mencionarlo aquí. Lo que hace chunker es dividir una oración en un conjunto de fragmentos utilizando los tokens generados por tokenizer.
No tengo un buen ejemplo para mostrar por qué chunker es muy útil, pero puede reemplazar la oración con sus propias oraciones en el siguiente código de ejemplo e intentar generar algo que le guste.

Código de ejemplo:

public static void chunk() throws IOException {
	POSModel model = new POSModelLoader()
			.load(new File("en-pos-maxent.bin"));
	PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
	POSTaggerME tagger = new POSTaggerME(model);
 
	String input = "Hi. How are you? This is Mike.";
	ObjectStream<String> lineStream = new PlainTextByLineStream(
			new StringReader(input));
 
	perfMon.start();
	String line;
	String whitespaceTokenizerLine[] = null;
 
	String[] tags = null;
	while ((line = lineStream.read()) != null) {
		whitespaceTokenizerLine = WhitespaceTokenizer.INSTANCE
				.tokenize(line);
		tags = tagger.tag(whitespaceTokenizerLine);
 
		POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
		System.out.println(sample.toString());
			perfMon.incrementCounter();
	}
	perfMon.stopAndPrintFinalResult();
 
	// chunker
	InputStream is = new FileInputStream("en-chunker.bin");
	ChunkerModel cModel = new ChunkerModel(is);
 
	ChunkerME chunkerME = new ChunkerME(cModel);
	String result[] = chunkerME.chunk(whitespaceTokenizerLine, tags);
 
	for (String s : result)
		System.out.println(s);
 
	Span[] span = chunkerME.chunkAsSpans(whitespaceTokenizerLine, tags);
	for (Span s : span)
		System.out.println(s.toString());
}

6. Analizador

Dada esta oración: «Programcreek es un sitio web muy grande y útil», el analizador puede devolver lo siguiente:

Código de ejemplo:

public static void Parse() throws InvalidFormatException, IOException {
	// http://sourceforge.net/apps/mediawiki/opennlp/index.php?title=Parser#Training_Tool
	InputStream is = new FileInputStream("en-parser-chunking.bin");
 
	ParserModel model = new ParserModel(is);
 
	Parser parser = ParserFactory.create(model);
 
	String sentence = "Programcreek is a very huge and useful website.";
	Parse topParses[] = ParserTool.parseLine(sentence, parser, 1);
 
	for (Parse p : topParses)
		p.show();
 
	is.close();
 
	/*
	 * (TOP (S (NP (NN Programcreek) ) (VP (VBZ is) (NP (DT a) (ADJP (RB
	 * very) (JJ huge) (CC and) (JJ useful) ) ) ) (. website.) ) )
	 */
}

Referencias:
Aunque la documentación no es buena, parte del sitio oficial de OpenNLP sigue siendo útil.
wiki: http://sourceforge.net/apps/mediawiki/opennlp/index.php?title=Main_Page
Documento de Java: http://opennlp.apache.org/documentation/1.5.2-incubating/apidocs/opennlp-tools/index.html