HuggingFace Transformers 4.17 : ガイド : 下流タスク用の再調整 – 多岐選択 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/03/2022 (v4.17.0)
* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
- 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
- sales-info@classcat.com ; Web: www.classcat.com ; ClassCatJP
HuggingFace Transformers : ガイド : 下流タスク用の再調整 – 多岐選択
多岐選択タスクは、幾つかの回答候補がコンテキストと一緒に提供される点以外は、質問応答に似ています。モデルは、コンテキストが与えられたとき複数の入力から正しい回答を選択するように訓練されています。
このガイドは、複数の選択肢と幾つかのコンテキストが与えられたときに最善の答えを選択するように、SWAG データセットの通常の configuration で BERT を再調整する方法を示します。
SWAG データセットのロード
Datasets ライブラリから SWAG データセットをロードします :
そしてサンプルを見てみましょう :
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 フィールドはセンテンスがどのように始まるかを示し、各 ending フィールドはどのようにセンテンスが終了するかを示します。センテンスの始まりが与えられたとき、モデルは、label フィールドで示される、正しいセンテンスの終わりを選択しなければなりません。
前処理
各センテンスの開始と 4 つの可能な終わりを処理するために BERT トークナイザーをロードします :
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
前処理関数は以下が必要です :
- sent1 フィールドの 4 つのコピーを作成し、センテンスがどのように開始されるか再現するためにそれらの各々を sent2 と結合できるようにします。
- sent2 を 4 つの可能なセンテンスの終わりの各々と結合します。
- これらの 2 つのリストをトークン化できるように平坦化 (= 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)
Transformers は多岐選択のためのデータ collator 作成する必要があります。多岐選択のためのサンプルのバッチを作成するために DataCollatorWithPadding を使用できます。それはまたバッチ内の最長要素の長さにテキストとラベルを動的にパディングしますので、それらは均一な長さです。
DataCollatorForMultipleChoice は総てのモデル入力を平坦化し、パディングを適用し、そして結果を unflatten します :
from dataclasses import dataclass
from transformers.tokenization_utils_base import PreTrainedTokenizerBase, PaddingStrategy
from typing import Optional, Union
import torch
@dataclass
class DataCollatorForMultipleChoice:
"""
Data collator that will dynamically pad the inputs for multiple choice received.
"""
tokenizer: PreTrainedTokenizerBase
padding: Union[bool, str, PaddingStrategy] = True
max_length: Optional[int] = None
pad_to_multiple_of: Optional[int] = None
def __call__(self, features):
label_name = "label" if "label" in features[0].keys() else "labels"
labels = [feature.pop(label_name) for feature in features]
batch_size = len(features)
num_choices = len(features[0]["input_ids"])
flattened_features = [
[{k: v[i] for k, v in feature.items()} for i in range(num_choices)] for feature in features
]
flattened_features = sum(flattened_features, [])
batch = self.tokenizer.pad(
flattened_features,
padding=self.padding,
max_length=self.max_length,
pad_to_multiple_of=self.pad_to_multiple_of,
return_tensors="pt",
)
batch = {k: v.view(batch_size, num_choices, -1) for k, v in batch.items()}
batch["labels"] = torch.tensor(labels, dtype=torch.int64)
return batch
from dataclasses import dataclass
from transformers.tokenization_utils_base import PreTrainedTokenizerBase, PaddingStrategy
from typing import Optional, Union
import tensorflow as tf
@dataclass
class DataCollatorForMultipleChoice:
"""
Data collator that will dynamically pad the inputs for multiple choice received.
"""
tokenizer: PreTrainedTokenizerBase
padding: Union[bool, str, PaddingStrategy] = True
max_length: Optional[int] = None
pad_to_multiple_of: Optional[int] = None
def __call__(self, features):
label_name = "label" if "label" in features[0].keys() else "labels"
labels = [feature.pop(label_name) for feature in features]
batch_size = len(features)
num_choices = len(features[0]["input_ids"])
flattened_features = [
[{k: v[i] for k, v in feature.items()} for i in range(num_choices)] for feature in features
]
flattened_features = sum(flattened_features, [])
batch = self.tokenizer.pad(
flattened_features,
padding=self.padding,
max_length=self.max_length,
pad_to_multiple_of=self.pad_to_multiple_of,
return_tensors="tf",
)
batch = {k: tf.reshape(v, (batch_size, num_choices, -1)) for k, v in batch.items()}
batch["labels"] = tf.convert_to_tensor(labels, dtype=tf.int64)
return batch
Trainer で再調整
AutoModelForMultipleChoice で BERT をロードします :
from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer
model = AutoModelForMultipleChoice.from_pretrained("bert-base-uncased")
この時点で、3 つのステップだけが残っています :
- TrainingArguments で訓練ハイパーパラメータを定義します。
- モデル, データセット, トークナイザー, そしてデータ collator と共に訓練引数を Trainer に渡します。
- モデルを再調整するために train() を呼び出します。
training_args = TrainingArguments(
output_dir="./results",
evaluation_strategy="epoch",
learning_rate=5e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
num_train_epochs=3,
weight_decay=0.01,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_swag["train"],
eval_dataset=tokenized_swag["validation"],
tokenizer=tokenizer,
data_collator=DataCollatorForMultipleChoice(tokenizer=tokenizer),
)
trainer.train()
TensorFlow による再調整
TensorFlow でモデルを再調整することは、幾つかの違いはありますが、同様に簡単です。
データセットを to_tf_dataset で tf.data.Dataset 形式に変換します。columns で入力を、label_cols でターゲットを、データセット順序をシャッフルするか否か、バッチサイズ、そしてデータ collator を指定します :
data_collator = DataCollatorForMultipleChoice(tokenizer=tokenizer)
tf_train_set = tokenized_swag["train"].to_tf_dataset(
columns=["attention_mask", "input_ids"],
label_cols=["labels"],
shuffle=True,
batch_size=batch_size,
collate_fn=data_collator,
)
tf_validation_set = tokenized_swag["validation"].to_tf_dataset(
columns=["attention_mask", "input_ids"],
label_cols=["labels"],
shuffle=False,
batch_size=batch_size,
collate_fn=data_collator,
)
optimizer 関数, 学習率スケジュール, そして幾つかの訓練ハイパーパラメータをセットアップします :
from transformers import create_optimizer
batch_size = 16
num_train_epochs = 2
total_train_steps = (len(tokenized_swag["train"]) // batch_size) * num_train_epochs
optimizer, schedule = create_optimizer(init_lr=5e-5, num_warmup_steps=0, num_train_steps=total_train_steps)
TFAutoModelForMultipleChoice で BERT をロードします :
from transformers import TFAutoModelForMultipleChoice
model = TFAutoModelForMultipleChoice.from_pretrained("bert-base-uncased")
compile で訓練のためにモデルを configure します :
model.compile(
optimizer=optimizer,
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
モデルを再調整するために fit を呼び出します :
model.fit(x=tf_train_set, validation_data=tf_validation_set, epochs=2)
以上