다중 선택
다중 선택 과제는 질의응답과 유사하지만, 컨텍스트와 함께 여러 후보 답변이 제공되며 모델이 올바른 답변을 선택하도록 학습됩니다.
이 가이드에서는 다음 내용을 보여 드립니다:
- SWAG 데이터셋의
regular구성을 사용하여 여러 선택지와 일부 컨텍스트가 주어졌을 때 가장 적절한 답변을 선택하도록 BERT를 fine-tune합니다. - 파인튜닝한 모델을 추론에 사용하세요.
시작하기 전에 필요한 라이브러리가 모두 설치되어 있는지 확인하세요:
pip install transformers datasets evaluate
모델을 업로드하고 커뮤니티와 공유할 수 있도록 Hugging Face 계정에 로그인하는 것을 권장합니다. 프롬프트가 표시되면 로그인할 토큰을 입력하세요:
>>> from huggingface_hub import notebook_login
>>> notebook_login()SWAG 데이터셋 로드
🤗 Datasets 라이브러리에서 SWAG 데이터셋의 regular 구성을 로드하는 것으로 시작합니다:
>>> 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")만들려는 전처리 함수는 다음을 수행해야 합니다:
sent1필드를 4개의 사본으로 만들고, 각각을sent2와 결합하여 문장의 시작 방식을 재현합니다.sent2를 네 가지 가능한 문장 끝맺음 각각과 결합합니다.- 토큰화를 수행할 수 있도록 이 두 리스트를 flatten한 뒤, 각 예시에 해당하는
input_ids,attention_mask,labels필드가 있도록 unflatten합니다.
>>> 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()}전체 데이터셋에 전처리 함수를 적용하려면 🤗 Datasets의 map 메서드를 사용합니다. batched=True를 설정하여 데이터셋의 여러 요소를 한 번에 처리하면 map 함수의 속도를 높일 수 있습니다:
>>> tokenized_swag = swag.map(preprocess_function, batched=True)예시 배치(batch)를 생성할 때, 데이터셋 전체를 최대 길이에 맞게 패딩하는 것보다 collation 단계에서 배치 내 가장 긴 길이에 맞춰 문장을 동적으로 패딩하는 것이 더 효율적입니다. DataCollatorForMultipleChoice는 모든 모델 입력을 평탄화(flatten)하고, 패딩을 적용한 뒤 결과를 다시 원래 형태로 복원합니다.
>>> from transformers import DataCollatorForMultipleChoice
>>> collator = DataCollatorForMultipleChoice(tokenizer=tokenizer)평가
학습 중에 메트릭을 포함하는 것은 모델 성능을 평가하는 데 도움이 되는 경우가 많습니다. 🤗 Evaluate 라이브러리를 사용하면 평가 방법을 빠르게 로드할 수 있습니다. 이 작업에서는 accuracy 메트릭을 로드합니다(메트릭을 로드하고 계산하는 방법에 대해 자세히 알아보려면 🤗 Evaluate quick tour를 참고하세요):
>>> 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를 사용하여 모델을 fine-tuning하는 방법에 대해 잘 모르신다면, 여기의 기본 튜토리얼을 참고하세요!
이제 모델 학습을 시작할 준비가 되었습니다! AutoModelForMultipleChoice로 BERT를 로드하세요:
>>> from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer
>>> model = AutoModelForMultipleChoice.from_pretrained("google-bert/bert-base-uncased")이 시점에서 남은 단계는 단 세 가지입니다:
- TrainingArguments에서 학습 하이퍼파라미터를 정의합니다. 필수 파라미터는 모델 저장 위치를 지정하는
output_dir하나뿐입니다.push_to_hub=True를 설정하여 이 모델을 Hub에 업로드할 수 있습니다(모델 업로드를 위해 Hugging Face에 로그인되어 있어야 합니다). 각 epoch가 끝나면 Trainer가 정확도를 평가하고 학습 체크포인트를 저장합니다. - 모델, 데이터셋, 토크나이저, 데이터 콜레이터,
compute_metrics함수와 함께 학습 인수를 Trainer에 전달합니다. - 모델을 파인튜닝하려면 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 노트북을 참고하세요.
추론
좋습니다. 이제 모델을 fine-tuning 했으므로 추론에 사용할 수 있습니다!
일부 텍스트와 두 개의 후보 답변을 생각해 보세요:
>>> 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