Transformers documentation

Выбор из нескольких вариантов

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Выбор из нескольких вариантов

Задача с множественным выбором похожа на задачу по ответам на вопросы, за исключением того, что вместе с контекстом предоставляется несколько вариантов ответа, а модель обучается выбирать правильный.

В этом руководстве показано, как:

  1. Настройте BERT на конфигурации regular набора данных SWAG, чтобы выбирать лучший ответ из нескольких вариантов с учётом контекста.
  2. Используйте вашу дообученную модель для инференса.

Прежде чем начать, убедитесь, что у вас установлены все необходимые библиотеки:

pip install transformers datasets evaluate

Мы рекомендуем вам войти в свой аккаунт Hugging Face, чтобы вы могли загрузить свою модель и поделиться ею с сообществом. При появлении запроса введите токен для входа:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

Загрузка набора данных SWAG

Начните с загрузки конфигурации regular набора данных SWAG из библиотеки 🤗 Datasets:

>>> from datasets import load_dataset

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

Теперь рассмотрим пример:

>>> 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'}

Хотя здесь много полей, на самом деле всё довольно просто:

  • sent1 и sent2: эти поля показывают, как начинается предложение, а если объединить их, получится поле startphrase.
  • ending: предлагает возможный вариант окончания предложения, но только один из них является правильным.
  • label: определяет правильный конец предложения.

Предобработка

Следующий шаг — загрузить токенизатор BERT для обработки начала предложения и четырёх возможных концов:

>>> from transformers import AutoTokenizer

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

Функция предобработки, которую вы хотите создать, должна:

  1. Создайте четыре копии поля sent1 и объедините каждую из них с sent2, чтобы воссоздать начало предложения.
  2. Соедините sent2 с каждым из четырёх возможных окончаний предложения.
  3. Выровняйте эти два списка, чтобы токенизировать их, а затем верните исходную структуру, чтобы у каждого примера были соответствующие поля input_ids, attention_mask и labels.
>>> 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()}

Чтобы применить функцию предобработки ко всему набору данных, используйте метод map библиотеки 🤗 Datasets. Вы можете ускорить работу функции map, установив batched=True, чтобы обрабатывать несколько элементов набора данных одновременно:

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

Чтобы создать батч примеров, эффективнее динамически дополнять предложения до максимальной длины в батче на этапе collation, чем дополнять весь датасет до максимальной длины. DataCollatorForMultipleChoice разворачивает все входные данные модели, применяет padding, а затем сворачивает результаты обратно.

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

Оценка

Добавление метрики в процесс обучения часто помогает оценить качество модели. Вы можете быстро загрузить метод оценки с помощью библиотеки 🤗 Evaluate. Для этой задачи загрузите метрику accuracy (ознакомьтесь с быстрым обзором 🤗 Evaluate, чтобы узнать, как загружать и вычислять метрики):

>>> import evaluate

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

Затем создайте функцию, которая передаёт ваши предсказания и метки в compute для вычисления точности:

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

Ваша функция compute_metrics готова, и вы вернётесь к ней при настройке обучения.

Обучение

Если вы не знакомы с дообучением модели с помощью Trainer, загляните в базовое руководство здесь!

Теперь вы готовы приступить к обучению модели! Загрузите BERT с помощью AutoModelForMultipleChoice:

>>> from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer

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

На этом этапе осталось выполнить только три шага:

  1. Определите гиперпараметры обучения в TrainingArguments. Единственный обязательный параметр — output_dir, который указывает, куда сохранять модель. Чтобы загрузить модель на Hub, установите push_to_hub=True (для загрузки модели необходимо войти в аккаунт Hugging Face). В конце каждой эпохи Trainer оценивает точность и сохраняет контрольную точку обучения.
  2. Передайте аргументы обучения в Trainer вместе с моделью, набором данных, токенизатором, data collator и функцией compute_metrics.
  3. Вызовите train(), чтобы дообучить модель.
>>> 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()

После завершения обучения используйте метод push_to_hub(), чтобы опубликовать модель на Hub и дать всем возможность её использовать:

>>> trainer.push_to_hub()

Более подробный пример того, как дообучить модель для задачи с множественным выбором, можно найти в соответствующем ноутбуке PyTorch.

Вывод

Отлично, теперь, когда вы дообучили модель, вы можете использовать её для инференса!

Придумайте какой-либо текст и два варианта ответа:

>>> 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."

Токенизируйте каждую пару «запрос — ответ» и верните тензоры PyTorch. Также необходимо создать некоторые labels:

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

Передайте входные данные и метки в модель и верните logits:

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

Получите класс с наибольшей вероятностью:

>>> predicted_class = logits.argmax().item()
>>> predicted_class
0
Update on GitHub