# Múltipla escolha

Uma tarefa de múltipla escolha é semelhante à resposta a perguntas, exceto que várias respostas candidatas são fornecidas junto com um contexto e o modelo é treinado para selecionar a resposta correta.

Este guia mostrará como:

1. Ajuste o [BERT](https://huggingface.co/google-bert/bert-base-uncased) na configuração `regular` do conjunto de dados [SWAG](https://huggingface.co/datasets/allenai/swag) para selecionar a melhor resposta dado um conjunto de opções e algum contexto.
2. Use seu modelo ajustado para inferência.

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 SWAG

Comece carregando a configuração `regular` do conjunto de dados SWAG a partir da biblioteca 🤗 Datasets:

```py
>>> from datasets import load_dataset

>>> swag = load_dataset("allenai/swag", "regular")
```

Em seguida, veja um exemplo:

```py
>>> swag["train"][0]
{'ending0': 'passes by walking down the street playing their instruments.',
 'ending1': 'has heard approaching them.',
 'ending2': "arrives and they're outside dancing and asleep.",
 'ending3': 'turns the lead singer watches the performance.',
 'fold-ind': '3416',
 'gold-source': 'gold',
 'label': 0,
 'sent1': 'Members of the procession walk down the street holding small horn brass instruments.',
 'sent2': 'A drum line',
 'startphrase': 'Members of the procession walk down the street holding small horn brass instruments. A drum line',
 'video-id': 'anetv_jkn6uvmqwh4'}
```

Embora pareça haver muitos campos aqui, na verdade é bastante direto:

- `sent1` e `sent2`: esses campos mostram como uma frase começa, e se você juntar os dois, obtém o campo `startphrase`.
- `ending`: sugere um possível final para como uma frase pode terminar, mas apenas um deles está correto.
- `label`: identifica o final correto da frase.

## Pré-processar

A próxima etapa é carregar um tokenizer BERT para processar o início da frase e os quatro possíveis finais:

```py
>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
```

A função de pré-processamento que você deseja criar precisa:

1. Faça quatro cópias do campo `sent1` e combine cada uma delas com `sent2` para recriar como uma frase começa.
2. Combine `sent2` com cada um dos quatro possíveis finais de frase.
3. Achate essas duas listas para que você possa tokenizá-las e, em seguida, desachate-as para que cada exemplo tenha os campos `input_ids`, `attention_mask` e `labels` correspondentes.

```py
>>> ending_names = ["ending0", "ending1", "ending2", "ending3"]

>>> def preprocess_function(examples):
...     first_sentences = [[context] * 4 for context in examples["sent1"]]
...     question_headers = examples["sent2"]
...     second_sentences = [
...         [f"{header} {examples[end][i]}" for end in ending_names] for i, header in enumerate(question_headers)
...     ]

...     first_sentences = sum(first_sentences, [])
...     second_sentences = sum(second_sentences, [])

...     tokenized_examples = tokenizer(first_sentences, second_sentences, truncation=True)
...     return {k: [v[i : i + 4] for i in range(0, len(v), 4)] for k, v in tokenized_examples.items()}
```

Para aplicar a 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:

```py
>>> tokenized_swag = swag.map(preprocess_function, batched=True)
```

Para criar um lote de exemplos, é mais eficiente *aplicar padding dinamicamente* nas frases até o comprimento mais longo dentro do lote durante a colação, em vez de aplicar padding em todo o conjunto de dados até o comprimento máximo. [DataCollatorForMultipleChoice](/docs/transformers/main/pt/main_classes/data_collator#transformers.DataCollatorForMultipleChoice) aplaina todas as entradas do modelo, aplica o padding e, em seguida, desaplaina os resultados.

```py
>>> from transformers import DataCollatorForMultipleChoice
>>> collator = DataCollatorForMultipleChoice(tokenizer=tokenizer)
```

## Avaliar

Incluir uma métrica durante o treinamento é frequentemente útil para avaliar o desempenho do seu modelo. Você pode carregar rapidamente um método de avaliação com a biblioteca 🤗 [Evaluate](https://huggingface.co/docs/evaluate/index). Para esta tarefa, carregue a métrica [accuracy](https://huggingface.co/spaces/evaluate-metric/accuracy) (veja o [quick tour](https://huggingface.co/docs/evaluate/a_quick_tour) do 🤗 Evaluate para saber mais sobre como carregar e calcular uma métrica):

```py
>>> import evaluate

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

Em seguida, crie uma função que passa suas previsões e rótulos para [compute](https://huggingface.co/docs/evaluate/main/en/package_reference/main_classes#evaluate.EvaluationModule.compute) para calcular a precisão:

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

Sua função `compute_metrics` está pronta para uso e você voltará a ela ao configurar o treinamento.

## 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 [aqui](../training)!

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

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

>>> model = AutoModelForMultipleChoice.from_pretrained("google-bert/bert-base-uncased")
```

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` (é necessário estar conectado ao Hugging Face para enviar seu modelo). No final de cada epoch, o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) avaliará a precisão e salvará o checkpoint de treinamento.
2. Passe os argumentos de treinamento para o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) junto com o modelo, o conjunto de dados, o tokenizer, o data collator e a função `compute_metrics`.
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_swag_model",
...     eval_strategy="epoch",
...     save_strategy="epoch",
...     load_best_model_at_end=True,
...     learning_rate=5e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     num_train_epochs=3,
...     weight_decay=0.01,
...     push_to_hub=True,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=tokenized_swag["train"],
...     eval_dataset=tokenized_swag["validation"],
...     processing_class=tokenizer,
...     data_collator=collator,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()
```

Quando o treinamento for concluído, 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 usá-lo:

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

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

## Inferência

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

Crie um texto e duas respostas candidatas:

```py
>>> prompt = "France has a bread law, Le Décret Pain, with strict rules on what is allowed in a traditional baguette."
>>> candidate1 = "The law does not apply to croissants and brioche."
>>> candidate2 = "The law applies to baguettes."
```

Tokenize cada par de prompt e resposta candidata e retorne tensores do PyTorch. Você também deve criar alguns `labels`:

```py
>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_swag_model")
>>> inputs = tokenizer([[prompt, candidate1], [prompt, candidate2]], return_tensors="pt", padding=True)
>>> labels = torch.tensor(0).unsqueeze(0)
```

Passe seus dados de entrada e rótulos para o modelo e retorne os `logits`:

```py
>>> from transformers import AutoModelForMultipleChoice

>>> model = AutoModelForMultipleChoice.from_pretrained("username/my_awesome_swag_model")
>>> outputs = model(**{k: v.unsqueeze(0) for k, v in inputs.items()}, labels=labels)
>>> logits = outputs.logits
```

Obtenha a classe com a maior probabilidade:

```py
>>> predicted_class = logits.argmax().item()
>>> predicted_class
0
```

