HuggingFace Transformers 3.4 : 訓練と再調整 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/22/2020 (3.4.0)
* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ |
Facebook: https://www.facebook.com/ClassCatJP/ |
HuggingFace Transformers : 訓練と再調整
Transformers のモデルクラスは native PyTorch と TensorFlow 2 と互換であるように設計されそしていずれと共にシームレスに利用可能です。このクイックスタートでは、いずれのフレームワークでも利用可能な標準訓練ツールを使用してモデルをどのように再調整するか (or スクラッチから訓練するか) を示します。含まれる Trainer() クラスをどのように使用するかも示します、これは訓練の複雑さの大半を貴方のために処理します。
このガイドは推論のためにモデルをロードして使用することに既に馴染みがあることを仮定します : そうでないなら タスクの概要 を見てください。貴方が PyTorch か TF2 のいずれかの深層ニューラルネットワークの訓練に馴染みがあることも仮定し、 Transformers の訓練のためのニュアンスとツールに特にフォーカスします。
native PyTorch で再調整する
TF で始まらない Transformers のモデルクラスは PyTorch モジュールで、これは推論と最適化の両者のために丁度 PyTorch の任意のモデルのようにそれらを利用できることを意味します。
シークエンス分類データセット上で BERT のようなマスク付き言語モデルを再調整する一般的なタスクを考えましょう。モデルを from_pretrained() でインスタンス化するとき、モデルを初期化するために指定されたモデルのモデル configuration と事前訓練重みが使用されます。ライブラリはまた幾つかのタスク固有の最終層や「ヘッド」も含みます、それらの重みは指定された事前訓練モデルに存在しないときランダムにインスタンス化されます。例えば、BertForSequenceClassification.from_pretrained(‘bert-base-uncased’, num_labels=2) によるモデルのインスタンス化は bert-base-uncased モデルからコピーされたエンコーダ重みとエンコーダの上に 2 の出力サイズを持つランダムに初期化されたシークエンス分類ヘッドで BERT モデルインスタンスを作成します。モデルはデフォルトでは eval モードで初期化されます。それを train モードに置くために model.train() を呼び出すことができます。
from transformers import BertForSequenceClassification model = BertForSequenceClassification.from_pretrained('bert-base-uncased', return_dict=True) model.train()
これは有用です、何故ならばそれは事前訓練された BERT エンコーダを利用してそれを選択するどのようなシークエンス分類データセットの上でも容易に訓練することを許容するからです。任意の PyTorch optimizer を利用できますが、ライブラリはまた AdamW() optimizer も提供します、これは重み減衰に加えて勾配バイアス補正 (= gradient bias correction) を実装しています。
from transformers import AdamW optimizer = AdamW(model.parameters(), lr=1e-5)
optimizer は特定のパラメータグループのために異なるハイパーパラメータを適用することを許容します。例えば、重み減衰をバイアスと層正規化項以外の総てのパラメータに適用できます :
no_decay = ['bias', 'LayerNorm.weight'] optimizer_grouped_parameters = [ {'params': [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01}, {'params': [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], 'weight_decay': 0.0} ] optimizer = AdamW(optimizer_grouped_parameters, lr=1e-5)
今では __call__() を使用して単純なダミー訓練バッチをセットアップすることができます。これは BatchEncoding() インスタンスを返します、これはモデルに渡す必要があるかもしれない総てを準備します。
from transformers import BertTokenizer tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') text_batch = ["I love Pixar.", "I don't care for Pixar."] encoding = tokenizer(text_batch, return_tensors='pt', padding=True, truncation=True) input_ids = encoding['input_ids'] attention_mask = encoding['attention_mask']
分類モデルを labels 引数で呼び出すとき、最初の返される要素は予測と渡されたラベルの間んほ交差エントロピーです。optimizer を既にセットアップしていますので、それから backwards を行ない重みを更新することができます :
labels = torch.tensor([1,0]).unsqueeze(0) outputs = model(input_ids, attention_mask=attention_mask, labels=labels) loss = outputs.loss loss.backward() optimizer.step()
代わりに、単にロジットを得て損失を貴方自身で計算することもできます。次は前のサンプルと同値です :
from torch.nn import functional as F labels = torch.tensor([1,0]) outputs = model(input_ids, attention_mask=attention_mask) loss = F.cross_entropy(outputs.logits, labels) loss.backward() optimizer.step()
もちろん、通常のようにモデルと入力上で to(‘cuda’) を呼び出して GPU 上で訓練することができます。
2, 3 の学習率スケジューリング・ツールも提供します。以下によって、スケジューラのセットアップができます、これは num_warmup_steps の間ウォームアップしてから訓練の終わりまでに 0 に線形に減衰します。
from transformers import get_linear_schedule_with_warmup scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps, num_train_steps)
それから行なわなければならないことの総ては optimizer.step() の後で scheduler.step() を呼び出すことです。
loss.backward() optimizer.step() scheduler.step()
下で議論されるように、Trainer() を使用することを強く勧めます、これは混合精度と容易な tensorboard ロギングのような特徴とともに Transformers モデルを訓練する可動部を便利に処理します。
エンコーダを凍結する
ある場合には、事前訓練されたエンコーダの重みを凍結し続けてヘッド層の重みだけを最適化することに関心があるかもしれません。そのためには、エンコーダ・パラメータ上で単純に requires_grad 属性を False に設定します、これはライブラリの任意のタスク固有モデル上 base_model サブモジュールでアクセスできます :
for param in model.base_model.parameters(): param.requires_grad = False
native TensorFlow 2 で再調整する
モデルはまた TensorFlow 2 でもネイティブに訓練できます。ちょうど PyTorch でのように、TensorFlow モデルはエンコーダの重みをロードするために from_pretrained() でインスタンス化できます。
from transformers import TFBertForSequenceClassification model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased')
GLUE からの MRPC データセット をロードするために tensorflow_datasets を使用しましょう。それから MRPC をトークン化してそれを TensorFlow Dataset オブジェクトに変換するために組込み glue_convert_examples_to_features() を利用できます。tokenizer はフレームワーク不可知ですので、事前訓練された tokenizer 名に TF を先頭に追加する必要はありません。
from transformers import BertTokenizer, glue_convert_examples_to_features import tensorflow as tf import tensorflow_datasets as tfds tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') data = tfds.load('glue/mrpc') train_dataset = glue_convert_examples_to_features(data['train'], tokenizer, max_length=128, task='mrpc') train_dataset = train_dataset.shuffle(100).batch(32).repeat(2)
そしてモデルは任意の Keras モデルとしてコンパイルされて訓練できます :
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5) loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) model.compile(optimizer=optimizer, loss=loss) model.fit(train_dataset, epochs=2, steps_per_epoch=115)
TensorFlow と PyTorch モデル間の緊密な相互運用性により、モデルをセーブしてからそれを PyTorch モデルとして再ロードすることさえできます (or vice-versa) :
from transformers import BertForSequenceClassification model.save_pretrained('./my_mrpc_model/') pytorch_model = BertForSequenceClassification.from_pretrained('./my_mrpc_model/', from_tf=True)
Trainer
Trainer() と TFTrainer() を通して単純ですが feature-complete な訓練と評価インターフェイスもまた提供します。広範囲の訓練オプションとロギング、勾配集積 (= accumulation) と混合精度のような組込み特徴で任意の Transformers モデルを訓練し、再調整し、そして評価することができます。
from transformers import TFBertForSequenceClassification, TFTrainer, TFTrainingArguments model = TFBertForSequenceClassification.from_pretrained("bert-large-uncased") training_args = TFTrainingArguments( output_dir='./results', # output directory num_train_epochs=3, # total # of training epochs per_device_train_batch_size=16, # batch size per device during training per_device_eval_batch_size=64, # batch size for evaluation warmup_steps=500, # number of warmup steps for learning rate scheduler weight_decay=0.01, # strength of weight decay logging_dir='./logs', # directory for storing logs ) trainer = TFTrainer( model=model, # the instantiated 🤗 Transformers model to be trained args=training_args, # training arguments, defined above train_dataset=tfds_train_dataset, # tensorflow_datasets training dataset eval_dataset=tfds_test_dataset # tensorflow_datasets evaluation dataset )
from transformers import BertForSequenceClassification, Trainer, TrainingArguments model = BertForSequenceClassification.from_pretrained("bert-large-uncased") training_args = TrainingArguments( output_dir='./results', # output directory num_train_epochs=3, # total # of training epochs per_device_train_batch_size=16, # batch size per device during training per_device_eval_batch_size=64, # batch size for evaluation warmup_steps=500, # number of warmup steps for learning rate scheduler weight_decay=0.01, # strength of weight decay logging_dir='./logs', # directory for storing logs ) trainer = Trainer( model=model, # the instantiated 🤗 Transformers model to be trained args=training_args, # training arguments, defined above train_dataset=train_dataset, # training dataset eval_dataset=test_dataset # evaluation dataset )
今では単純に訓練するために trainer.train() をそして評価するために trainer.evaluate() を呼び出します。貴方自身のモジュールもまた使用できますが、forward から返される最初の引数は最適化することを望む損失でなければなりません。
Trainer() はバッチを順番に並べてそれらをモデルに供給されるように準備するために組込みのデフォルト関数を使用します。必要であれば、貴方自身の collator 関数を渡すために data_collator 引数も使用できます、これは貴方のデータセットにより提供される形式のデータを取りそしてモデルに供給される準備ができたバッチを返します。TFTrainer は渡されたデータセットが tensorflow_datasets からのデータセット・オブジェクトであることを想定していることに注意してください。
損失に加えて追加のメトリクスを計算するために、貴方自身の compute_metrics 関数も定義してそれを Trainer に渡すこともできます。
from sklearn.metrics import accuracy_score, precision_recall_fscore_support def compute_metrics(pred): labels = pred.label_ids preds = pred.predictions.argmax(-1) precision, recall, f1, _ = precision_recall_fscore_support(labels, preds, average='binary') acc = accuracy_score(labels, preds) return { 'accuracy': acc, 'f1': f1, 'precision': precision, 'recall': recall }
最後に、指定された logging_dir ディレクトリで tensorboard を起動することにより任意の計算されたメトリクスを含む結果を見ることができます。
追加リソース
- 軽量 colab デモ、これは IMDb センチメント分類のために Trainer を使用します。
Transformers サンプル、これは GLUE, SQuAD と幾つかの他のタスク上の訓練と再調整のためのスクリプトを含みます。
- 言語モデルをどのように訓練するか、詳細な colab ノートブック、これは Esperanto 上でスクラッチからマスク付き言語モデルを訓練するために Trainer を使用します。
Transformers ノートブック、これは
様々のタスク上Transformers の訓練と利用のためのコミュニティからの数十のサンプル・ノートブックを含みます。
以上