Cómo entrenar un modelo de correferencia neural: Neuralcoref 2

Enlaces: Repo de Github de demostración en línea: https://github.com/huggingface/neuralcoref y nuestra publicación anterior de Medium.

Los últimos meses han sido bastante intensos en HuggingFace con un crecimiento de uso loco y todos los que trabajan duro para mantenerse al día , pero finalmente logramos liberar algo de tiempo y actualizar nuestra biblioteca de código abierto Neuralcoref mientras publicamos el código de capacitación en al mismo tiempo.

Desde que lanzamos v1 el verano pasado, más de diez millones de coreferencias se han resuelto en Hugging Face. Además, estamos encantados de que nuestra biblioteca ahora sea utilizada en producción por algunas otras compañías y algunos investigadores realmente inteligentes, ¡y nuestro trabajo se presentó en la última sesión del curso de PNL de Stanford!

El código de entrenamiento se ha actualizado para funcionar con las últimas versiones de PyTorch (v0.3) y spaCy v2.0, mientras que el modelo pre-entrenado solo depende de Numpy y spaCy v2.0.

El hito principal de esta versión: ahora podrá entrenar a Neuralcoref en su propio conjunto de datos, por ejemplo, en otro idioma que no sea inglés. - siempre que tenga un conjunto de datos anotado.

Hemos agregado una sección especial al archivo Léame sobre capacitación en otro idioma, así como instrucciones detalladas sobre cómo obtener, procesar y capacitar el modelo en el conjunto de datos OntoNotes 5.0 en inglés.

Como antes, Neuralcoref está diseñado para lograr un buen equilibrio entre precisión y velocidad / simplicidad, utilizando un módulo de detección de mención basado en reglas, un número restringido de características y una red neuronal de retroalimentación simple que se puede implementar fácilmente en Numpy.

En el resto de esta publicación de blog, describiré cómo funciona el sistema de resolución de coreferencia y cómo capacitarlo. La resolución de la correferencia es una tarea de PNL bastante complicada ¡tan desnuda conmigo que no te arrepentirás!

Echemos un vistazo rápido a un conjunto de datos (público)

Un conjunto de datos públicos de buena calidad que puede usar para entrenar el modelo en inglés es el conjunto de datos CoNLL 2012. Es uno de los conjuntos de datos más grandes disponibles de forma gratuita con anotaciones de coreferencia, con aproximadamente 1,5 millones de tokens que abarcan muchos campos, como noticias, transmisión y conversaciones telefónicas, así como datos web (blogs, grupos de noticias ...).

En el repositorio, explicamos cómo descargar y preparar este conjunto de datos si desea usarlo. Una vez que haya terminado con eso, un archivo CoNLL típico se verá así:

Extracto del archivo de conjunto de datos CoNLL 2012

Este extracto contiene 2 oraciones: "Sí, noté que muchos amigos, a mi alrededor lo recibieron" y "Parece que casi todos recibieron este SMS"

Las oraciones se tokenizan y se anotan con los tokens en la columna 4 y una gran cantidad de anotaciones: etiquetas POS (col 5), árbol de análisis (col 6), lema de verbos (col 7), hablante (col 10) y, lo que somos especialmente interesado en las etiquetas de referencia conjunta en la última columna (etiquetas 12, 119 en las líneas 5, 12, 14, 23 y 24). En este extracto, "I" se anota como una referencia conjunta con "yo" (tienen la misma etiqueta de entidad 12) y "eso" como una referencia conjunta con "este SMS" (etiqueta 119).

También puede observar que solo las menciones que tienen al menos una referencia conjunta están etiquetadas en el conjunto de datos (es decir, al menos un par de menciones que se refieren a la misma entidad). Las menciones individuales de una entidad, sin otra mención que se refiera a la misma entidad, no están etiquetadas.

Esto es algo molesto, ya que significa que no podemos evaluar completamente (y entrenar fácilmente) el módulo de identificación de mención de nuestro sistema de coreferencia (con precisión, recuperación y métricas F1). Sin embargo, todavía podemos echar un vistazo al recuerdo de las menciones de referencia conjunta como mencionamos en el repositorio de Github.

El flujo de trabajo del módulo coreference

El primer paso de nuestro proceso es extraer posibles menciones. Neuralcoref utiliza una función de mención-extracción basada en reglas para esta operación y obtiene, en nuestro ejemplo de dos oraciones:

Dependiendo de la selectividad del extractor de menciones basado en reglas y el árbol de análisis para nuestra oración, también puede capturar algunas menciones más grandes como "muchos amigos, a mi alrededor lo recibieron" o "casi todos recibieron este SMS". Mantengamos aquí solo las breves menciones en aras de la simplicidad.

Cada mención puede correlacionarse con varias referencias anteriores. Podemos recopilar todas las menciones en una tabla de pares de mención para resaltar los pares de referencia conjunta (en la tabla ∅ significa que una mención no se transfiere con ninguna mención previa).

Una tabla de pares de mención coreferring para nuestro ejemplo de dos oraciones (etiquetas positivas en rojo)

Tenga en cuenta que puede haber más de un antecedente de referencia conjunta para una mención dada (es decir, varios recuadros rojos en una sola línea en nuestra tabla), formando grupos de menciones de referencia conjunta (la resolución de referencia conjunta es una tarea de agrupación).

Ya podemos ver algunos de los problemas que surgirán al entrenar un modelo en dichos datos, a saber, que (i) cada mención tendrá un número variable de antecedentes potenciales, lo que complicará el procesamiento por lotes (el tamaño de nuestro vector de pares de mención abarcará todos el rango de 0 a N el número total de menciones en un documento), y (ii) la tabla de pares de mención generalmente se escalará como cN donde c en el número promedio de menciones en cada documento del conjunto de datos, y esto puede convertirse en bastante grande.

En la práctica, nuestro extractor de menciones basado en reglas identifica alrededor de 1 millón de menciones potenciales en el conjunto de capacitación CoNLL 2012, lo que resulta en unos 130 millones de pares de menciones para entrenar nuestro modelo.

Una vez que hemos identificado posibles menciones y etiquetas para ellos (el cuadro rojo en nuestra tabla), podemos extraer un conjunto de características para cada mención y cada par de menciones. Veamos las características que extraemos:

Funciones extraídas para menciones y pares de menciones. Los vectores de extensión son promedios calculados previamente de vectores de palabras.

Puede parecer que necesitamos muchas funciones, pero una de las ventajas de Neuralcoref es en realidad su reducido número de funciones: ¡algunos sistemas de resolución de coreferencia utilizan hasta +120 funciones! Otra ventaja es que la mayoría de estas funciones no dependen del analizador o de bases de datos adicionales (como la palabra género / número) y son fáciles / rápidas de calcular.

Prácticamente, las características son un montón de vectores de valores reales (por ejemplo, los vectores de extensión que son promedio sobre los vectores de palabras y no serán entrenados), enteros (por ejemplo, índices de palabras en un diccionario, índices categoriales) y booleanos (por ejemplo, "anidados" ? ”Indica si una mención de par está contenida en la otra).

La combinación de valores reales, enteros y características booleanas puede dar lugar a grandes matrices numpy si simplemente las reunimos en una sola matriz (enteros y booleanos se convertirán en flotantes). Por lo tanto, los almacenamos en matrices separadas y construimos las matrices de características a tiempo mientras alimentamos la red neuronal (consulte el código de DataLoader en dataset.py).

Hemos terminado con los pasos de preprocesamiento. Estos pasos se implementan en conllparser.py y document.py en el código Neuralcoref.

¡Ahora, usemos estas funciones para entrenar a nuestro modelo!

Un vistazo rápido al modelo de red neuronal

Como siempre, es un placer escribir el modelo de red neuronal en pyTorch, así que lo copio aquí por completo (solo eliminé las funciones de inicialización / carga de pesos).

El modelo comprende una capa de incrustación común, autoincrustada, que transforma los índices de palabras en vectores de palabras y alimenta dos redes de retroalimentación paralelas:

  • self.single toma como entradas vectores de palabras, espacios y características adicionales (ver arriba) de una mención y calcula el puntaje que no tiene otra mención de referencia conjunta (puntaje de ∅ como etiqueta),
  • self.pairs toma como entradas vectores de palabras, espacios y características de una mención y un antecedente, junto con características de pares, y calcula el puntaje que el par de menciones hace referencia.

Entonces, ¿cómo entrenamos a esta belleza?

Entrenamiento de la red neuronal coreferencial

Primero, una palabra sobre mini-lote. Hablamos sobre el problema de tener un número variable de pares para cada mención. Una forma de usar mini lotes en tales condiciones es empacar mini lotes de la siguiente manera:

  • Ordene las menciones en el conjunto de entrenamiento por su número de antecedentes potenciales (la longitud de cada línea en nuestra tabla de pares),
  • Definir un número máximo de pares P para un mini lote, y
  • Corte el conjunto de entrenamiento ordenado en mini lotes de tamaño ≅P, rellenando los pares de mención en cada mini lote hasta el número máximo de pares en el mini lote (la línea más larga, es decir, la última de nuestro conjunto de datos ordenados).

En Neuralcoref, esto se hace mediante el módulo dataset.py que carga y construye un conjunto de datos y un cargador de datos con tales mini lotes rellenados.

Ejemplo de métrica de evaluación Neuralcoref durante el entrenamiento

Una vez que nuestros mini lotes estén listos, podemos comenzar a entrenar.

El entrenamiento pasa por tres fases de entrenamiento sucesivas: Todos los pares, Pares superiores y Clasificación.

Establecimos un esquema de programación muy simple para mantener el entrenamiento rápido: cada vez que nuestra métrica en el conjunto de desarrollo deja de aumentar, pasamos a la siguiente etapa.

Las dos primeras fases usan pérdida probabilística (entropía cruzada), mientras que la última fase usa una pérdida de clasificación escalada sin holgura. Más precisamente, nuestras pérdidas para cada fase de entrenamiento se ven así:

𝓣 (m) es el conjunto de antecedentes verdaderos de una mención m, 𝓕 (m) los antecedentes falsos y 𝓐 (m) todos los antecedentes (incluido ∅).

La pérdida de Todos los pares es una pérdida de entropía cruzada estándar en el conjunto completo de pares de mención. La pérdida de los pares superiores también es una entropía cruzada, pero está restringida a los antecedentes verdaderos y falsos (actualmente) de máxima puntuación de una mención. Finalmente, la pérdida de Clasificación es una pérdida de margen máximo con un costo reescalado flojo Δ.

Para obtener más información, debe consultar el excelente trabajo publicado en 2016 por Kevin Clark y Christopher Manning (consulte “Aprendizaje de refuerzo profundo para modelos de referencia de clasificación de referencia” por Kevin Clark y Christopher D. Manning, EMNLP 2016, Mejorando la resolución de referencia por Representaciones distribuidas a nivel de entidad de aprendizaje de Kevin Clark y Christopher D. Manning, ACL 2016, y las referencias que contiene), de las cuales nuestro modelo es una adaptación.

Los detalles completos y más se dan en estas publicaciones que definitivamente debería leer si está interesado en este modelo.

Esta capacitación se implementa en learn.py en el código Neuralcoref.

Así que espero que esto te dé algunas buenas intuiciones sobre cómo funciona esta bestia poco común.

Lo más importante, configuramos una demostración realmente agradable y rápida, ¡así que no dudes en probar el sistema de coreferencia por ti mismo!

Y no dude en bifurcar el código y usarlo en sus proyectos. Espero que les haya gustado y háganos saber cómo lo usan