Lucene: Analyzers, stemming y búsqueda de documentos similares.

0
21109

Lucene: Analyzers, stemming y búsqueda de
documentos similares.

0. Índice de contenidos.

1. Introducción

Lucene
es un api para la recuperación de
información, Information Retrieval (IR), distribuido bajo
la Apache Software License.

Encaja perfectamente en el concepto de gestión
documental (DMS) e incluso en la gestión de
contenidos (CMS), puesto que un
sistema de gestión documental requiere
de la extracción del contenido de los documentos, la
indexación de los mismos en un repositorio y la posibilidad
de recuperarlos realizando búsquedas por su contenido textual.

No penséis en un sistema de
gestión documental como en la mega-aplicación
construida única y exclusivamente como «contenedor de documentos»
para vuestra organización, cualquier aplicación tiene algo
de gestión de documentos. Y, si tenemos en cuenta que buena parte del existo de esa
gestión radicará en la capacidad de recuperar la
información que se cataloga, después de leer este
tutorial pensarás que Lucene debe formar parte de tu vida…
😀

Ya dimos, de la mano de Roberto Canales,
los
primeros pasos con Lucene en java,

instalándolo, creando un
índice, extrayendo el contenido de un pdf,
indexándolo y recuperando
la información del mismo.

En este tutorial vamos a ver cómo implementar un
analizador semántico en nuestro idioma, potenciando
la indexación y búsqueda, para terminar
analizando la viabilidad de realizar búsquedas de documentos
similares.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Asus G1 (Core 2 Duo a 2.1
    GHz, 2048 MB RAM, 120 GB HD).
  • Sistema Operativo: GNU / Linux, Debian (unstable), Kernel
    2.6.23, KDE 3.5
  • JDK 1.5.0_14
  • Eclipse Europa 3.3
  • Lucene 2.2.0

3. Consideraciones previas.

Para la indexación y recuperación del contenido
textual de los documentos que gestionamos nos bastaría con
utilizar alguno de los analizadores que proporciona por defecto Lucene,
pero si queremos potenciar las búsquedas de modo que no se
produzca demasiado ruido en el resultado y para cumplir el
objetivo de buscar documentos similares, tenemos que conseguir que los
documentos pasen por un filtro lo más exhaustivo posible.

Podemos conseguirlo implementando los siguientes conceptos:

  • stopwords:
    son una lista de palabras de uso frecuente que, tanto en la
    indexación como
    en la búsqueda, no se tienen en consideración, se
    omiten. 
  • stemming:
    es un método para obtener la raíz
    semántica
    de una palabra. Las palabras se reducen a su raíz o stem
    (tema), de modo
    que, si buscamos por “abandonados”
    encontrará
    “abandonados” pero también
    “abandonadas”,
    “abandonamos”, … porque, en realidad, estamos
    buscando por
    “abandon”.
  • modelo de
    espacio vectorial
    : es un modelo algebraico utilizado para
    filtrar, indexar, recuperar
    y calcular la relevancia de la información. Representa los
    documentos con un lenguaje natural mediante
    el uso
    de vectores en un espacio lineal multidimensional. La relevancia de un
    documento frente a una búsqueda puede calcularse
    usando la diferencia de ángulos de cada uno de los
    documentos respecto del vector de busca, utilizando
    el producto escalar entre el vector de búsqueda.

A priori parece complejo, pero lo que cuesta es comprenderlo, vamos a
ver cómo Lucene nos va a facilitar mucho la vida. Lo costoso
que resulte implementarlo en tus desarrollos, eso solo lo sabes
tú, aunque sino te haces una idea de ello… siempre nos
puedes llamar para analizarlo y, en su caso, desarrollarlo.

A continuación, las dependencias que tendrá
el proyecto en nuestro pom.xml, si no usáis maven,
serán las librerías a importar manualmente:

4. SpanishAnalyzer.

Lucene provee varios analizadores por defecto, el StandardAnalyzer con
un listado reducido de
stopwords en inglés y podemos obtener una
librería (lucene-analyzers) con analizadores en bastantes
idiomas… casi todos menos en Castellano… 🙁

Aún teniendo un analizador en el idioma requerido, la
recomendación es que construyáis el vuestro
propio para aumentar el listado de stopwords, si fuese necesario, y
comprobar el algoritmo con el que se está realizando, si es
que se realiza, el stemming.

Para la elaboración del listado de stopwords podemos acudir
a páginas
especializadas en IR o Text Mining (http://snowball.tartarus.org/
, http://www.unine.ch/info/clef/).

Nuestra clase SpanishAnalyzer hederará de org.apache.lucene.analysis.Analyzer y tendría el siguiente
código fuente:

En la constante SPANISH_STOP_WORDS incluiremos el listado por defecto de
stopWords en castellano que tendrá el analizador. Lo ideal sería que el listado final de stopWords
se obtuviese de un recurso externo parametrizable (un fichero de propiedades, base de datos…).

En el método tokenStream es donde se filtra el
contenido, para ello hemos incluido varios filters:

  • StandardFilter: básicamente, elimina los signos
    de puntuación, 
  • LowerCaseFilter: convierte el contenido a
    minúsculas,
  • StopFilter: filtrará el contenido con el listado
    de stopWords,
  • SpanishStemFilter: objeto del siguiente punto del tutorial.

5. SpanishTemFilter.

Nuestro filtro de stemming heredará de org.apache.lucene.analysis.TokenFilter y tendrá el siguiente código fuente:

Utiliza la clase SpanishStemmer, de la librería lucene-snowball.
Snowball es un lenguaje de programación para el manejo de strings que
permite implementar fácilmente algoritmos de stemming.

6. Test unitario SpanishAnalyzerTest.

Desde Autentia insistimos
mucho en la realización de test (unitarios y de integración) de nuestras aplicaciones.

Una vez implementado el analizador en castellano deberíamos probarlo, y qué mejor
que un test de Junit que forme parte de nuestro código fuente?, con ello testeamos
el funcionamiento actual y futuro (si alguien toca nuestro código, los tests deben
seguir funcionando).

7. Búsqueda de documentos por similitud.

Tomando como base el modelo de espacio vectorial que Lucene implementa, podemos realizar una búsqueda por similitud teniendo en cuenta los siguientes parámetros:

  • el número mínimo de ocurrencias de una palabra en un documento,
  • el número mínimo de ocurrencias de un término, esto es, de la raíz semántica de una palabra en un documento,
  • la longitud mínima de una palabra, el número mínimo de caracteres de una palabra para que sea tenida en cuenta. Fortaleciendo, de este modo, el listado de stop words.
  • un número máximo de términos para componer la consulta.

En función a los mismos se generará una consulta que estará formada por los términos del vector más relevantes del documento, hasta llegar al número máximo parametrizado.

Lucene distribuye una librería (lucene-similarity) que contiene una clase que implementa ésta funcionalidad: MoreLikeThis. Vamos a ver su funcionamiento en el siguiente test:

El test se ejecuta en un entorno en el que el directorio src/test/resources/files contiene una serie de documentos, en formato word, que serán indexados.
Y se busca los documentos similares al documento Original.doc [línea 60].

A destacar:

  • línea 70 y siguientes: en la que se crea una instancia de la clase MoreLikeThis y se setean los parámetros que hemos comentado para la generación de la consulta.
  • línea 135: en la que se crea el campo del documento de Lucene que almacenará el contenido de nuestro documento, indicando para ello el tipo de almacenamiento que tendrá nuestro vector de términos (TermVector.WITH_POSITIONS_OFFSETS) y extrayendo el contenido de nuestro documento de Microsoft Word utilizando la última versión de la librería poi

Si tienes la oportunidad pruébalo con alguno de los documentos que manejas habitualmente, te sorprenderán los resultados.

Recomendamos utilizar una capa de indexación que encapsule la lógica de acceso a Lucene como lius, y si tu problemática es solo la extracción del contenido de los
documentos (en diferentes formatos) puedes echar un ojo al proyecto tika de apache, basado en lius.

8. Conclusiones.

Hemos visto cómo realizar un analizador semántico en castellano para Lucene que implemente
un listado elaborado de stopwords, y filtre el contenido de los términos, a indexar y buscar, en
función de su raíz semántica. Con ello podemos comprobar cómo realizar búsquedas
de documentos por simlitud, con un alto grado de acierto.

Y hemos potenciado la funcionalidad de Lucene, se te ocurre alguna aplicación práctica?, a nosotros sí.

Si necesitas un empujón a tus desarrollos, ampliar la funcionalidad de tus aplicaciones, un estudio de la viabilidad de implementar ésta tecnología u otras… llámanos!!!

Somos Autentia.

Dejar respuesta

Please enter your comment!
Please enter your name here