Transformers documentation
Modelado de lenguaje causal
Modelado de lenguaje causal
Existen dos tipos de modelado de lenguaje: causal y enmascarado. Esta guía ilustra el modelado de lenguaje causal. Los modelos de lenguaje causal se utilizan con frecuencia para la generación de texto. Puede utilizar estos modelos para aplicaciones creativas, como elegir su propia aventura de texto o un asistente de codificación inteligente como Copilot o CodeParrot.
El modelado de lenguaje causal predice el siguiente token en una secuencia de tokens, y el modelo solo puede prestar atención a los tokens de la izquierda. Esto significa que el modelo no puede ver tokens futuros. GPT-2 es un ejemplo de un modelo de lenguaje causal.
Esta guía le mostrará cómo:
- Ajusta DistilGPT2 en el subconjunto r/askscience del conjunto de datos ELI5.
- 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
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 ELI5
Comience cargando los primeros 5000 ejemplos del conjunto de datos ELI5-Category con la biblioteca 🤗 Datasets. Esto le dará la oportunidad de experimentar y asegurarse de que todo funcione antes de dedicar más tiempo a entrenar con el conjunto de datos completo.
>>> from datasets import load_dataset
>>> eli5 = load_dataset("dany0407/eli5_category", split="train[:5000]")Divide la partición train del conjunto de datos en un conjunto de entrenamiento y uno de prueba con el método train_test_split:
>>> eli5 = eli5.train_test_split(test_size=0.2)A continuación, echa un vistazo a un ejemplo:
>>> eli5["train"][0]
{'q_id': '7h191n',
'title': 'What does the tax bill that was passed today mean? How will it affect Americans in each tax bracket?',
'selftext': '',
'category': 'Economics',
'subreddit': 'explainlikeimfive',
'answers': {'a_id': ['dqnds8l', 'dqnd1jl', 'dqng3i1', 'dqnku5x'],
'text': ["The tax bill is 500 pages long and there were a lot of changes still going on right to the end. It's not just an adjustment to the income tax brackets, it's a whole bunch of changes. As such there is no good answer to your question. The big take aways are: - Big reduction in corporate income tax rate will make large companies very happy. - Pass through rate change will make certain styles of business (law firms, hedge funds) extremely happy - Income tax changes are moderate, and are set to expire (though it's the kind of thing that might just always get re-applied without being made permanent) - People in high tax states (California, New York) lose out, and many of them will end up with their taxes raised.",
'None yet. It has to be reconciled with a vastly different house bill and then passed again.',
'Also: does this apply to 2017 taxes? Or does it start with 2018 taxes?',
'This article explains both the House and senate bills, including the proposed changes to your income taxes based on your income level. URL_0'],
'score': [21, 19, 5, 3],
'text_urls': [[],
[],
[],
['https://www.investopedia.com/news/trumps-tax-reform-what-can-be-done/']]},
'title_urls': ['url'],
'selftext_urls': ['url']}Aunque esto puede parecer mucho, en realidad solo te interesa el campo text. Lo interesante de las tareas de modelado de lenguaje es que no necesitas etiquetas (también conocidas como tareas no supervisadas), porque la siguiente palabra es la etiqueta.
Preprocesar
El siguiente paso es cargar un tokenizador de DistilGPT2 para procesar el subcampo text:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilgpt2")Como se observa en el ejemplo anterior, el campo text está anidado dentro de answers. Esto significa que deberá
extraer el subcampo text de su estructura anidada mediante el método flatten:
>>> eli5 = eli5.flatten()
>>> eli5["train"][0]
{'q_id': '7h191n',
'title': 'What does the tax bill that was passed today mean? How will it affect Americans in each tax bracket?',
'selftext': '',
'category': 'Economics',
'subreddit': 'explainlikeimfive',
'answers.a_id': ['dqnds8l', 'dqnd1jl', 'dqng3i1', 'dqnku5x'],
'answers.text': ["The tax bill is 500 pages long and there were a lot of changes still going on right to the end. It's not just an adjustment to the income tax brackets, it's a whole bunch of changes. As such there is no good answer to your question. The big take aways are: - Big reduction in corporate income tax rate will make large companies very happy. - Pass through rate change will make certain styles of business (law firms, hedge funds) extremely happy - Income tax changes are moderate, and are set to expire (though it's the kind of thing that might just always get re-applied without being made permanent) - People in high tax states (California, New York) lose out, and many of them will end up with their taxes raised.",
'None yet. It has to be reconciled with a vastly different house bill and then passed again.',
'Also: does this apply to 2017 taxes? Or does it start with 2018 taxes?',
'This article explains both the House and senate bills, including the proposed changes to your income taxes based on your income level. URL_0'],
'answers.score': [21, 19, 5, 3],
'answers.text_urls': [[],
[],
[],
['https://www.investopedia.com/news/trumps-tax-reform-what-can-be-done/']],
'title_urls': ['url'],
'selftext_urls': ['url']}Cada subcampo ahora es una columna separada, como lo indica el prefijo answers, y el campo text ahora es una lista. En lugar de tokenizar cada oración por separado, convierta la lista en una cadena para poder tokenizarlas conjuntamente.
Aquí hay una primera función de preprocesamiento para unir la lista de cadenas de cada ejemplo y tokenizar el resultado:
>>> def preprocess_function(examples):
... return tokenizer([" ".join(x) for x in examples["answers.text"]])Para aplicar esta función de preprocesamiento a todo el conjunto de datos, utiliza el método map de 🤗 Datasets. Puedes acelerar la función map estableciendo batched=True para procesar varios elementos del conjunto de datos a la vez, y aumentando el número de procesos con num_proc. Elimina las columnas que no necesites:
>>> tokenized_eli5 = eli5.map(
... preprocess_function,
... batched=True,
... num_proc=4,
... remove_columns=eli5["train"].column_names,
... )Este conjunto de datos contiene las secuencias de tokens, pero algunas de ellas son más largas que la longitud máxima de entrada del modelo.
Ahora puede usar una segunda función de preprocesamiento para
- concatenar todas las secuencias
- divida las secuencias concatenadas en fragmentos más cortos definidos por
block_size, que deben ser más cortos que la longitud máxima de entrada y lo suficientemente cortos para la RAM de su GPU.
>>> block_size = 128
>>> def group_texts(examples):
... # Concatenate all texts.
... concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
... total_length = len(concatenated_examples[list(examples.keys())[0]])
... # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
... # customize this part to your needs.
... if total_length >= block_size:
... total_length = (total_length // block_size) * block_size
... # Split by chunks of block_size.
... result = {
... k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
... for k, t in concatenated_examples.items()
... }
... result["labels"] = result["input_ids"].copy()
... return resultAplicar la función group_texts sobre el conjunto de datos completo:
>>> lm_dataset = tokenized_eli5.map(group_texts, batched=True, num_proc=4)Ahora crea un lote de ejemplos usando DataCollatorForLanguageModeling. Es más eficiente rellenar dinámicamente las oraciones hasta la longitud máxima del lote durante la agrupación, en lugar de rellenar todo el conjunto de datos hasta la longitud máxima.
Utilice el token de fin de secuencia como token de relleno y establezca mlm=False. Esto usará las entradas como etiquetas desplazadas a la derecha un elemento:
>>> from transformers import DataCollatorForLanguageModeling
>>> tokenizer.pad_token = tokenizer.eos_token
>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)Entrenar
Si no estás familiarizado con el ajuste fino de un modelo con Trainer, ¡echa un vistazo al tutorial básico!
¡Ya estás listo para comenzar a entrenar tu modelo! Carga DistilGPT2 con AutoModelForCausalLM:
>>> from transformers import AutoModelForCausalLM, TrainingArguments, Trainer
>>> model = AutoModelForCausalLM.from_pretrained("distilbert/distilgpt2")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á tu modelo. Subirás este modelo al Hub configurandopush_to_hub=True(debes iniciar sesión en Hugging Face para subir tu modelo). - Pasa los argumentos de entrenamiento a Trainer junto con el modelo, los conjuntos de datos y el data collator.
- Llama a train() para ajustar tu modelo.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_eli5_clm-model",
... eval_strategy="epoch",
... learning_rate=2e-5,
... weight_decay=0.01,
... push_to_hub=True,
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=lm_dataset["train"],
... eval_dataset=lm_dataset["test"],
... data_collator=data_collator,
... processing_class=tokenizer,
... )
>>> trainer.train()Una vez completado el entrenamiento, utiliza el método evaluate() para evaluar tu modelo y obtener su perplejidad:
>>> import math
>>> eval_results = trainer.evaluate()
>>> print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}")
Perplexity: 49.61Luego, 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 el modelado de lenguaje causal, consulte el cuaderno de PyTorch correspondiente.
Inferencia
Genial, ahora que has afinado un modelo, ¡puedes usarlo para inferencia!
Piensa en un prompt del que te gustaría generar texto:
>>> prompt = "Somatic hypermutation allows the immune system to"La forma más sencilla de probar tu modelo afinado para inferencia es usarlo en un pipeline(). Crea una instancia de pipeline para la generación de texto con tu modelo y pásale tu texto:
>>> from transformers import pipeline
>>> generator = pipeline("text-generation", model="username/my_awesome_eli5_clm-model")
>>> generator(prompt)
[{'generated_text': "Somatic hypermutation allows the immune system to be able to effectively reverse the damage caused by an infection.\n\n\nThe damage caused by an infection is caused by the immune system's ability to perform its own self-correcting tasks."}]Tokeniza el texto y devuelve los input_ids como tensores de PyTorch:
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_eli5_clm-model")
>>> inputs = tokenizer(prompt, return_tensors="pt").input_idsUse el método generate() para generar texto. Para más detalles sobre las diferentes estrategias de generación de texto y los parámetros para controlar la generación, consulte la página Estrategias de generación de texto.
>>> from transformers import AutoModelForCausalLM
>>> model = AutoModelForCausalLM.from_pretrained("username/my_awesome_eli5_clm-model")
>>> outputs = model.generate(inputs, max_new_tokens=100, do_sample=True, top_k=50, top_p=0.95)Decodifica los ids de tokens generados de nuevo en texto:
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
["Somatic hypermutation allows the immune system to react to drugs with the ability to adapt to a different environmental situation. In other words, a system of 'hypermutation' can help the immune system to adapt to a different environmental situation or in some cases even a single life. In contrast, researchers at the University of Massachusetts-Boston have found that 'hypermutation' is much stronger in mice than in humans but can be found in humans, and that it's not completely unknown to the immune system. A study on how the immune system"]