# Modelagem de linguagem causal

Existem dois tipos de modelagem de linguagem: causal e mascarada. Este guia ilustra a modelagem de linguagem causal. Os modelos de linguagem causal são frequentemente usados para geração de texto. Você pode usar esses modelos para aplicações criativas, como escolher sua própria aventura de texto ou um assistente de codificação inteligente como Copilot ou CodeParrot.

O modelamento de linguagem causal prevê o próximo token em uma sequência de tokens, e o modelo só pode prestar atenção aos tokens à esquerda. Isso significa que o modelo não consegue ver tokens futuros. O GPT-2 é um exemplo de modelo de linguagem causal.

Este guia mostrará como:

1. Ajuste fino de [DistilGPT2](https://huggingface.co/distilbert/distilgpt2) no subconjunto [r/askscience](https://www.reddit.com/r/askscience/) do conjunto de dados [ELI5](https://huggingface.co/datasets/dany0407/eli5_category).
2. Use seu modelo ajustado para inferência.

Para ver todas as arquiteturas e checkpoints compatíveis com esta tarefa, recomendamos consultar a [página da tarefa](https://huggingface.co/tasks/text-generation)

Antes de começar, verifique se você tem todas as bibliotecas necessárias instaladas:

```bash
pip install transformers datasets evaluate
```

Recomendamos que você faça login na sua conta do Hugging Face para que possa enviar e compartilhar seu modelo com a comunidade. Quando solicitado, insira seu token para fazer login:

```py
>>> from huggingface_hub import notebook_login

>>> notebook_login()
```

## Carregar o conjunto de dados ELI5

Comece carregando os primeiros 5000 exemplos do conjunto de dados [ELI5-Category](https://huggingface.co/datasets/dany0407/eli5_category) com a biblioteca 🤗 Datasets. Isso lhe dará a oportunidade de experimentar e garantir que tudo funcione antes de gastar mais tempo treinando no conjunto de dados completo.

```py
>>> from datasets import load_dataset

>>> eli5 = load_dataset("dany0407/eli5_category", split="train[:5000]")
```

Divida o split `train` do conjunto de dados em um conjunto de treinamento e um conjunto de teste com o método [train_test_split](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.train_test_split):

```py
>>> eli5 = eli5.train_test_split(test_size=0.2)
```

Em seguida, veja um exemplo:

```py
>>> 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']}
```

Embora isso possa parecer muito, você realmente se interessa apenas pelo campo `text`. O que é legal nas tarefas de modelagem de linguagem é que você não precisa de rótulos (também conhecida como tarefa não supervisionada), porque a próxima palavra *é* o rótulo.

## Pré-processar

O próximo passo é carregar um tokenizer DistilGPT2 para processar o subcampo `text`:

```py
>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilgpt2")
```

Você notará, pelo exemplo acima, que o campo `text` está, na verdade, aninhado dentro de `answers`. Isso significa que você precisará extrair o subcampo `text` de sua estrutura aninhada com o método [`flatten`](https://huggingface.co/docs/datasets/process#flatten):

```py
>>> 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 agora é uma coluna separada, conforme indicado pelo prefixo `answers`, e o campo `text` agora é uma lista. Em vez de tokenizar cada frase separadamente, converta a lista em uma string para que você possa tokenizá-las em conjunto.

Aqui está uma primeira função de pré-processamento para juntar a lista de strings de cada exemplo e tokenizar o resultado:

```py
>>> def preprocess_function(examples):
...     return tokenizer([" ".join(x) for x in examples["answers.text"]])
```

Para aplicar esta função de pré-processamento em todo o conjunto de dados, use o método [map](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.map) do 🤗 Datasets. Você pode acelerar a função `map` definindo `batched=True` para processar vários elementos do conjunto de dados de uma vez e aumentando o número de processos com `num_proc`. Remova quaisquer colunas que você não precise:

```py
>>> tokenized_eli5 = eli5.map(
...     preprocess_function,
...     batched=True,
...     num_proc=4,
...     remove_columns=eli5["train"].column_names,
... )
```

Este conjunto de dados contém as sequências de tokens, mas algumas delas são mais longas do que o comprimento máximo de entrada para o modelo.

Agora você pode usar uma segunda função de pré-processamento para

- concatenar todas as sequências
- divida as sequências concatenadas em blocos menores definidos por `block_size`, que devem ser mais curtos que o comprimento máximo de entrada e curtos o suficiente para a RAM da sua GPU.

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

Aplique a função `group_texts` em todo o conjunto de dados:

```py
>>> lm_dataset = tokenized_eli5.map(group_texts, batched=True, num_proc=4)
```

Agora crie um lote de exemplos usando [DataCollatorForLanguageModeling](/docs/transformers/main/pt/main_classes/data_collator#transformers.DataCollatorForLanguageModeling). É mais eficiente *preencher dinamicamente* as frases até o comprimento mais longo em um lote durante a colação, em vez de preencher todo o conjunto de dados até o comprimento máximo.

Use o token de fim de sequência como token de preenchimento e defina `mlm=False`. Isso usará as entradas como rótulos deslocados para a direita em um elemento:

```py
>>> from transformers import DataCollatorForLanguageModeling

>>> tokenizer.pad_token = tokenizer.eos_token
>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
```

## Treinar

Se você não está familiarizado com o ajuste fino de um modelo usando o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer), dê uma olhada no [tutorial básico](../training)!

Agora você está pronto para começar a treinar seu modelo! Carregue o DistilGPT2 com [AutoModelForCausalLM](/docs/transformers/main/pt/model_doc/auto#transformers.AutoModelForCausalLM):

```py
>>> from transformers import AutoModelForCausalLM, TrainingArguments, Trainer

>>> model = AutoModelForCausalLM.from_pretrained("distilbert/distilgpt2")
```

Neste ponto, restam apenas três etapas:

1. Defina os hiperparâmetros de treinamento em [TrainingArguments](/docs/transformers/main/pt/main_classes/trainer#transformers.TrainingArguments). O único parâmetro obrigatório é `output_dir`, que especifica onde salvar seu modelo. Você enviará este modelo para o Hub definindo `push_to_hub=True` (você precisa estar conectado ao Hugging Face para enviar seu modelo).
2. Passe os argumentos de treinamento para o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) junto com o modelo, os conjuntos de dados e o data collator.
3. Chame [train()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.train) para fazer o ajuste fino do seu modelo.

```py
>>> 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()
```

Após a conclusão do treinamento, use o método [evaluate()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.evaluate) para avaliar seu modelo e obter sua perplexidade:

```py
>>> import math

>>> eval_results = trainer.evaluate()
>>> print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}")
Perplexity: 49.61
```

Em seguida, compartilhe seu modelo no Hub com o método [push_to_hub()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.push_to_hub) para que todos possam usar seu modelo:

```py
>>> trainer.push_to_hub()
```

Para um exemplo mais detalhado de como fazer o ajuste fino de um modelo para modelagem de linguagem causal, consulte o [notebook do PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/language_modeling.ipynb) correspondente.

## Inferência

Ótimo, agora que você ajustou um modelo, pode usá-lo para inferência!

Crie um prompt do qual você gostaria de gerar texto:

```py
>>> prompt = "Somatic hypermutation allows the immune system to"
```

A maneira mais simples de testar seu modelo ajustado para inferência é usá-lo em um [pipeline()](/docs/transformers/main/pt/main_classes/pipelines#transformers.pipeline). Instancie um `pipeline` para geração de texto com seu modelo e passe seu texto para ele:

```py
>>> 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."}]
```

Tokenize o texto e retorne os `input_ids` como tensores do PyTorch:

```py
>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_eli5_clm-model")
>>> inputs = tokenizer(prompt, return_tensors="pt").input_ids
```

Use o método [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate) para gerar texto. Para mais detalhes sobre as diferentes estratégias de geração de texto e os parâmetros para controlar a geração, consulte a página [Estratégias de geração de texto](../generation_strategies).

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

Decodifique os ids de tokens gerados de volta para texto:

```py
>>> 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"]
```

