Historias de usuarios

Clasificación de textos facilitada con Elasticsearch

Elasticsearch se usa ampliamente como motor de búsqueda y analítica. Sus capacidades como API de minería de textos no son tan conocidas.

En el siguiente artículo me gustaría mostrar cómo se puede hacer la clasificación de texto con Elasticsearch. Con formación en lingüística computacional y varios años de experiencia empresarial como profesional independiente en el campo de la minería de textos, tuve la oportunidad de implementar y probar las siguientes técnicas en diferentes situaciones.

Cuando me topé con Elasticsearch por primera vez, me fascinó su facilidad de uso, velocidad y opciones de configuración. Cada vez que trabajaba con Elasticsearch, encontraba una forma aún más simple de lograr lo que estaba acostumbrada a resolver con las herramientas y técnicas tradicionales del procesamiento de lenguajes naturales (NLP).

Entonces me di cuenta de que puede resolver muchas cosas de inmediato para las que se me capacitó para implementar desde cero.

La mayoría de las tareas de NLP comienzan con un pipeline de preprocesamiento estándar:

  1. Recopilación de datos
  2. Extracción de texto sin procesar
  3. División de oraciones
  4. Tokenización
  5. Normalización (derivación, lematización)
  6. Eliminación de palabras vacías
  7. Parte del etiquetado de las oraciones

Algunas tareas de NLP, como el análisis sintáctico, requieren un análisis lingüístico profundo.

Para este tipo de tareas, Elasticsearch no proporciona la arquitectura y el formato de datos ideales listos para usar. Es decir, para tareas que van más allá del nivel de token, los plugins personalizados que acceden al texto completo deben escribirse o usarse.

Pero las tareas tales como clasificación, distribución en clusters, extracción de palabras clave, medición de similitudes, etc. solo requieren una representación de bolsa de palabras normalizada y posiblemente ponderada de un documento dado.

Los pasos 1 y 2 se pueden resolver con el plugin de procesador de datos adjuntos de ingestión (antes de 5.0 plugin para datos adjuntos de mapeador) en Elasticsearch.

La extracción de texto sin formato para estos plugins se basa en Apache Tika, que funciona en los formatos de datos más comunes (HTML/PDF/Word etc.).

Los pasos 4 a 6 se resuelven con los analizadores de lenguaje listos para usar.

Mapeo de muestra:

  {
    "properties":{
       "content":{
          "type":"text",
          "analyzer":"german"
       }
    }
  }

Si el tipo de mapeo para un campo dado es "text" (texto) (antes de 5.0: "analyzed string" [texto analizado]) y el analizador está configurado en uno de los idiomas admitidos de forma nativa por Elasticsearch, la tokenización, la derivación y la eliminación de palabras vacías se realizarán automáticamente al momento de la indexación.

Por lo tanto, no se requiere ningún código personalizado ni ninguna otra herramienta para pasar de cualquier tipo de documento compatible con Apache Tika a una representación de bolsa de palabras.

Los analizadores de lenguaje también se pueden llamar a través de API REST, cuando Elasticsearch se está ejecutando.

curl -XGET "http://localhost:9200/_analyze?analyzer=english" -d'
  {
   "text" : "This is a test."
  }'
  {
    "tokens":[
       {
          "token":"test",
          "start_offset":10,
          "end_offset":14,
          "type":"<ALPHANUM>",
          "position":3
       }
    ]
  }

El enfoque sin Elasticsearch se ve así:

Recopilación del texto con un código personalizado, análisis de documentos a mano o con la biblioteca Tika, mediante el uso de una biblioteca de NLP tradicional o API como NLTK, OpenNLP, Stanford NLP, Spacy o cualquier otra cosa que se haya desarrollado en algún departamento de investigación. Sin embargo, las herramientas desarrolladas en los departamentos de investigación generalmente no son muy útiles para un contexto empresarial. Con mucha frecuencia, los formatos de datos están patentados, las herramientas deben compilarse y ejecutarse en la línea de comando y los resultados a menudo simplemente se canalizan a la salida estándar. Las API REST son una excepción.

Con los analizadores de lenguaje Elasticsearch, por otro lado, solo necesitas configurar tu mapeo e indexar los datos. El preprocesamiento ocurre automáticamente al momento de la indexación.

Enfoque tradicional para la clasificación de texto

La clasificación de texto es una tarea tradicionalmente resuelta con Machine Learning supervisado. La entrada para entrenar un modelo es un conjunto de documentos etiquetados. La representación mínima de esto sería un documento JSON con 2 campos:

"content" (contenido) y "category" (categoría)

Tradicionalmente, la clasificación de texto se puede resolver con una herramienta como SciKit Learn, Weka, NLTK, Apache Mahout, etc.

Creación de los modelos

La mayoría de los algoritmos de Machine Learning requieren una representación del modelo de espacio vectorial de los datos. El espacio de características suele ser algo así como las 10 000 palabras más importantes de un conjunto de datos determinado. ¿Cómo se puede medir la importancia de una palabra?

Generalmente, con TF-IDF. Esta es una fórmula que se inventó en los años setenta del siglo pasado. TF-IDF es una ponderación que puntúa un término dentro de un documento determinado en relación con el resto del conjunto de datos. Si un término de un documento tiene una alta puntuación de TF-IDF, significa que es una palabra clave muy característica y distingue un documento de todos los demás documentos por medio de esa palabra.

Las palabras clave con las puntuaciones más altas de TF-IDF en un subconjunto de documentos pueden representar un tema. Puede procesar texto arbitrario, extraer las n palabras clave principales relativas al "modelo" real y ejecutar una búsqueda de coincidencia booleana con esas palabras clave.

Cada documento se convierte en un vector de características; después, con todas las instancias de entrenamiento para cada clase/categoría, se crea un modelo. Después de eso, los nuevos documentos se pueden clasificar de acuerdo con este modelo. Por lo tanto, el documento debe convertirse en un vector de características y, a partir de ahí, se calculan todas las similitudes. El documento se etiquetará con la categoría con la puntuación más alta.

Clasificación de texto con Elasticsearch

Todo lo anterior se puede resolver de una manera mucho más simple con Elasticsearch (o Lucene).

Solo necesitas ejecutar 4 pasos:

  1. Configurar tu mapeo ("content" [contenido]: "text" [texto], "category" [categoría]: "keyword" [palabra clave])
  2. Indexar tus documentos
  3. Ejecutar una More Like This Query (búsqueda más similar a esta) (búsqueda MLT)
  4. Escribir un pequeño script que agregue los resultados de esa búsqueda por puntuación
PUT sample
  POST sample/document/_mapping
  {
    "properties":{
       "content":{
          "type":"text",
          "analyzer":"english"
       },
       "category":{
          "type":"text",
          "analyzer":"english",
          "fields":{
             "raw":{
                "type":"keyword"
             }
          }
       }
    }
  }
  POST sample/document/1
  {
    "category":"Apple (Fruit)",
    "content":"Granny Smith, Royal Gala, Golden Delicious and Pink Lady are just a few of the thousands of different kinds of apple that are grown around the world! You can make dried apple rings at home - ask an adult to help you take out the core, thinly slice the apple and bake the rings in the oven at a low heat."
  }
  POST sample/document/2
  {
    "category":"Apple (Company)",
    "content":"Apple is an American multinational technology company headquartered in Cupertino, California, that designs, develops, and sells consumer electronics, computer software, and online services. Its hardware products include the iPhone smartphone, the iPad tablet computer, the Mac personal computer, the iPod portable media player, the Apple Watch smartwatch, and the Apple TV digital media player. Apple's consumer software includes the macOS and iOS operating systems, the iTunes media player, the Safari web browser, and the iLife and iWork creativity and productivity suites. Its online services include the iTunes Store, the iOS App Store and Mac App Store, Apple Music, and iCloud."
  }

La búsqueda de MLT es una búsqueda muy importante para la minería de textos.

¿Cómo funciona? Puede procesar texto arbitrario, extraer las palabras clave con n principales relativas al "modelo" real y ejecutar una búsqueda de coincidencia booleana con esas palabras clave. Esta búsqueda se usa a menudo para recopilar documentos similares.

Si todos los documentos tienen una etiqueta de clase/categoría y una cantidad similar de instancias de entrenamiento por clase, esto es equivalente a la clasificación. Simplemente, ejecuta una búsqueda de MLT con el documento de entrada como campo similar y escribe un pequeño script que agregue puntuación y categoría de los mejores n resultados.

GET sample/document/_search
  {
    "query":{
       "more_like_this":{
          "fields":[
             "content",
             "category"
          ],
          "like":"The apple tree (Malus pumila, commonly and erroneously called Malus domestica) is a deciduous tree in the rose family best known for its sweet, pomaceous fruit, the apple. It is cultivated worldwide as a fruit tree, and is the most widely grown species in the genus Malus. The tree originated in Central Asia, where its wild ancestor, Malus sieversii, is still found today. Apples have been grown for thousands of years in Asia and Europe, and were brought to North America by European colonists. Apples have religious and mythological significance in many cultures, including Norse, Greek and European Christian traditions.",
          "min_term_freq":1,
          "max_query_terms":20
       }
    }
  }

Esta muestra solo pretende ilustrar el flujo de trabajo. Para una clasificación real, necesitarás un poco más de datos. Así que no te preocupes si con ese ejemplo no obtienes ningún resultado real. Simplemente, agrega más datos y funcionará.

Este es un pequeño script de Python que procesa la respuesta y devuelve la categoría más probable para el documento de entrada.

from operator import itemgetter
  def get_best_category(response):
     categories = {}
     for hit in response['hits']['hits']:
         score = hit['_score']
         for category in hit['_source']['category']: 
             if category not in categories:
                 categories[category] = score
             else:
                 categories[category] += score
     if len(categories) > 0:
         sortedCategories = sorted(categories.items(), key=itemgetter(1), reverse=True)
         category = sortedCategories[0][0]
     return category

¡Y ahí está tu clasificador de texto de Elasticsearch!

Casos de uso

La clasificación de texto es un caso de uso muy común del mundo real para NLP. Piensa en los datos del comercio electrónico (productos). Mucha gente dirige tiendas de comercio electrónico con enlaces de afiliados. Los datos los proporcionan varias tiendas y a menudo vienen con una etiqueta de categoría. Pero cada tienda tiene otra etiqueta de categoría. Por lo tanto, los sistemas de categorías deben estar unificados y, por ende, todos los datos deben volver a clasificarse de acuerdo con el nuevo árbol de categorías. O deben pensar en una aplicación de Inteligencia de Negocios donde los sitios web de las empresas necesiten clasificarse según su sector (peluquería vs. panadería, etc.).

Evaluación

Evalué este enfoque con un conjunto de datos de clasificación de texto estándar: El conjunto de datos 20 Newsgroups. La mayor precisión (92 % de etiquetas correctas) se logró con un umbral de puntuación de alta calidad que incluyó solo el 12 % de los documentos. Al etiquetar todos los documentos (100 % de recuperación), el 72 % de las predicciones fueron correctas.

Los mejores algoritmos para la clasificación de texto en el conjunto de datos 20 Newsgroups son generalmente SVM y Naive Bayes. Tienen una mayor precisión promedio en todo el conjunto de datos.

Entonces, ¿por qué deberías considerar usar Elasticsearch para la clasificación si hay mejores algoritmos?

Hay algunas razones prácticas: entrenar un modelo de SVM lleva mucho tiempo. Especialmente cuando trabajas en una empresa emergente o necesitas realizar adaptaciones rápidas para diferentes clientes o casos de uso que podrían convertirse en un problema real. Por lo tanto, es posible que no puedas volver a entrenar tu modelo cada vez que cambien tus datos. Lo experimenté yo misma trabajando en un proyecto para un gran banco alemán. Por lo tanto, trabajarás con modelos obsoletos que seguramente ya no obtendrán tan buenos resultados.

Con el enfoque de Elasticsearch, el entrenamiento se realiza al momento de la indexación, y tu modelo se puede actualizar dinámicamente en cualquier momento con cero tiempo de inactividad de tu aplicación. Si tus datos ya están almacenados en Elasticsearch, no necesitas ninguna infraestructura adicional. Con más del 10 % de resultados altamente precisos, generalmente puedes llenar la primera página. En muchas aplicaciones, eso es suficiente para una primera buena impresión.

¿Por qué entonces usar Elasticsearch cuando hay otras herramientas?

Porque tus datos ya están allí y se van a calcular previamente las estadísticas subyacentes de todos modos. ¡Es casi como si recibieras un poco de NLP gratis!


Saskia Vola

Saskia Vola estudió Lingüística Computacional en la Universidad de Heidelberg y comenzó a trabajar en el campo de la minería de textos en 2009. Después de unos años en el ámbito de las empresas emergentes de Berlín, decidió convertirse en una profesional independiente a tiempo completo y disfrutar de la vida como nómada digital. A medida que recibió más y más ofertas de proyectos relevantes, decidió comenzar una plataforma para trabajadores independientes de NLP/AI llamada textminers.io