Aprenda a usar Transformers con Huggingface y Spacy

Introducción

La arquitectura de última generación para PNL y no solo. Modelos modernos como ChatGPT, Llama y Gemma se basan en esta arquitectura introducida en 2017 en la atención es todo lo que necesita papel de Vaswani et al.

En el artículo anteriorVimos cómo usar Spacy para realizar varias tareas, y es posible que haya notado que nunca tuvimos que entrenar nada, pero aprovechamos las capacidades de Spacy, que son principalmente enfoques basados ​​en reglas.

Spacy también ofrece insertar en los componentes capacitables de la tubería NLP o usar modelos fuera del estante desde el 🤗 HUB HUPGINGFACE, que es una plataforma en línea que proporciona modelos de código abierto para que los desarrolladores de IA lo usen.

¡Así que aprendamos a usar Spacy con los modelos de Hugging Face!

¿Por qué transformadores?

Antes de los transformadores, la arquitectura SOTA para crear representaciones vectoriales de palabras fue Vectores de palabras técnicas. Un vector de palabras es una representación densa de una palabra, que podemos usar para realizar algún cálculo matemático en ella.

Por ejemplo, podemos observar que dos palabras que tienen un significado similar también tienen vectores similares. Las técnicas más famosas de este tipo son Guante y Contenedor.

Sin embargo, estos métodos han introducido un gran problema, una palabra está representada siempre por el mismo vector. Pero una palabra no siempre tiene el mismo significado.

Por ejemplo:

  • “Ella fue al banco para retirar algo de dinero “.
  • “Se sentó por el banco del río, observando fluir el agua “.

En estas dos oraciones, la palabra banco asume dos significados diferentes, por lo que no tiene sentido representar siempre la palabra con el mismo vector.

Con la arquitectura basada en transformadores, hoy podemos crear modelos que tienen en cuenta todo el contexto para generar la representación vectorial de una palabra.

SRC: https://arxiv.org/abs/1706.03762

La principal innovación introducida por esta red es la bloque de atención múltiple. Si no está familiarizado con él, recientemente escribí un artículo sobre esto: https://towardsdatascience.com/a-simple-implementation-of-the-attention-mechanism-from-scratch/

El transformador está compuesto por dos partes. La parte izquierda, que es la codificador que crea la representación vectorial de los textos, y la parte correcta, la descifradorse usa para generar texto nuevo. Por ejemplo, GPT se basa en la parte correcta, porque genera texto como chatbot.

En este artículo, estamos interesados ​​en la parte del codificador, que puede capturar la semántica del texto que damos como entrada.

Bert y Roberta

Este no será un curso sobre estos modelos, pero recapitulemos algunos temas principales.

Mientras ChatGPT se basa en el lado decodificador de la arquitectura del transformador, Bert y Roberta se basan en el lado del codificador.

Bert fue presentado por Google en 2018 y puede leer más al respecto aquí: https://arxiv.org/abs/1810.04805

Bert es una pila de capas codificadoras. Hay dos tamaños de este modelo. La base de Bert contiene 12 codificadores, mientras que Bert grande contiene 24 codificadores

SRC: https://iq.opengenus.org/content/images/2021/01/bert-base-bert-large-coders.png

La base Bert genera un vector de tamaño 768, mientras que el grande es un vector de tamaño 1024. Ambos toman una entrada de tokens de tamaño 512.

El tokenizador utilizado por el modelo Bert se llama Obra de palabras.

Bert está entrenado en dos objetivos:

  • Modelado de lenguaje enmascarado (MLM): Predice tokens faltantes (enmascarados) dentro de una oración.
  • Predicción de la siguiente oración (NSP): Determina si una segunda oración dada sigue lógicamente la primera.

Roberta Model se basa en la parte superior de Bert con algunas diferencias clave: https://arxiv.org/abs/1907.11692.

Roberta usa un enmascaramiento dinámico, por lo que los tokens enmascarados cambian en cada iteración durante la capacitación, y no utiliza el NSP como objetivos de entrenamiento.

Usa Roberta con Spacy

El TextCategorizer es un componente espacial que predice una o más etiquetas para un documento completo. Puede funcionar en dos modalidades:

  • exclusive_classes = verdadero: una etiqueta por texto (por ejemplo, positivo o negativo)
  • exclusive_classes = falso: múltiples etiquetas por texto (por ejemplo, correo basura, urgente, facturación)

Spacy puede combinar esto con diferentes incrustaciones:

  • Vectores de palabras clásicas (tok2vec)
  • Modelos de transformadores como Robertaque usamos aquí

De esta manera, podemos lavar la comprensión de Roberta del idioma inglés e integrarlo en la tubería Spacy para que se prepare la producción.

Si tiene un conjunto de datos, puede entrenar aún más el modelo Roberta utilizando Spacy para ajustarlo en la tarea específica aguas abajo que está tratando de resolver.

Preparación de datos

En este artículo voy a usar el Conjunto de datos TRECque contiene corto preguntas. Cada pregunta está etiquetada con el tipo de respuesta que esperacomo:

Etiqueta Significado
Abbr Abreviatura
Descomunal Descripción / definición
Enty Entidad (cosa, objeto)
TARAREAR Humano (persona, grupo)
Loc Ubicación (lugar)
Numer Numérico (recuento, fecha, etc.)

Este es un ejemplo, donde esperamos como respuesta un nombre humano:

P (texto): “¿Quién escribió la Ilíada?”
A (etiqueta): “Hum”

Como de costumbre, comenzamos instalando las bibliotecas.

!pip install datasets==3.6.0
!pip install -U spacy[transformers]

Ahora necesitamos cargar preparar el conjunto de datos.

Con spacy.blank("en") Podemos crear un tubería espacial en blanco para inglés. No incluye ningún componente (como el etiquetador o el analizador). Es liviano y perfecto para convertir el texto crudo a Doc objetos sin cargar un modelo de idioma completo como lo hacemos con en_core_web_sm.

DocBin es una clase especial especial que almacena eficientemente muchos Doc Objetos en formato binario. Así es como Spacy espera que se guarden los datos de capacitación.

Una vez convertido y guardado como .spacy archivos, estos se pueden pasar directamente a spacy trainque es mucho más rápido que usar archivos JSON o texto simples.

Así que ahora este script para preparar el tren y el conjunto de datos de desarrollo deberían ser bastante sencillos.

from datasets import load_dataset
import spacy
from spacy.tokens import DocBin

# Load TREC dataset
dataset = load_dataset("trec")

# Get label names (e.g., ["DESC", "ENTY", "ABBR", ...])
label_names = dataset["train"].features["coarse_label"].names

# Create a blank English pipeline (no components yet)
nlp = spacy.blank("en")

# Convert Hugging Face examples into spaCy Docs and save as .spacy file
def convert_to_spacy(split, filename):
    doc_bin = DocBin()
    for example in split:
        text = example["text"]
        label = label_names[example["coarse_label"]]
        cats = {name: 0.0 for name in label_names}
        cats[label] = 1.0
        doc = nlp.make_doc(text)
        doc.cats = cats
        doc_bin.add(doc)
    doc_bin.to_disk(filename)

convert_to_spacy(dataset["train"], "train.spacy")
convert_to_spacy(dataset["test"], "dev.spacy")

Vamos a entrenar a Roberta en este conjunto de datos utilizando un comando SAPCY CLI. El comando espera un config.cfg Archivo donde describimos el tipo de entrenamiento, el modelo que estamos utilizando, el número de epohchs, etc.

Aquí está el archivo de configuración que utilicé para mis Pourpos de entrenamiento.

[paths]
train = ./train.spacy
dev = ./dev.spacy
vectors = null
init_tok2vec = null

[system]
gpu_allocator = "pytorch"
seed = 42

[nlp]
lang = "en"
pipeline = ["transformer", "textcat"]
batch_size = 32

[components]

[components.transformer]
factory = "transformer"

[components.transformer.model]
@architectures = "spacy-transformers.TransformerModel.v3"
name = "roberta-base"
tokenizer_config = {"use_fast": true}
transformer_config = {}
mixed_precision = false
grad_scaler_config = {}

[components.transformer.model.get_spans]
@span_getters = "spacy-transformers.strided_spans.v1"
window = 128
stride = 96

[components.textcat]
factory = "textcat"
scorer = {"@scorers": "spacy.textcat_scorer.v2"}
threshold = 0.5

[components.textcat.model]
@architectures = "spacy.TextCatEnsemble.v2"
nO = null

[components.textcat.model.linear_model]
@architectures = "spacy.TextCatBOW.v3"
ngram_size = 1
no_output_layer = true
exclusive_classes = true
length = 262144

[components.textcat.model.tok2vec]
@architectures = "spacy-transformers.TransformerListener.v1"
upstream = "transformer"
pooling = {"@layers": "reduce_mean.v1"}
grad_factor = 1.0

[corpora]

[corpora.train]
@readers = "spacy.Corpus.v1"
path = ${paths.train}

[corpora.dev]
@readers = "spacy.Corpus.v1"
path = ${paths.dev}

[training]
train_corpus = "corpora.train"
dev_corpus = "corpora.dev"
seed = ${system.seed}
gpu_allocator = ${system.gpu_allocator}
dropout = 0.1
accumulate_gradient = 1
patience = 1600
max_epochs = 10
max_steps = 2000
eval_frequency = 100
frozen_components = []
annotating_components = []

[training.optimizer]
@optimizers = "Adam.v1"
learn_rate = 0.00005
L2 = 0.01
grad_clip = 1.0
use_averages = false
eps = 1e-08
beta1 = 0.9
beta2 = 0.999
L2_is_weight_decay = true

[training.batcher]
@batchers = "spacy.batch_by_words.v1"
discard_oversize = false
tolerance = 0.2

[training.batcher.size]
@schedules = "compounding.v1"
start = 256
stop = 2048
compound = 1.001

[training.logger]
@loggers = "spacy.ConsoleLogger.v1"
progress_bar = true

[training.score_weights]
cats_score = 1.0

[initialize]
vectors = ${paths.vectors}
init_tok2vec = ${paths.init_tok2vec}
vocab_data = null
lookups = null

[initialize.components]
[initialize.tokenizer]

¡Asegúrese de tener una GPU a su disposición y lance el comando CLI de capacitación!

python —m spacy train config.cfg --output ./output --gpu-id 0

Verá la capacitación comenzando y puede monitorear la pérdida del componente TextCategorizer.

Solo para ser claros, somos capacitación aquí el TextCategorizer Componente, que es un pequeño jefe de red neuronal que recibe la representación del documento y aprende a predecir la etiqueta correcta.

Pero también somos ajustando a Roberta durante este entrenamiento. Eso significa que los pesos de Roberta se actualizan utilizando el conjunto de datos TREC, por lo que aprende cómo representar preguntas de entrada de una manera que sea más útil para la clasificación.

Una vez que el modelo está entrenado y guardado, ¡podemos usarlo en inferencia!

import spacy

nlp = spacy.load("output/model-best")

doc = nlp("What is the capital of Italy?")
print(doc.cats)

La salida debe ser algo similar a la siguiente

{'LOC': 0.98, 'HUM': 0.01, 'NUM': 0.0, …}

Pensamientos finales

Para recapitular, en esta publicación vimos cómo: Usar un conjunto de datos facial de abrazos con Spacy

  • Convertir los datos de clasificación de texto en .spacy formato
  • Configure una tubería completa con Roberta y textcat
  • Entrena y prueba tu modelo usando Spacy CLI

Este método funciona para cualquier tarea de clasificación de texto corta, correos electrónicos, boletos de soporte, revisiones de productos, preguntas frecuentes o incluso intentos de chatbot.