# 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:

1. Ajusta [DistilBERT](https://huggingface.co/distilbert/distilbert-base-uncased) en el conjunto de datos [IMDb](https://huggingface.co/datasets/stanfordnlp/imdb) para determinar si una reseña de película es positiva o negativa.
2. 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](https://huggingface.co/tasks/text-classification).

Antes de comenzar, asegúrate de tener instaladas todas las bibliotecas necesarias:

```bash
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:

```py
>>> 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:

```py
>>> from datasets import load_dataset

>>> imdb = load_dataset("stanfordnlp/imdb")
```

A continuación, echa un vistazo a un ejemplo:

```py
>>> 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 es `0` para una reseña negativa o `1` para una reseña positiva.

## Preprocesar

El siguiente paso es cargar un tokenizador de DistilBERT para preprocesar el campo `text`:

```py
>>> 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:

```py
>>> 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](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.map) de 🤗 Datasets. Puede acelerar `map` estableciendo `batched=True` para procesar varios elementos del conjunto de datos a la vez:

```py
tokenized_imdb = imdb.map(preprocess_function, batched=True)
```

Ahora crea un lote de ejemplos usando [DataCollatorWithPadding](/docs/transformers/main/es/main_classes/data_collator#transformers.DataCollatorWithPadding). Es más eficiente *rellenar dinámicamente* las oraciones hasta la longitud más larga dentro de un lote durante la recopilación, en lugar de rellenar todo el conjunto de datos hasta la longitud máxima.

```py
>>> 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](https://huggingface.co/docs/evaluate/index). Para esta tarea, carga la métrica [accuracy](https://huggingface.co/spaces/evaluate-metric/accuracy) (consulta el [quick tour](https://huggingface.co/docs/evaluate/a_quick_tour) de 🤗 Evaluate para saber más sobre cómo cargar y calcular una métrica):

```py
>>> import evaluate

>>> accuracy = evaluate.load("accuracy")
```

Luego, crea una función que pase tus predicciones y etiquetas a [compute](https://huggingface.co/docs/evaluate/main/en/package_reference/main_classes#evaluate.EvaluationModule.compute) para calcular la precisión:

```py
>>> 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`:

```py
>>> id2label = {0: "NEGATIVE", 1: "POSITIVE"}
>>> label2id = {"NEGATIVE": 0, "POSITIVE": 1}
```

Si no estás familiarizado con el ajuste fino de un modelo con [Trainer](/docs/transformers/main/es/main_classes/trainer#transformers.Trainer), ¡echa un vistazo al tutorial básico [aquí](../training)!

¡Ya estás listo para comenzar a entrenar tu modelo! Carga DistilBERT con [AutoModelForSequenceClassification](/docs/transformers/main/es/model_doc/auto#transformers.AutoModelForSequenceClassification) junto con el número de etiquetas esperadas y los mapeos de etiquetas:

```py
>>> 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:

1. Define los hiperparámetros de entrenamiento en [TrainingArguments](/docs/transformers/main/es/main_classes/trainer#transformers.TrainingArguments). El único parámetro obligatorio es `output_dir`, que especifica dónde se guardará el modelo. Subirás este modelo al Hub configurando `push_to_hub=True` (debes iniciar sesión en Hugging Face para subir tu modelo). Al final de cada época, [Trainer](/docs/transformers/main/es/main_classes/trainer#transformers.Trainer) evaluará la precisión y guardará el punto de control de entrenamiento.
2. Pasa los argumentos de entrenamiento a [Trainer](/docs/transformers/main/es/main_classes/trainer#transformers.Trainer) junto con el modelo, el conjunto de datos, el tokenizador, el data collator y la función `compute_metrics`.
3. Llama a [train()](/docs/transformers/main/es/main_classes/trainer#transformers.Trainer.train) para ajustar tu modelo.

```py
>>> 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](/docs/transformers/main/es/main_classes/trainer#transformers.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()](/docs/transformers/main/es/main_classes/trainer#transformers.Trainer.push_to_hub) para que todo el mundo pueda usarlo:

```py
>>> 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](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/text_classification.ipynb) correspondiente.

## Inferencia

Genial, ahora que has afinado un modelo, ¡puedes usarlo para inferencia!

Guarda el texto sobre el que deseas ejecutar la inferencia:

```py
>>> 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()](/docs/transformers/main/es/main_classes/pipelines#transformers.pipeline). Crea una instancia de `pipeline` para el análisis de sentimiento con tu modelo y pásale tu texto:

```py
>>> 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:

```py
>>> 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`:

```py
>>> import torch
>>> from transformers import AutoModelForSequenceClassification

>>> model = AutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model")
>>> with torch.no_grad():
...     logits = model(**inputs).logits
```

Obtén la clase con la probabilidad más alta y usa el mapeo `id2label` del modelo para convertirla en una etiqueta de texto:

```py
>>> predicted_class_id = logits.argmax().item()
>>> model.config.id2label[predicted_class_id]
'POSITIVE'
```

