NLP Course documentation

Poniendo todo junto

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Poniendo todo junto

Ask a Question Open In Colab Open In Studio Lab

En las últimas secciones, hemos hecho nuestro mejor esfuerzo para realizar la mayor parte del trabajo a mano. Exploramos como funcionan los tokenizadores y vimos la tokenización, conversión a IDs de entrada, relleno, truncado, y máscaras de atención.

Sin embargo, como vimos en la sección 3, la API de transformadores 🤗 puede manejar todo esto por nosotros con una función de alto nivel la cual trataremos aquí. Cuando llamas a tu tokenizer directamente en una sentencia, obtienes entradas que están lista para pasar a tu modelo:

from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)

Aquí la variable model_inputs contiene todo lo necesario para que un modelo opere bien. Para DistilBERT, que incluye los IDs de entrada también como la máscara de atención. Otros modelos que aceptan entradas adicionales también tendrán las salidas del objeto tokenizer.

Como veremos en los ejemplos de abajo, este método es muy poderoso. Primero, puede tokenizar una sola secuencia:

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)

También maneja múltiples secuencias a la vez, sin cambios en la API:

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

model_inputs = tokenizer(sequences)

Puede rellenar de acuerdo a varios objetivos:

# Rellenar las secuencias hasta la mayor longitud de secuencia
model_inputs = tokenizer(sequences, padding="longest")

# Rellenar las secuencias hasta la máxima longitud del modelo
# (512 para BERT o DistilBERT)
model_inputs = tokenizer(sequences, padding="max_length")

# Rellenar las secuencias hasta la máxima longitud especificada
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)

También puede truncar secuencias:

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Truncar las secuencias más largas que la máxima longitud del modelo
# (512 para BERT o DistilBERT)
model_inputs = tokenizer(sequences, truncation=True)

# Truncar las secuencias más largas que la longitud especificada
model_inputs = tokenizer(sequences, max_length=8, truncation=True)

El objeto tokenizer puede manejar la conversión a tensores de frameworks específicos, los cuales pueden ser enviados directamente al modelo. Por ejemplo, en el siguiente código de ejemplo estamos solicitando al tokenizer que regrese los tensores de los distintos frameworks — "pt" regresa tensores de PyTorch, "tf" regresa tensores de TensorFlow, y "np" regresa arreglos de NumPy:

sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Devuelve tensores PyTorch
model_inputs = tokenizer(sequences, padding=True, return_tensors="pt")

# Devuelve tensores TensorFlow
model_inputs = tokenizer(sequences, padding=True, return_tensors="tf")

# Devuelve arrays Numpy
model_inputs = tokenizer(sequences, padding=True, return_tensors="np")

Tokens especiales

Si damos un vistazo a los IDs de entrada retornados por el tokenizer, veremos que son un poquito diferentes a lo que teníamos anteriormente:

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
print(model_inputs["input_ids"])

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)
[101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102]
[1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]

Se agregó un ID de token al principio, y uno al final. Decodifiquemos las dos secuencias de IDs de arriba para ver de que se trata:

print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))
"[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
"i've been waiting for a huggingface course my whole life."

El tokenizador agregó la palabra especial [CLS] al principio y la palabra especial [SEP] al final. Esto se debe a que el modelo fue preentrenado con esos, así para obtener los mismos resultados por inferencia necesitamos agregarlos también. Nota que algunos modelos no agregan palabras especiales, o agregan unas distintas; los modelos también pueden agregar estas palabras especiales sólo al principio, o sólo al final. En cualquier caso, el tokenizador sabe cuáles son las esperadas y se encargará de ello por tí.

Conclusión: Del tokenizador al modelo

Ahora que hemos visto todos los pasos individuales que el objeto tokenizer usa cuando se aplica a textos, veamos una última vez cómo maneja varias secuencias (¡relleno!), secuencias muy largas (¡truncado!), y múltiples tipos de tensores con su API principal:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)