Adaptación de dominio Ajuste fino de modelos de procesamiento del lenguaje natural pre-entrenados

Domain Adaptation Fine-tuning Pre-trained Models for Natural Language Processing.

Foto de Pietro Jeng en Unsplash

Tutoriales prácticos

Una guía paso a paso para ajustar modelos NLP pre-entrenados para cualquier dominio

Prefacio: Este artículo presenta un resumen de información sobre el tema dado. No debe considerarse una investigación original. La información y el código incluidos en este artículo pueden verse influenciados por cosas que he leído o visto en el pasado en varios artículos en línea, documentos de investigación, libros y código de código abierto.

Co-Autor: Billy Hines

Tabla de contenido

  • Introducción
  • Marco teórico
  • Descripción de los datos
  • Punto de partida: El modelo de referencia
  • Ajuste del modelo
  • Evaluación de los resultados
  • Conclusiones

Introducción

En el mundo actual, la disponibilidad de modelos NLP pre-entrenados ha simplificado en gran medida la interpretación de datos textuales utilizando técnicas de aprendizaje profundo. Sin embargo, si bien estos modelos son excelentes en tareas generales, a menudo carecen de adaptabilidad a dominios específicos. Esta guía exhaustiva tiene como objetivo guiarlo a través del proceso de ajuste de modelos NLP pre-entrenados para lograr un mejor rendimiento en un dominio particular.

Motivación

Aunque los modelos NLP pre-entrenados como BERT y el Universal Sentence Encoder (USE) son efectivos para capturar las complejidades lingüísticas, su rendimiento en aplicaciones específicas de dominio puede ser limitado debido a la amplia gama de conjuntos de datos en los que están entrenados. Esta limitación se hace evidente al analizar las relaciones dentro de un dominio específico.

Por ejemplo, al trabajar con datos de empleo, esperamos que el modelo reconozca la mayor proximidad entre los roles de ‘Científico de datos’ e ‘Ingeniero de aprendizaje automático’, o la asociación más fuerte entre ‘Python’ y ‘TensorFlow’. Desafortunadamente, los modelos de propósito general a menudo pasan por alto estas relaciones sutiles.

La tabla a continuación demuestra las discrepancias en la similitud obtenida a partir de un modelo base USE multilingüe:

Fig 1. Puntuación de similitud entre dos vectores de texto del modelo base MultiLingual Universal Sentence Encoder

Para abordar este problema, podemos ajustar finamente modelos pre-entrenados con conjuntos de datos de alta calidad y específicos del dominio. Este proceso de adaptación mejora significativamente el rendimiento y la precisión del modelo, desbloqueando por completo el potencial del modelo NLP.

Cuando se trata de modelos NLP pre-entrenados grandes, es recomendable implementar inicialmente el modelo base y considerar el ajuste fino solo si su rendimiento no es suficiente para el problema específico en cuestión.

Este tutorial se centra en el ajuste fino del modelo Universal Sentence Encoder (USE) utilizando datos de código abierto de fácil acceso.

Resumen teórico

El ajuste fino de un modelo de ML se puede lograr mediante diversas estrategias, como el aprendizaje supervisado y el aprendizaje por refuerzo. En este tutorial, nos centraremos en un enfoque de aprendizaje de uno (pocos) disparos combinado con una arquitectura siamesa para el proceso de ajuste fino.

Metodología

En este tutorial, utilizamos una red neuronal siamesa, que es un tipo específico de red neuronal artificial. Esta red aprovecha pesos compartidos mientras procesa simultáneamente dos vectores de entrada distintos para calcular vectores de salida comparables. Inspirado en el aprendizaje de un solo disparo, este enfoque ha demostrado ser particularmente efectivo para capturar similitudes semánticas, aunque puede requerir tiempos de entrenamiento más largos y carecer de salida probabilística.

Una red neuronal siamesa crea un ‘espacio de incrustación’ donde los conceptos relacionados se posicionan cerca, lo que permite que el modelo distinga mejor las relaciones semánticas.

Fig 2. Arquitectura siamesa para ajustar finamente modelos NLP pre-entrenados
  • Ramas Gemelas y Pesos Compartidos: La arquitectura consiste en dos ramas idénticas, cada una con una capa de incrustación con pesos compartidos. Estas ramas duales manejan dos entradas simultáneamente, ya sean similares o diferentes.
  • Similitud y Transformación: Las entradas se transforman en incrustaciones vectoriales utilizando el modelo de procesamiento de lenguaje natural pre-entrenado. A continuación, la arquitectura calcula la similitud entre los vectores. La puntuación de similitud, que varía entre -1 y 1, cuantifica la distancia angular entre los dos vectores, sirviendo como una métrica para su similitud semántica.
  • Pérdida Contrastiva y Aprendizaje: El aprendizaje del modelo está guiado por la “Pérdida Contrastiva”, que es la diferencia entre la salida esperada (puntuación de similitud a partir de los datos de entrenamiento) y la similitud calculada. Esta pérdida guía el ajuste de los pesos del modelo para minimizar la pérdida y mejorar la calidad de las incrustaciones aprendidas.

Para obtener más información sobre el aprendizaje de uno (pocos) disparos, la arquitectura siamesa y la pérdida contrastiva, consulte los siguientes recursos:

Una Introducción Sencilla a la Arquitectura de Redes Neuronales Siamesas

Arquitectura de Redes Neuronales Siamesas: Una Visión General y Conceptos Clave Explicados con Ejemplos | ProjectPro

www.projectpro.io

¿Qué es el aprendizaje de uno disparo? – TechTalks

El aprendizaje de uno disparo permite que los algoritmos de aprendizaje profundo midan la similitud y la diferencia entre dos imágenes.

bdtechtalks.com

Pérdida Contrastiva Explicada

La pérdida contrastiva se ha utilizado recientemente en varios documentos que muestran resultados de vanguardia con el aprendizaje no supervisado…

towardsdatascience.com

El código completo está disponible como un Cuaderno de Jupyter en GitHub

Resumen de Datos

Para el ajuste fino de modelos de procesamiento de lenguaje natural pre-entrenados utilizando este método, los datos de entrenamiento deben consistir en pares de cadenas de texto acompañadas de puntuaciones de similitud entre ellas.

Los datos de entrenamiento siguen el formato mostrado a continuación:

Fig 3. Formato de Muestra para Datos de Entrenamiento

En este tutorial, utilizamos un conjunto de datos obtenido del conjunto de datos de clasificación ESCO, que se ha transformado para generar puntuaciones de similitud basadas en las relaciones entre diferentes elementos de datos.

Preparar los datos de entrenamiento es un paso crucial en el proceso de ajuste fino. Se asume que tiene acceso a los datos requeridos y un método para transformarlo en el formato especificado. Dado que el enfoque de este artículo es demostrar el proceso de ajuste fino, omitiremos los detalles de cómo se generaron los datos utilizando el conjunto de datos ESCO.

El conjunto de datos ESCO está disponible para que los desarrolladores lo utilicen libremente como base para diversas aplicaciones que ofrecen servicios como autocompletar, sistemas de sugerencia, algoritmos de búsqueda de empleo y algoritmos de coincidencia de empleo. El conjunto de datos utilizado en este tutorial se ha transformado y se proporciona como una muestra, permitiendo su uso sin restricciones para cualquier propósito.

Comencemos examinando los datos de entrenamiento:

import pandas as pd# Leer el archivo CSV en un DataFrame de pandasdata = pd.read_csv("./data/training_data.csv")# Imprimir encabezadadata.head()
Fig 4. Datos de muestra utilizados para el ajuste fino del modelo

Punto de Partida: El Modelo de Referencia

Para comenzar, establecemos el codificador de frases universal multilingüe como nuestro modelo de referencia. Es esencial establecer este punto de referencia antes de continuar con el proceso de ajuste fino.

Para este tutorial, utilizaremos el conjunto de datos de referencia STS y una visualización de similitud de muestra como métricas para evaluar los cambios y mejoras logrados a través del proceso de ajuste fino.

El conjunto de datos de referencia STS consiste en pares de frases en inglés, cada uno asociado con una puntuación de similitud. Durante el proceso de entrenamiento del modelo, evaluamos el rendimiento del modelo en este conjunto de referencia. Las puntuaciones persistidas para cada ejecución de entrenamiento son la correlación de Pearson entre las puntuaciones de similitud predichas y las puntuaciones de similitud reales en el conjunto de datos.

Estas puntuaciones aseguran que a medida que el modelo se ajusta finamente con nuestros datos de entrenamiento específicos del contexto, mantiene cierto nivel de generalización.

# Carga el módulo Universal Sentence Encoder Multilingual de TensorFlow Hub.base_model_url = "https://tfhub.dev/google/universal-sentence-encoder-multilingual/3"base_model = tf.keras.Sequential([    hub.KerasLayer(base_model_url,                   input_shape=[],                   dtype=tf.string,                   trainable=False)])# Define una lista de frases de prueba. Estas frases representan diversos títulos de trabajo.test_text = ['Data Scientist', 'Data Analyst', 'Data Engineer',             'Nurse Practitioner', 'Registered Nurse', 'Medical Assistant',             'Social Media Manager', 'Marketing Strategist', 'Product Marketing Manager']# Crea incrustaciones para las frases en la lista test_text. # La función np.array() se utiliza para convertir el resultado en una matriz numpy.# La función .tolist() se utiliza para convertir la matriz numpy en una lista, lo cual puede ser más fácil de trabajar.vectors = np.array(base_model.predict(test_text)).tolist()# Llama a la función plot_similarity para crear un gráfico de similitud.plot_similarity(test_text, vectors, 90, "modelo base")# Calcula la puntuación de referencia STS para el modelo basepearsonr = sts_benchmark(base_model)print("STS Benachmark: " + str(pearsonr))
Fig 5. Visualizaciones de similitud entre palabras de prueba

STS Benchmark (dev): 0.8325

Ajuste fino del modelo

El siguiente paso implica construir la arquitectura del modelo siamés utilizando el modelo de línea base y ajustarlo finamente con nuestros datos específicos del dominio.

# Carga el modelo de incrustación de palabras pre-entrenadoembedding_layer = hub.load(base_model_url)# Crea una capa de Keras a partir del modelo de incrustación cargado.shared_embedding_layer = hub.KerasLayer(embedding_layer, trainable=True)# Define las entradas para el modeloleft_input = keras.Input(shape=(), dtype=tf.string)right_input = keras.Input(shape=(), dtype=tf.string)# Pasa las entradas a través de la capa de incrustación compartidaembedding_left_output = shared_embedding_layer(left_input)embedding_right_output = shared_embedding_layer(right_input)# Calcula la similitud coseno entre los vectores de incrustacióncosine_similarity = tf.keras.layers.Dot(axes=-1, normalize=True)(    [embedding_left_output, embedding_right_output])# Convierte la similitud coseno en distancia angularpi = tf.constant(math.pi, dtype=tf.float32)clip_cosine_similarities = tf.clip_by_value(    cosine_similarity, -0.99999, 0.99999)acos_distance = 1.0 - (tf.acos(clip_cosine_similarities) / pi)# Empaqueta el modeloencoder = tf.keras.Model([left_input, right_input], acos_distance)# Compila el modeloencoder.compile(    optimizer=tf.keras.optimizers.Adam(        learning_rate=0.00001,        beta_1=0.9,        beta_2=0.9999,        epsilon=0.0000001,        amsgrad=False,        clipnorm=1.0,        name="Adam",    ),    loss=tf.keras.losses.MeanSquaredError(        reduction=keras.losses.Reduction.AUTO, name="mean_squared_error"    ),    metrics=[        tf.keras.metrics.MeanAbsoluteError(),        tf.keras.metrics.MeanAbsolutePercentageError(),    ],)# Imprime el resumen del modeloencoder.summary()
Fig 6. Arquitectura del modelo para ajuste fino

Ajuste del modelo

# Define el callback de detención tempranaearly_stop = keras.callbacks.EarlyStopping(    monitor="loss", patience=3, min_delta=0.001)# Define el callback de TensorBoardlogdir = os.path.join(".", "logs/fit/" + datetime.now().strftime("%Y%m%d-%H%M%S"))tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)# Entrada del modeloleft_inputs, right_inputs, similarity = process_model_input(data)# Entrena el modelo encoderhistory = encoder.fit(    [left_inputs, right_inputs],    similarity,    batch_size=8,    epochs=20,    validation_split=0.2,    callbacks=[early_stop, tensorboard_callback],)# Define la entrada del modeleinputs = keras.Input(shape=[], dtype=tf.string)# Pasa la entrada a través de la capa de incrustaciónembedding = hub.KerasLayer(embedding_layer)(inputs)# Crea el modelo ajustadotuned_model = keras.Model(inputs=inputs, outputs=embedding)

Evaluación

Ahora que tenemos el modelo ajustado, vamos a volver a evaluarlo y comparar los resultados con los del modelo base.

# Crea embeddings para las oraciones en la lista test_text. # La función np.array() se utiliza para convertir el resultado en un arreglo de numpy.# La función .tolist() se utiliza para convertir el arreglo de numpy en una lista, que puede ser más fácil de trabajar.vectors = np.array(tuned_model.predict(test_text)).tolist()# Llama a la función plot_similarity para crear un gráfico de similitud.plot_similarity(test_text, vectors, 90, "modelo ajustado")# Calcula el puntaje de referencia STS para el modelo ajustadopearsonr = sts_benchmark(tuned_model)print("STS Benachmark: " + str(pearsonr))

STS Benchmark (dev): 0.8349

Basado en el ajuste fino del modelo en el conjunto de datos relativamente pequeño, el puntaje de referencia STS es comparable al del modelo base, lo que indica que el modelo ajustado todavía muestra generalizabilidad. Sin embargo, la visualización de similitud muestra puntajes de similitud más fuertes entre títulos similares y una reducción en los puntajes para los que no son similares.

Reflexiones Finales

El ajuste fino de modelos pre-entrenados de procesamiento del lenguaje natural para la adaptación de dominio es una técnica poderosa para mejorar su rendimiento y precisión en contextos específicos. Al utilizar conjuntos de datos de calidad específicos del dominio y aprovechar las redes neuronales siamesas, podemos mejorar la capacidad del modelo para capturar similitud semántica.

Este tutorial proporcionó una guía paso a paso del proceso de ajuste fino, utilizando el modelo Universal Sentence Encoder (USE) como ejemplo. Exploramos el marco teórico, la preparación de datos, la evaluación del modelo base y el proceso de ajuste fino real. Los resultados demostraron la efectividad del ajuste fino para fortalecer los puntajes de similitud dentro de un dominio.

Al seguir este enfoque y adaptarlo a su dominio específico, puede aprovechar todo el potencial de los modelos pre-entrenados de procesamiento del lenguaje natural y obtener mejores resultados en sus tareas de procesamiento del lenguaje natural.

Gracias por leer. Si tienes algún comentario, no dudes en hacerlo en esta publicación, enviarme un mensaje en LinkedIn o escribirme un correo electrónico (smhkapadia[at]gmail.com)

Si te gustó este artículo, visita mis otros artículos

Evaluar Modelos de Temas: Latent Dirichlet Allocation (LDA)

Una guía paso a paso para construir modelos de temas interpretables

towardsdatascience.com

La Evolución del Procesamiento del Lenguaje Natural

Una Perspectiva Histórica sobre el Desarrollo de los Modelos de Lenguaje

Zepes.com

Sistema de Recomendación en Python: LightFM

Una guía paso a paso para construir un sistema de recomendación en Python utilizando LightFM

towardsdatascience.com