Clasificación de texto

Cómo afinar un modelo de RoBERTa en español para clasificar las reseñas de Amazon

Lewis Tunstall

Open In Colab

Configuración

Si está ejecutando este notebook en Google Colab, ejecute la siguiente celda para instalar las bibliotecas que necesitamos:

!pip install transformers datasets

Para compartir tu modelo con la comunidad, primero crea una cuenta en elHugging Face Hub. A continuación, ejecute la siguiente celda y proporcione su nombre de usuario y contraseña para generar un token de autenticación:

# Esto sólo funciona en Google Colab! Para los notebooks normales, es necesario ejecutar esto en el terminal
!huggingface-cli login

Si no tienes instaladoGit LFS, puedes hacerlo descomentando y ejecutando la celda de abajo:

# !apt install git-lfs
# !git config --global user.email "you@example.com"
# !git config --global user.name "Your Name"

Cargar y explorar los datos

Utilizaremos 🤗 Datasets para cargar y procesar nuestro conjunto de datos. Si no está familiarizado con 🤗 Datasets, vea el siguiente vídeo :)

from IPython.display import YouTubeVideo

YouTubeVideo("_BZearw7f0w", width=600, height=400)
from datasets import load_dataset

dataset = load_dataset("amazon_reviews_multi", "es")
dataset
import random
import pandas as pd
from datasets import ClassLabel
from IPython.display import display, HTML

def show_random_elements(dataset, num_examples=10):
    "Taken from https://github.com/huggingface/notebooks/blob/master/examples/text_classification.ipynb"
    
    assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
    picks = []
    for _ in range(num_examples):
        pick = random.randint(0, len(dataset)-1)
        while pick in picks:
            pick = random.randint(0, len(dataset)-1)
        picks.append(pick)
    
    df = pd.DataFrame(dataset[picks])
    for column, typ in dataset.features.items():
        if isinstance(typ, ClassLabel):
            df[column] = df[column].transform(lambda i: typ.names[i])
    display(HTML(df.to_html()))

show_random_elements(dataset["train"])
dataset.set_format("pandas")
df = dataset["train"][:]
df.head()
df["product_category"].value_counts()
df["stars"].value_counts()
dataset.reset_format()

Fusionar las clasificaciones por estrellas

dataset = dataset.filter(lambda x : x["stars"] != 3)
def merge_star_ratings(examples):
    if examples["stars"] <= 2:
        label = 0
    else:
        label = 1
    return {"labels": label}
dataset = dataset.map(merge_star_ratings)
show_random_elements(dataset["train"], num_examples=3)

Tokenizar las reseñas

from transformers import AutoTokenizer

model_checkpoint = "BSC-TeMU/roberta-base-bne"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)

Tokenización de las reseñas

Para entender la siguiente sección, vea este breve vídeo sobre la tokenización:

YouTubeVideo("Yffk5aydLzg", width=600, height=400)
tokenizer.vocab_size
text = "¡hola, me llamo lewis!"
tokenized_text = tokenizer.encode(text)

for token in tokenized_text:
    print(token, tokenizer.decode([token]))
encoded_text = tokenizer(text, return_tensors="pt")
encoded_text
def tokenize_reviews(examples):
    return tokenizer(examples["review_body"], truncation=True)
columns = dataset["train"].column_names
columns.remove("labels")
encoded_dataset = dataset.map(tokenize_reviews, batched=True, remove_columns=columns)
encoded_dataset
encoded_dataset["train"][0]

Cargar el modelo preentrenado

from transformers import AutoModelForSequenceClassification

num_labels = 2
model = AutoModelForSequenceClassification.from_pretrained(model_checkpoint, num_labels=num_labels)

De las input IDs a los hidden states

outputs = model(**encoded_text)
outputs

Definir las métricas de rendimiento

from datasets import load_metric 

metric = load_metric("accuracy")
metric
import numpy as np

def compute_metrics(eval_pred):
    predictions, labels = eval_pred
    predictions = np.argmax(predictions, axis=1)
    return metric.compute(predictions=predictions, references=labels)

Afinar el modelo preentrenado

Si quiere entender más profundamente cómo funciona el Entrenador, vea el siguiente vídeo:

YouTubeVideo("nvBXf7s7vTI", width=600, height=400)
from transformers import TrainingArguments

model_name = model_checkpoint.split("/")[-1]

batch_size = 16
num_train_epochs=2
num_train_samples = 20_000
train_dataset = encoded_dataset["train"].shuffle(seed=42).select(range(num_train_samples))
logging_steps = len(train_dataset) // (2 * batch_size * num_train_epochs)

training_args = TrainingArguments(
    output_dir="results",
    num_train_epochs=num_train_epochs,     
    learning_rate=2e-5,
    per_device_train_batch_size=batch_size,
    per_device_eval_batch_size=batch_size,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch", 
    logging_steps=logging_steps,
    push_to_hub=True,
    push_to_hub_model_id=f"{model_name}-finetuned-amazon_reviews_multi"
)
from transformers import Trainer

trainer = Trainer(
    model=model, 
    args=training_args, 
    compute_metrics=compute_metrics,
    train_dataset=train_dataset,
    eval_dataset=encoded_dataset["validation"],
    tokenizer=tokenizer
)
trainer.train()

Empuje hacia el Hugging Face Hub

Para más detalles sobre el envío de modelos al Hub, vea el siguiente vídeo:

YouTubeVideo("A5IWIxsHLUw", width=600, height=400)
trainer.push_to_hub()

Descargue el modelo desde el Hub

from transformers import pipeline

model_checkpoint = "lewtun/roberta-base-bne-finetuned-amazon_reviews_multi"
pipe = pipeline("sentiment-analysis", model=model_checkpoint)
pipe("¡me encanta el ipad!")

Este notebook forma parte del curso de NLP de 0 a 100. Puedes encontrar el curso completoaquí.