HuggingFace Transformers 4.5 : Gettiing Started : クイック・ツアー (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/01/2021 (4.5.1)
* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Gettiing Started : Quick tour
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
スケジュールは弊社 公式 Web サイト でご確認頂けます。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
人工知能研究開発支援 | 人工知能研修サービス | テレワーク & オンライン授業を支援 |
PoC(概念実証)を失敗させないための支援 (本支援はセミナーに参加しアンケートに回答した方を対象としています。) |
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
HuggingFace Transformers : Gettiing Started : クイック・ツアー
- 訳注 : 本ドキュメントの PyTorch バージョンは こちら をご覧ください。
Transformers ライブラリの特徴を素早く見ましょう。ライブラリは、テキストのセンチメントを分析するような自然言語理解 (NLU) タスク、そしてプロンプトを新しいテキストで補完したりもう一つの他の言語に翻訳するような自然言語生成 (NLG) のための事前訓練モデルをダウンロードします。
最初にそれらの事前訓練モデルを推論で素早く利用するためにパイプライン API をどのように容易に活用するかを見ます。それから、もう少し掘り下げてライブラリがそれらのモデルへのアクセスをどのように与えてデータを前処理することを手助けするかを見ます。
パイプラインでタスク上で始める
与えられたタスク上で事前訓練モデルを利用する最も容易な方法は pipeline() を使用することです。 Transformers は以下のタスクをすぐに使えるように提供します :
- センチメント解析 : テキストはポジティブ or ネガティブ?
- テキスト生成 (in English) : プロンプトを提示してモデルはそれに続くものを生成します。
- 固有表現認識 (NER) : 入力センテンスで、各単語をそれが表すエンティティ (person, place, etc.) でラベル付けします
- 質問応答 : あるコンテキストと質問とともにモデルを提供します、コンテキストから答えを抽出します。
- マスクされたテキストを埋める : マスクされた単語 (e.g., [MASK] で置き換えられた) を持つテキストが与えられたとき、ブランクを埋めます。
- 要約 : 長いテキストの要約を生成します。
- 翻訳 : テキストを別の言語に翻訳します。
- 特徴抽出 : テキストの tensor 表現を返します。
センチメント解析のためにこれがどのように動作するか見ましょう (他のタスクは タスク要約 で総てカバーされます) :
from transformers import pipeline
classifier = pipeline('sentiment-analysis')
このコマンドを最初にタイプしたとき、事前訓練モデルとその tokenizer がダウンロードされてキャッシュされます。両者を後で見ますが、イントロダクションとして tokenizer のジョブはモデルのためにテキストを前処理することです、これはそれから予測を行なう責任を追います。パイプラインはその総てを一緒にグループ化して、予測を可読にするために後処理します。例えば :
classifier('We are very happy to show you the 🤗 Transformers library.')
That’s encouraging! センテンスのリスト上でそれを利用できます、それは前処理されてからモデルにバッチとして供給され、この一つのように辞書のリストを返します :
results = classifier(["We are very happy to show you the 🤗 Transformers library.",
"We hope you don't hate it."])
for result in results:
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
2 番目のセンテンスがネガティブとして分類されたのを見れますが (それはポジティブかネガティブである必要があります)、そのスコアは公平に中立です。
デフォルトで、このパイプラインのためにダウンロードされるモデルは “distilbert-base-uncased-finetuned-sst-2-english” と呼ばれます。それについてより多くの情報を得るためにその モデルページ を見ることができます。それは DistilBERT アーキテクチャ を使用してセンチメント分析タスクのための SST-2 と呼ばれるデータセット上で再調整されました。
別のモデルを利用することを望むとしましょう ; 例えば、フランス語データ上で訓練された一つです。研究ラボにより多くのデータ上で事前訓練されたモデルを集めた モデルハブ を通して検索できますが、コミュニティ・モデルもまたあります (通常は特定のデータセット上でのそれらの大きなモデルの再調整版です)。タグ “French” と “text-classification” の適用は提案 “nlptown/bert-base-multilingual-uncased-sentiment” を与えます。それをどのように使用するか見ましょう。
pipeline() を使用するためにモデルの名前を直接渡すことができます :
classifier = pipeline('sentiment-analysis', model="nlptown/bert-base-multilingual-uncased-sentiment")
分類器は今では英語、フランス語だけでなく、オランダ語、ドイツ語、イタリア語とスペイン語のテキストも扱うことができます!その名前を事前訓練モデルをセーブしたローカルフォルダで置き換えることもできます (下を見てください)。モデルオブジェクトとその関連する tokenizer を渡すこともできます。
このために 2 つのクラスを必要とします。最初のものは AutoTokenizer で、これは選択したモデルに関連する tokenizer をダウンロードしてそれをインスタンス化するために使用します。2 番目のものは AutoModelForSequenceClassification (or TensorFlow を使用していれば TFAutoModelForSequenceClassification) で、これはモデル自身をダウンロードするために使用します。他のタスク上でライブラリを使用していた場合には、モデルのクラスは変わることに注意してください。タスク要約 チュートリアルはどのクラスがどのタスクのためのに使用されるかを要約しています。
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification
今では、前に見つけたモデルと tokenizer をダウンロードするためには、単に from_pretrained() メソッドを使用しなければならないだけです (model_name はモデルハブからの任意の他のモデルで自由に置き換えてください) :
model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
# This model only exists in PyTorch, so we use the `from_pt` flag to import that model in TensorFlow.
model = TFAutoModelForSequenceClassification.from_pretrained(model_name, from_pt=True)
tokenizer = AutoTokenizer.from_pretrained(model_name)
classifier = pipeline('sentiment-analysis', model=model, tokenizer=tokenizer)
貴方のものに類似したあるデータ上で事前訓練されたモデルが見つからない場合には、事前訓練されたモデルを貴方のデータ上で再調整する必要があります。それを行なう サンプル・スクリプト を提供します。ひとたびそれを行なったら、この チュートリアル を使用して、貴方の再調整モデルをハブ上でコミュニティと共有することを忘れないでください
Under the hood: 事前訓練モデル
今はそれらのパイプラインを使用するとき中で何が起きるかを見ましょう。見たように、モデルと tokenizer は from_pretrained メソッドを使用して作成されます :
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
tf_model = TFAutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer を使用する
tokenizer はテキストの前処理の責任を負うと言及しました。最初に、それは与えられたテキストを通常はトークンと呼ばれる単語 (or 単語の部分、句読記号等) に分割します。そのプロセスを管理できる複数のルールがあります (tokenizer 要約 でそれらについて更に学習できます)、これが何故モデルの名前を使用して tokenizer をインスタンス化する必要があるかです、モデルが事前訓練されたときと同じルールを使用することを確実にするためです。
2 番目のステップはそれらのトークンを数字に変換することです、それらから tensor を構築してそれらをモデルに供給できるようにです。これを行なうため、tokenizer は vocab を持ちます、これは from_pretrained メソッドでそれをインスタンス化するときダウンロードする一部です、何故ならばモデルが事前訓練したときと同じ vocab を使用する必要があるからです。
与えられたテキストでこれらのステップを適用するため、単にそれを tokenizer に供給できます :
inputs = tokenizer("We are very happy to show you the 🤗 Transformers library.")
これは整数のリストへの辞書文字列を返します。それは (前に言及されたように) トークンの id だけでなく、モデルに必要な追加引数も含みます。ここでは例えば、attention マスク も持ちます、これはシークエンスのより良い理解を持つためにモデルが利用します :
>>> print(inputs)
{'input_ids': [101, 2057, 2024, 2200, 3407, 2000, 2265, 2017, 1996, 100, 19081, 3075, 1012, 102], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
センテンスのリストを tokenizer に直接渡すことができます。ゴールがそれらをモデルにバッチとして送ることならば、それらを総て同じ長さにパッドし、それらをモデルが受け取れる最大長に truncate してそして tensor を返すことを多分望むでしょう。それら総てを tokenizer に指定することができます :
tf_batch = tokenizer(
["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."],
padding=True,
truncation=True,
max_length=512,
return_tensors="tf"
)
パディングは、(それで) モデルが訓練されたパディングトークンで、モデルにより想定されるサイドで自動的に適用されます (この場合、右側)。attention マスクはまたパディングを考慮にいれるために適応されます :
for key, value in tf_batch.items():
print(f"{key}: {value.numpy().tolist()}")
input_ids: [[101, 2057, 2024, 2200, 3407, 2000, 2265, 2017, 1996, 100, 19081, 3075, 1012, 102], [101, 2057, 3246, 2017, 2123, 1005, 1056, 5223, 2009, 1012, 102, 0, 0, 0]] attention_mask: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]]
tokenizer について ここ で更に学習できます。
モデルを使用する
入力が tokenizer によりひとたび前処理されれば、それをモデルに直接送ることができます。言及したように、それはモデルが必要とする関連情報を総て含みます。TensorFlow モデルを使用している場合、辞書キーを tensor に直接渡すことができて、PyTorch モデルについては、 ** を追加することにより辞書をアンパックする必要があります。
tf_outputs = tf_model(tf_batch)
Transformers では、総ての出力は (潜在的に一つの要素だけを持つ) タプルです。ここでは、単にモデルの最後の活性を持つタプルを得ます。
print(tf_outputs)
(<tf.Tensor: shape=(2, 2), dtype=float32, numpy= array([[-4.0832963 , 4.336414 ], [ 0.08181786, -0.04179301]], dtype=float32)>,)
モデルは単なる最後の活性以上を返すことができます、これは何故出力がタプルであるかです。ここでは最後の活性だけを求めますので、一つの要素を持つタプルを得ます。
Note: 総ての Transformers モデル (PyTorch or TensorFlow) は (SoftMax のような) 最後の活性化関数の 前の モデルの活性を返します、何故ならばこの最後の活性化関数はしばしば損失と融合されるからです。
予測を得るために SoftMax 活性を適用しましょう。
import tensorflow as tf
tf_predictions = tf.nn.softmax(tf_outputs[0], axis=-1)
前からの数字を得ることを見れます :
print(tf_predictions)
tf.Tensor( [[2.2042994e-04 9.9977952e-01] [5.3086340e-01 4.6913657e-01]], shape=(2, 2), dtype=float32)
ラベルを持つのであれば、それらをモデルに提供できます、それは損失と最後の活性を持つタプルを返します。
import tensorflow as tf
tf_outputs = tf_model(tf_batch, labels = tf.constant([1, 0]))
モデルは標準的な torch.nn.Module or tf.keras.Model ですから通常の訓練ループでそれらを使用できます。 Transformers は訓練を手助けする (分散訓練、混合精度等のようなものを処理します) ためにまた Trainer クラス (or TensorFlow を使用していれば TFTrainer) も提供します。より多くの詳細については 訓練チュートリアル を見てください。
貴方のモデルがひとたび再調整されれば、tokenizer で次の方法でそれをセーブできます :
tokenizer.save_pretrained(save_directory)
model.save_pretrained(save_directory)
それからモデル名の代わりにディレクトリ名を渡すことにより from_pretrained() メソッドを使用してモデルをロードし戻すことができます。 Transformers の一つのクールな特徴は PyTorch と TensorFlow 間で容易に切り替えられることです : 前のようにセーブされた任意のモデルは PyTorch か TensorFlow のいずれかでロードし戻すことができます。セーブされた PyTorch モデルを TensorFlow モデル内にロードしている場合には、このように from_pretrained() を使用します :
tokenizer = AutoTokenizer.from_pretrained(save_directory)
model = TFAutoModel.from_pretrained(save_directory, from_pt=True)
そしてセーブされた TensorFlow モデルを PyTorch モデル内にロードしている場合は、次のコードを使用するべきです :
tokenizer = AutoTokenizer.from_pretrained(save_directory)
model = AutoModel.from_pretrained(save_directory, from_tf=True)
最後に、総ての隠れ状態と総ての attention 重みを返すように (もしそれらを必要とするならば) モデルに要求することもできます :
tf_outputs = tf_model(tf_batch, output_hidden_states=True, output_attentions=True)
all_hidden_states, all_attentions = tf_outputs[-2:]
コードにアクセスする
AutoModel と AutoTokenizer クラスは任意の事前訓練モデルで自動的に動作する単なるショートカットです。内部的には、ライブラリはアーキテクチャとクラスの組合せ毎に一つの model クラスを持ちますので、コードは必要であれば容易にアクセスして調整できます。
前のサンプルでは、モデルは “distilbert-base-uncased-finetuned-sst-2-english” と呼ばれました、これはそれが DistilBERT アーキテクチャを使用してることを意味しています。AutoModelForSequenceClassification (or TensorFlow を使用しているなら TFAutoModelForSequenceClassification) が使用されたとき、自動的に作成されるモデルは DistilBertForSequenceClassification です。その特定のモデルに関連する詳細の総てについてのドキュメントを見る、あるいはソースコードをブラウザすることができます。これは auto マジックなしでモデルと tokenizer をどのように直接インスタンス化するかです :
from transformers import DistilBertTokenizer, TFDistilBertForSequenceClassification
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
model = TFDistilBertForSequenceClassification.from_pretrained(model_name)
tokenizer = DistilBertTokenizer.from_pretrained(model_name)
モデルをカスタマイズする
モデル自身がどのように構築されるかを変更することを望む場合、カスタム configuration クラスを定義することができます。各アーキテクチャはそれ自身の関連 configuration (DistilBERT の場合は DistilBertConfig) を備え、これは任意の隠れ次元、dropout 率等を指定することを可能にします。隠れサイズを変更するような、中心的な変更を行なう場合には、事前訓練モデルを利用することはもはやできませんのでスクラッチから訓練する必要があります。それからこの configuration から直接モデルをインスタンス化するでしょう。
ここでは DistilBERT の事前定義された語彙を利用して (これ故に from_pretrained() メソッドで tokenizer をロードします) モデルをスクラッチから初期化します (これ故に from_pretrained() メソッドを使用する代わりに configuration からモデルをインスタンス化します)。
from transformers import DistilBertConfig, DistilBertTokenizer, TFDistilBertForSequenceClassification
config = DistilBertConfig(n_heads=8, dim=512, hidden_dim=4*512)
tokenizer = DistilBertTokenizer.from_pretrained('distilbert-base-uncased')
model = TFDistilBertForSequenceClassification(config)
モデルのヘッド (例えば、ラベル数) を変更するだけの何かについては、ボディのために依然として事前訓練モデルを利用できます。例えば、事前訓練ボディを使用して 10 の異なるラベルのための分類器を定義しましょう。総てのデフォルト値を持つ configuration を作成してラベル数を単に変更することはできるでしょうが、より簡単に、configuration が取る任意の引数を直接 from_pretrained() メソッドに渡すことができてそれはそれでデフォルト configuration を更新します :
from transformers import DistilBertConfig, DistilBertTokenizer, TFDistilBertForSequenceClassification
model_name = "distilbert-base-uncased"
model = TFDistilBertForSequenceClassification.from_pretrained(model_name, num_labels=10)
tokenizer = DistilBertTokenizer.from_pretrained(model_name)
以上