LoginSignup
4
2

More than 1 year has passed since last update.

[翻訳] Hugging Face transformersのクイックスタート

Posted at

Quickstart — transformers 2.11.0 documentationの翻訳です。

本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。

哲学

Transformersは大規模トランスフォーマーモデルを活用/研究/拡張しようとしているNLP研究者のために構築されたこだわりのあるライブラリです。

このライブラリは2つの強いゴールを念頭に設計されました:

  • 可能な限り簡単かつすぐに使えるように:
    • 学習すべきユーザーが直面する抽象化の数を強力に制限しています。実際、抽象化はほとんど存在せず、それぞれのモデルで必要とされる標準的なクラスはたった3つです: configuration、modelsとtokenizerです。
    • これらのクラス全ては、ライブラリあるいはご自身が保存したインスタンスで提供される事前学習済みインスタンスから関連するクラスのダウンロード(必要な場合)、キャッシュ、ロードのケアをする共通のfrom_pretrained()インスタンス生成メソッドを用いることで、事前学習済みインスタンスからシンプルかつ統合された方法でインスタンス化されます。
    • このため、このライブラリはニューラルネットのビルディングブロックのモジュール化されたツールボックスではありません。ライブラリを拡張したい場合には、シンプルに通常のPython/PyTorchモジュールを使用し、モデルのロード/セーブのような機能を再利用するにはライブラリのベースクラスから継承してください。
  • オリジナルのモデルと可能な限り近しいパフォーマンスを提供する最先端のモデルの提供:
    • 当該アーキテクチャの正式な作者によって提供される結果を再現するアーキテクチャのそれぞれに対して、最低1つのサンプルを提供します。
    • コードは可能な限りオリジナルのものに近いものとなっており、これはいくつかのPyTorchコードがTensorFlowコードに変換された結果、本来よりもpytorchicでない場合があります。

その他のゴール:

  • 可能なかぎり、一貫性を持ってモデルの内部を公開します:
    • シンプルなAPIを用いて完全な隠し状態、アテンションの重みへのアクセスを提供します。
    • モデル間を容易にスイッチできるようにトークナイザーとモデルのAPIは標準化されています。
  • これらのもデールをファインチューン/調査するために主観的に選択した有望なツールを組み込みんでいます:
    • ファインチューニングの際、ボキャブラリーとエンベディングに新規トークンを追加するシンプル/一貫性のある方法。
    • トランスフォーマーのヘッドをマスク、切り取るシンプルな方法。

主要なコンセプト

このライブラリは、それぞれのモデルに対する3つのタイプのクラスを軸に構成されています。

  • モデルクラス: ライブラリで提供されている事前学習済み重みで動作するBertModelのような20+のPyTorchモデル(torch.nn.Modules)。TF2ではtf.keras.Modelとなります。
  • 設定クラス: BertConfigのようにモデルの構築に必要なすべてのパラメーターを格納するクラス。常にあなた自身でインスタンスを作成する必要はありません。特に、変更なしに事前学習済みモデルを使用する際、モデルの作成によって(モデルの一部である)設定のインスタンス化は自動でケアされます。
  • トークナイザークラス: BertTokenizerのようにモデルに投入されるトークンのエンベディングのインデックスのリストにおけるエンコーディング/デコーディングの方法とそれぞれのモデルのボキャブラリーを格納します。

これら全てのクラスは事前学習済みインスタンスからインスタンスが作成され、2つのメソッドを用いてローカルに保存されます:

  • from_pretrained()を用いることで、ライブラリ自身(こちらに現在提供されている27のモデルが一覧されています)あるいはユーザーによってローカルに保存されたものから提供される事前学習済みバージョンからモデル/設定/トークナイザーのインスタンスを作成できます。
  • save_pretrained()を用いることで、from_pretrained()を用いて再ロードできるようにモデル/設定/トークナイザーをローカルに保存することができます。

これらのクラスをどのようにインスタンス化し、使用できるのかを見るためのいくつかのシンプルなクイックスタートのサンプルでこのクイックスタートツアーを終わりにします。

  • MAIN CLASSESセクションでは、3つの主要タイプのクラス(configuration, model, tokenizer)の一般的な機能/メソッド/属性とトレーニングのユーティリティとして提供されるクラスに関連するいくつかの最適化の詳細を説明します。
  • PACKAGE REFERENCEセクションでは、それぞれのモデルアーキテクチャのそれぞれのクラスのすべての派生系と、特にそれらを呼び出す際に予期すべき入力/出力の詳細を説明します。

クイックツアー: 使い方

ここでは、BertGPT2クラスと事前学習済みモデルをショーケースするサンプルを説明します。

それぞれのモデルクラスのサンプルに関しては完全なAPIリファレンスをご覧ください。

BERTのサンプル

BertTokenizerを用いてテキスト文字列からトークナイズされた入力(Bertに与えられるトークンのエンベディングのインデックス)を準備することからスタートしましょう。

Python
import torch
from transformers import BertTokenizer, BertModel, BertForMaskedLM

# OPTIONAL: if you want to have more information on what's happening under the hood, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary)
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# Tokenize input
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = tokenizer.tokenize(text)

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 8
tokenized_text[masked_index] = '[MASK]'
assert tokenized_text == ['[CLS]', 'who', 'was', 'jim', 'henson', '?', '[SEP]', 'jim', '[MASK]', 'was', 'a', 'puppet', '##eer', '[SEP]']

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
# Define sentence A and B indices associated to 1st and 2nd sentences (see paper)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])

隠し状態でこの入力をエンコーディングするためにどのようにBertModelを使うのかを見てみましょう。

Python
# Load pre-trained model (weights)
model = BertModel.from_pretrained('bert-base-uncased')

# Set the model in evaluation mode to deactivate the DropOut modules
# This is IMPORTANT to have reproducible results during evaluation!
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
segments_tensors = segments_tensors.to('cuda')
model.to('cuda')

# Predict hidden states features for each layer
with torch.no_grad():
    # See the models docstrings for the detail of the inputs
    outputs = model(tokens_tensor, token_type_ids=segments_tensors)
    # Transformers models always output tuples.
    # See the models docstrings for the detail of all the outputs
    # In our case, the first element is the hidden state of the last layer of the Bert model
    encoded_layers = outputs[0]
# We have encoded our input sequence in a FloatTensor of shape (batch size, sequence length, model hidden dimension)
assert tuple(encoded_layers.shape) == (1, len(indexed_tokens), model.config.hidden_size)

そして、マスクされたトークンを予測するためにBertForMaskedLMを使います。

Python
# Load pre-trained model (weights)
model = BertForMaskedLM.from_pretrained('bert-base-uncased')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
segments_tensors = segments_tensors.to('cuda')
model.to('cuda')

# Predict all tokens
with torch.no_grad():
    outputs = model(tokens_tensor, token_type_ids=segments_tensors)
    predictions = outputs[0]

# confirm we were able to predict 'henson'
predicted_index = torch.argmax(predictions[0, masked_index]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
assert predicted_token == 'henson'

OpenAI GPT-2

こちらは、テキストプロンプトから次のトークンを予測するために、OpenAIの事前学習済みモデルとGPT2TokenizerGPT2LMHeadModelクラスを用いたクイックスタートのサンプルです。

最初に、GPT2Tokenizerを用いてテキスト文字列からトークナイズされた入力を準備しましょう。

Python
import torch
from transformers import GPT2Tokenizer, GPT2LMHeadModel

# OPTIONAL: if you want to have more information on what's happening, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary)
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')

# Encode a text inputs
text = "Who was Jim Henson ? Jim Henson was a"
indexed_tokens = tokenizer.encode(text)

# Convert indexed tokens in a PyTorch tensor
tokens_tensor = torch.tensor([indexed_tokens])

テキストに続く次のトークンを生成するためにGPT2LMHeadModelを使います。

Python
# Load pre-trained model (weights)
model = GPT2LMHeadModel.from_pretrained('gpt2')

# Set the model in evaluation mode to deactivate the DropOut modules
# This is IMPORTANT to have reproducible results during evaluation!
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')

# Predict all tokens
with torch.no_grad():
    outputs = model(tokens_tensor)
    predictions = outputs[0]

# get the predicted next sub-word (in our case, the word 'man')
predicted_index = torch.argmax(predictions[0, -1, :]).item()
predicted_text = tokenizer.decode(indexed_tokens + [predicted_index])
assert predicted_text == 'Who was Jim Henson? Jim Henson was a man'

それぞれのモデルアーキテクチャ(Bert, GPT, GPT-2, Transformer-XL, XLNet, XLM)に対するそれぞれのモデルクラスのサンプルは、ドキュメントで参照することができます。

pastの活用

GPT-2や他のモデルのいくつか(GPT, XLNet, Transfo-XL, CTRL)では、シーケンスのデコードを行う際、キー/バリューペアの再計算を避けるために使用できるpastmems属性を活用しています。以前の計算からアテンション機構の大部分を享受することでシーケンスを生成する際には有用です。

こちらは、GPT2LMHeadModelpastとargmaxデコーディング(argmaxデコーディングは大量の繰り返しを引き起こすので、これはサンプルとしてのみ使用されるべきです)を用いた完全に動作するサンプルです。

Python
from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained('gpt2')

generated = tokenizer.encode("The Manhattan bridge")
context = torch.tensor([generated])
past = None

for i in range(100):
    print(i)
    output, past = model(context, past=past)
    token = torch.argmax(output[..., -1, :])

    generated += [token.tolist()]
    context = token.unsqueeze(0)

sequence = tokenizer.decode(generated)

print(sequence)

過去の全てのトークンのキー/バリューペアはpastに格納されているので、このモデルの入力としては単一のトークンだけで大丈夫です。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2