Transformers documentation
Clasificación de texto
Clasificación de texto
La clasificación de texto es una tarea común de PLN que asigna una etiqueta o clase a un texto. Algunas de las empresas más grandes ejecutan la clasificación de texto en producción para una amplia gama de aplicaciones prácticas. Una de las formas más populares de clasificación de texto es el análisis de sentimiento, que asigna una etiqueta como 🙂 positivo, 🙁 negativo o 😐 neutral a una secuencia de texto.
Esta guía le mostrará cómo:
- Ajusta DistilBERT en el conjunto de datos IMDb para determinar si una reseña de película es positiva o negativa.
- Usa tu modelo afinado para la inferencia.
Para ver todas las arquitecturas y puntos de control compatibles con esta tarea, recomendamos consultar la página de la tarea.
Antes de comenzar, asegúrate de tener instaladas todas las bibliotecas necesarias:
pip install transformers datasets evaluate accelerate
Te animamos a iniciar sesión en tu cuenta de Hugging Face para que puedas subir y compartir tu modelo con la comunidad. Cuando se te solicite, introduce tu token para iniciar sesión:
>>> from huggingface_hub import notebook_login
>>> notebook_login()Cargar el conjunto de datos IMDb
Comience cargando el conjunto de datos IMDb desde la biblioteca 🤗 Datasets:
>>> from datasets import load_dataset
>>> imdb = load_dataset("stanfordnlp/imdb")A continuación, echa un vistazo a un ejemplo:
>>> imdb["test"][0]
{
"label": 0,
"text": "I love sci-fi and am willing to put up with a lot. Sci-fi movies/TV are usually underfunded, under-appreciated and misunderstood. I tried to like this, I really did, but it is to good TV sci-fi as Babylon 5 is to Star Trek (the original). Silly prosthetics, cheap cardboard sets, stilted dialogues, CG that doesn't match the background, and painfully one-dimensional characters cannot be overcome with a 'sci-fi' setting. (I'm sure there are those of you out there who think Babylon 5 is good sci-fi TV. It's not. It's clichéd and uninspiring.) While US viewers might like emotion and character development, sci-fi is a genre that does not take itself seriously (cf. Star Trek). It may treat important issues, yet not as a serious philosophy. It's really difficult to care about the characters here as they are not simply foolish, just missing a spark of life. Their actions and reactions are wooden and predictable, often painful to watch. The makers of Earth KNOW it's rubbish as they have to always say \"Gene Roddenberry's Earth...\" otherwise people would not continue watching. Roddenberry's ashes must be turning in their orbit as this dull, cheap, poorly edited (watching it without advert breaks really brings this home) trudging Trabant of a show lumbers into space. Spoiler. So, kill off a main character. And then bring him back as another actor. Jeeez! Dallas all over again.",
}Este conjunto de datos tiene dos campos:
text: el texto de la reseña de la película.label: un valor que es0para una reseña negativa o1para una reseña positiva.
Preprocesar
El siguiente paso es cargar un tokenizador de DistilBERT para preprocesar el campo text:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")Cree una función de preprocesamiento para tokenizar text y truncar las secuencias para que no superen la longitud máxima de entrada de DistilBERT:
>>> def preprocess_function(examples):
... return tokenizer(examples["text"], truncation=True)Para aplicar la función de preprocesamiento a todo el conjunto de datos, use la función map de 🤗 Datasets. Puede acelerar map estableciendo batched=True para procesar varios elementos del conjunto de datos a la vez:
tokenized_imdb = imdb.map(preprocess_function, batched=True)Ahora crea un lote de ejemplos usando DataCollatorWithPadding. Es más eficiente rellenar dinámicamente las oraciones hasta la longitud más larga dentro de un lote durante la agrupación, en lugar de rellenar todo el conjunto de datos hasta la longitud máxima.
>>> from transformers import DataCollatorWithPadding
>>> data_collator = DataCollatorWithPadding(tokenizer=tokenizer)Evaluar
Incluir una métrica durante el entrenamiento suele ser útil para evaluar el rendimiento de tu modelo. Puedes cargar rápidamente un método de evaluación con la biblioteca 🤗 Evaluate. Para esta tarea, carga la métrica accuracy (consulta el quick tour de 🤗 Evaluate para saber más sobre cómo cargar y calcular una métrica):
>>> import evaluate
>>> accuracy = evaluate.load("accuracy")Luego, crea una función que pase tus predicciones y etiquetas a compute para calcular la precisión:
>>> import numpy as np
>>> def compute_metrics(eval_pred):
... predictions, labels = eval_pred
... predictions = np.argmax(predictions, axis=1)
... return accuracy.compute(predictions=predictions, references=labels)Tu función compute_metrics ya está lista y volverás a ella cuando configures el entrenamiento.
Entrenar
Antes de comenzar a entrenar tu modelo, crea un mapa de los ids esperados a sus etiquetas con id2label y label2id:
>>> id2label = {0: "NEGATIVE", 1: "POSITIVE"}
>>> label2id = {"NEGATIVE": 0, "POSITIVE": 1}Si no está familiarizado con el ajuste fino de un modelo con Trainer, ¡eche un vistazo al tutorial básico aquí!
¡Ya estás listo para comenzar a entrenar tu modelo! Carga DistilBERT con AutoModelForSequenceClassification, junto con el número de etiquetas esperadas y los mapeos de etiquetas:
>>> from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer
>>> model = AutoModelForSequenceClassification.from_pretrained(
... "distilbert/distilbert-base-uncased", num_labels=2, id2label=id2label, label2id=label2id
... )En este punto, solo quedan tres pasos:
- Define los hiperparámetros de entrenamiento en TrainingArguments. El único parámetro obligatorio es
output_dir, que especifica dónde se guardará el modelo. Subirás este modelo al Hub estableciendopush_to_hub=True(debes iniciar sesión en Hugging Face para subir tu modelo). Al final de cada época, Trainer evaluará la precisión y guardará el punto de control de entrenamiento. - Pasa los argumentos de entrenamiento a Trainer junto con el modelo, el conjunto de datos, el tokenizador, el data collator y la función
compute_metrics. - Llama a train() para ajustar tu modelo.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_model",
... learning_rate=2e-5,
... per_device_train_batch_size=16,
... per_device_eval_batch_size=16,
... num_train_epochs=2,
... weight_decay=0.01,
... eval_strategy="epoch",
... save_strategy="epoch",
... load_best_model_at_end=True,
... push_to_hub=True,
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=tokenized_imdb["train"],
... eval_dataset=tokenized_imdb["test"],
... processing_class=tokenizer,
... data_collator=data_collator,
... compute_metrics=compute_metrics,
... )
>>> trainer.train()Trainer aplica relleno dinámico de forma predeterminada cuando se le pasa
tokenizer. En este caso, no es necesario especificar un data collator de forma explícita.
Una vez completado el entrenamiento, comparte tu modelo en el Hub con el método push_to_hub() para que todo el mundo pueda usarlo:
>>> trainer.push_to_hub()Para un ejemplo más detallado sobre cómo ajustar un modelo para la clasificación de texto, consulte el cuaderno de PyTorch correspondiente.
Inferencia
Genial, ahora que has afinado un modelo, ¡puedes usarlo para inferencia!
Guarda el texto sobre el que deseas ejecutar la inferencia:
>>> text = "This was a masterpiece. Not completely faithful to the books, but enthralling from beginning to end. Might be my favorite of the three."La forma más sencilla de probar tu modelo afinado para inferencia es usarlo en un pipeline(). Crea una instancia de pipeline para el análisis de sentimiento con tu modelo y pásale tu texto:
>>> from transformers import pipeline
>>> classifier = pipeline("sentiment-analysis", model="stevhliu/my_awesome_model")
>>> classifier(text)
[{'label': 'POSITIVE', 'score': 0.9994940757751465}]También puedes replicar manualmente los resultados de pipeline si lo deseas:
Tokeniza el texto y devuelve tensores de PyTorch:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model")
>>> inputs = tokenizer(text, return_tensors="pt")Pasa tus entradas al modelo y devuelve los logits:
>>> import torch
>>> from transformers import AutoModelForSequenceClassification
>>> model = AutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model")
>>> with torch.no_grad():
... logits = model(**inputs).logitsObtén la clase con la probabilidad más alta y usa el mapeo id2label del modelo para convertirla en una etiqueta de texto:
>>> predicted_class_id = logits.argmax().item()
>>> model.config.id2label[predicted_class_id]
'POSITIVE'