Procesamiento del lenguaje natural con ElasticSearch

por:

Procesamiento del lenguaje natural con ElasticSearch

Uno de los problemas que se presentan con una mayor frecuencia hoy en día, es la realización de búsquedas textuales. Este problema se puede resolver con muchos enfoques, desde una búsqueda exacta como permiten la mayoría de los lenguajes de programación, hasta la utilización de algoritmos de procesamiento del lenguaje natural.

¿Qué es el procesamiento del lenguaje natural?

El procesamiento del lenguaje natural, conocido también por sus siglas en inglés NPL consiste en desarrollar y aplicar distintas técnicas, metodologías y algoritmos que utilizan como entrada y/o salida texto o voz. La complejidad de este campo, es que agrupa conceptos como:

  • El reconocimiento de voz (traducir la voz en texto).
  • La síntesis de voz (traducir el texto en voz).
  • La traducción en tiempo real.
  • La identificación del idioma del usuario.

Además, hay que tener en cuenta que mientras que la escritura por ordenador es siempre igual, en el caso de la voz cada usuario dependiendo de su lugar, sexo, edad, etc presenta características distintas.

¿Qué es ElasticSearch?

ElasticSearch es un proyecto basado en Apache Lucene, que nos permite tener un servidor para realizar búsquedas. El proyecto fue creado por Shay Banon y tiene como principales características la velocidad de búsqueda y la escalabilidad. Este software es ampliamente usado en buscadores, e-commerce y para tratar el lenguaje natural.

¿Cómo funciona ElasticSearch?

La verdad es que ElasticSearch es bastante complejo de utilizar ya que utiliza una conjunto de conceptos específicos de este software y su configuración no es del todo intuitiva. Sin embargo, los resultados valen la pena. Por este motivo os dejo la siguiente presentación, en la cual podéis ver un explicación detallada de todos los conceptos, cómo configurar ElasticSearch y algunos casos de uso. Esta presentación es la que yo he utilizado para desarrollar un trabajo sobre este software y es de lo mejor que he leído en español sobre este tema.

Procesamiento del lenguaje natural con ElasticSearch

Muchos os preguntaréis por qué hablo de ElasticSearch si es un software de búsqueda. Esto es debido a que ElasticSearch tiene implementado multitud de algoritmos para el procesamiento del lenguaje natural, ya que estos se usan para mejorar los resultados. Por ejemplo, si el usuario busca por “coches” también le interesan los resultados de “coche”.

Los algoritmos de procesamiento del lenguaje más destacados se pueden categorizar en:

  • Stemmers: son algoritmos que reducen una palabra a su raíz, para ello:
    • Elimina los plurales
    • Transforma las formas verbales a su raíz.
    • Elimina los sufijos con los que se forman otras palabras por derivación.
  • Lowercase: transforma a minúsculas todas las letras de la entrada de datos.
  • Stop Words: elimina un conjunto de palabras que no aportan significado a la frase, por ejemplo los artículos o las preposiciones.

Para obtener los mejores resultados, hay que utilizar los tres anteriores de manera consecutiva.

Para ilustrar cómo funcionaría, si nosotros realizásemos la siguiente búsqueda: “¿Dónde comer en Salamanca?”, con lo anterior se transformaría en “donde come salamanca”. Esto haría que el número de resultados desfavorables se redujera ya que, aquellos que tienen en su título la palabra “en” no saldrían, al haber sido eliminada.

Open Distro for ElasticSearch

Debido al modelo de negocio de ElasticSearch, que combina una base gratuita con multitud addons de pago, para rentabilizar el proyecto, muchos de ellos relativos a la seguridad, Amazon ha creado Open Distro for ElasticSearch. Esta nueva distribución, no es más que la base de ElasticSearch con algunas mejoras, principalmente en los siguientes aspectos:

  • Mayor seguridad
  • Gestión de alertas
  • Soporte de SQL como lenguaje de consultas
  • Monitor de rendmiento

Debido a estas mejoras, puede que te interese probar esta versión si estas comenzando en este mundillo.

Espero que esta entrada os anime a profundizar en ElasticSearch y que lo podáis utilizar para vuestros sistemas de búsqueda.

Cómo diseñar analyzers personalizados

Si bien ElasticSearch trae un número bastante grande de analyzers ya creados, si necesitas realizar búsquedas muy específicas, te tocará diseñar tu propio analyzer. Ese sistema se diseña como un pipeline o tu tubería, donde la salida de un módulo se conecta a la entrada de otro módulo, dando como resultado los tokens que se indexaran en el diccionario invertido. Si estas palabras te suenan a chino, te invito a ver la presentación de mercadolibre que hay en este mismo artículo. Los distintos módulos que forman un analyzer pueden ser:

  • Character filters reciben una colección ordenada de caracteres (la entrada del usuario, para el primero de este tipo) y generan otra cadena de caracteres. Lo más importante es que trabajan a nivel de caracter. Un analyzer puede estar formado por 0 o más de este tipo y siempre son los primeros en ejecutarse.
  • Tokenizer, recibe un grupo de caracteres y los separa en grupos o tokens, siguiendo el algoritmo designado, como la separación por espacios en blanco. Sólo puede existir uno.
  • Token filters, recibe una colección de tokens y realiza transformaciones sobre los mismos (añadir, quitar o cambiar tokens). Son los últimos en ejecutarse y un analyzer puede tener 0 o más de este tipo.

Partes de un analyzer con su character filters, tokenizer y token filters

Supongamos que tenemos un campo “teléfonos” y ahí los usuarios introducen datos de múltiples maneras:

  • Hay usuarios que meten el prefijo del tipo: “+34123456789” o “+34 123456789”
  • Otros usuarios meten varios teléfonos: “123456789 234555666”
  • Pero también tenemos casos como: “123-456-788” o “922-11-22-33”

Si queremos realizar una búsqueda con ElasticSearch sobre estos campos podríamos configurar un analyzer de la siguiente manera:

  1. Usar un character filter de tipo pattern_replace con una expresión regular que detecte los grupos “-” y “\+dd “
  2. Un tokenizer de tipo whitespace que separe la cadena por espacios en blanco
  3. Un token filter de tipo pattern_replace que elimine todo aquello que no sea números, por ejemplo “[^\d]+”
  4. Un token filter de tipo n-gram configurado como min_gram= 3 y max_gram=7 que genere de cada token todos los n-gramas de longitud entre 3 y 7

Supongamos que la entrada a indexar es “+34 123-456-789 +77456789123” el resultado de aplicar cada módulo sería el siguiente:

  1. Se eliminan los caracteres y queda “123456789 +77456789123”
  2. Se parte la cadena y quedan dos tokens “123456789” y “+77456789123”
  3. El primer token queda igual y el segundo queda “456789123”
  4. Se generan los n-grams de cada token por ejemplo de123456789son: 123, 1234, 12345, 123456, 1234567, 234, 2345, 23456, 234567, 2345678, 345, 3456, 34567, 345678, 3456789, 456, 4567, 4568, 456789, 567, 5678, 56789, 678, 6789, 789

El algoritmo que se sigue para esto último es similar a:

var input = "123456789"
var ngram =3;
do{
    for(var i=0;input.length>=(i+ngram);i++)
        console.log(input.slice(i,i+ngram));

ngram++
}while(ngram<7)

Espero que este artículo te resulte útil

Deja una Respuesta