HuggingFace Transformers 4.5 : Gettiing Started : 用語集 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/06/2021 (4.5.1)
* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Gettiing Started : Glossary
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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 : 用語集
一般用語
- autoencoding モデル : MLM 参照
- autoregressive モデル : CLM 参照
- CLM : 因果 (= causal) 言語モデリング、モデルがテキストを順番に読みそして次の単語を予測しなければならない事前訓練タスクです。それは通常はセンテンス全体を読むことにより成されますが、特定の時間ステップで未来のトークンを隠すためにモデル内のマスクを使用します。
- 深層学習 : 幾つかの層を持つニューラルネットワークを使用する機械学習アルゴリズム
- MLM : masked 言語モデリング、モデルは (通常は幾つかのトークンをランダムにマスクすることにより成される) テキストの破損した (= corrupted) バージョンを見て、元のテキストを予測しなければならない事前訓練タスクです。
- multimodal (多様性) : テキストと別の種類の入力 (例えば画像) を結合するタスク。
- NLG: 自然言語生成 (= generation)、テキスト生成に関連する総てのタスク (例えば transformer と話す、翻訳)。
- NLP : 自然言語処理、「テキストを処理する」と言うための一般的な方法です。
- NLU : 自然言語理解 (= understanding)、テキスト内にあるものの理解に関連する総てのタスク (例えばテキスト全体、個々の単語の分類)。
- 事前訓練モデル : あるデータ上で事前訓練されたモデル (例えば総ての Wikipedia)。事前訓練方法は自己教師あり目的を含みます、これはテキストを読んで次の単語を予測しようとする (CLM 参照) か、幾つかの単語をマスクしてそれらを予測しようとすることであり得ます (MLM 参照)。
- RNN : リカレント・ニューラルネットワーク、テキストを処理するために層に渡るループを使用するタイプのモデル。
- self-attention : 入力の各要素は入力のどの別の要素に注意を払うべきかを明らかにします。
- seq2seq or sequence-to-sequence : (Bart や T5 のような) 翻訳モデルや要約モデルのように、入力から新しいシークエンスを生成するモデル。
- トークン : センテンスの一部、通常は単語ですが、部分単語 (非一般的単語はしばしば部分単語に分割されます) や句読点シンボルでもあり得ます。
- transformer : self-attention ベースの深層学習モデル・アーキテクチャ。
モデル入力
総てのモデルは異なりますが他のものとの類似性を有します。従って殆どのモデルは同じ入力を用います、これはここで使用サンプルとともに詳述されます。
入力 ID
入力 id はしばしば入力としてモデルに渡される唯一の必須パラメータです。それらはトークン・インデックスで、モデルにより入力として使用されるシークエンスを構築するトークンの数値表現です。
各 tokenizer は異なって動作しますが基礎的なメカニズムは同じままです。ここに BERT tokenzier を使用するサンプルがあります、これは WordPiece tokenizer です :
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
sequence = "A Titan RTX has 24GB of VRAM"
tokenizer はシークエンスを tokenzier 語彙で利用可能なトークンに分割する処理をします。
tokenized_sequence = tokenizer.tokenize(sequence)
トークンは単語か部分単語のいずれかです。ここでは例えば、”VRAM” はモデル語彙にないので、それは “V”, “RA” と “M” に分割されます。それらのトークンが別々の単語ではなく同じ単語の一部であることを示すために、“RA” と “M” のために double-hash プレフィックスが追加されます。
print(tokenized_sequence)
['A', 'Titan', 'R', '##T', '##X', 'has', '24', '##GB', 'of', 'V', '##RA', '##M']
そしてこれらのトークンはモデルにより理解可能な ID に変換できます。これはセンテンスを直接 tokenizer に供給することにより成されます、これは最高のパフォーマンスのために huggingface/tokenizers の Rust 実装を活用しています。
inputs = tokenizer(sequence)
tokenizer は対応するモデルが正しく動作するために必要な総ての引数を持つ辞書を返します。トークンインデックスはキー “inputs_ids” のもとにあります。
encoded_sequence = inputs["input_ids"]
print(encoded_sequence)
[101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]
tokenizer は (関連モデルがそれらに依拠する場合)「特殊トークン」を自動的に追加することに注意してください、これはモデルが時に利用する特殊な ID です。
前の id のシークエンスをデコードする場合、
decoded_sequence = tokenizer.decode(encoded_sequence)
次を見ます :
print(decoded_sequence)
[CLS] A Titan RTX has 24GB of VRAM [SEP]
これは BertModel がその入力に想定する方法であるからです。
Attention マスク
attention マスクはシークエンスをまとめてバッチ処理するときに使用されるオプションの引数です。この引数はどのトークンが注意を払われるべきか、そしてどれがそうでないかをモデルに示します。
例えば、これらの 2 つのセンテンスを考えます :
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
sequence_a = "This is a short sequence."
sequence_b = "This is a rather long sequence. It is at least longer than the sequence A."
encoded_sequence_a = tokenizer(sequence_a)["input_ids"]
encoded_sequence_b = tokenizer(sequence_b)["input_ids"]
エンコードされたバージョンは異なる長さを持ちます :
len(encoded_sequence_a), len(encoded_sequence_b)
(8, 19)
従って、それらを as-is で同じ tensor に一緒に配置することはできません。最初のシークエンスは 2 番目のものの長さにまでパディングされる必要があるか、あるいは 2 番目のものが最初のものの長さにまで切り捨てられる必要があります。
最初のケースでは、ID のリストはパディング・インデックスにより拡張されます。リストを tokenizer に渡してこのようにパッドすることを求めることができます :
padded_sequences = tokenizer([sequence_a, sequence_b], padding=True)
最初のセンテンスの右側にそれを 2 番目のものと同じ長さにするために 0 が追加されたことを見ることができます。
padded_sequences["input_ids"]
[[101, 1188, 1110, 170, 1603, 4954, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 1188, 1110, 170, 1897, 1263, 4954, 119, 1135, 1110, 1120, 1655, 2039, 1190, 1103, 4954, 138, 119, 102]]
そしてこれは PyTorch や TensorFlow の tensor に変換できます。attention マスクはパディングされたインデックスの位置を示す二値 tensor で、その結果モデルはそれらに注意を払いません。BertTokenizer については、1 は注意すべき値を示し、その一方で 0 はパディングされた値を示します。この attention マスクはキー “attention_mask” のもとで tokenizer により返される辞書内にあります。
padded_sequences["attention_mask"]
[[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
トークン型 ID
幾つかのモデルの目的はシークエンス分類や質問応答を行なうことです。これらは 2 つの異なるシークエンスが単一の “input_ids” エントリ内に結合されることを必要とします、これは通常は classifier ([CLS]) と separator ([SEP]) トークンのような特殊トークンの助けにより遂行されます。例えば、BERT モデルはその 2 つのシークエンス入力を次のように構築します :
# [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP]
そのようなセンテンスを自動的に生成するためにこのように 2 つのセンテンスを tokenizer に (前のように、リストではなく、) 2 つの引数として渡すことにより tokenizer を利用できます :
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
sequence_a = "HuggingFace is based in NYC"
sequence_b = "Where is HuggingFace based?"
encoded_dict = tokenizer(sequence_a, sequence_b)
decoded = tokenizer.decode(encoded_dict["input_ids"])
これは次を返します :
print(decoded)
[CLS] HuggingFace is based in NYC [SEP] Where is HuggingFace based? [SEP]
幾つかのモデルについては 1 つのシークエンスがどこで終わりそしてもう 1 つがどこから始まるかを理解するためにこれで十分です。けれども、BERT のような他のモデルはまたトークン型 ID も配備します (セグメント ID とも呼ばれます)。それらはモデルの 2 つのタイプのシークエンスを識別する二値マスクとして表されます。
tokenizer はこのマスクを “token_type_ids” エントリとして返します :
encoded_dict['token_type_ids']
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
最初のシークエンス、質問のために使用される「コンテキスト」は 0 で表される総てのトークンを持ち、その一方で「質問」に相当する 2 番目のシークエンスは 1 で表される総てのトークンを持ちます。
XLNetModel のような幾つかのモデルは 2 で表される追加のトークンを使用します。
位置 ID
(RNN に) 埋め込まれた各トークンの位置を持つ RNN とは違い、transformer は各トークンの位置を知りません。そのため、トークンのリスト内の各トークンの位置を識別するために位置 ID (position_ids) がモデルにより使用されます。
これらはオプションのパラメータです。position_ids がモデルに渡されない場合、ID は絶対的位置の埋め込みとして自動的に作成されます。
絶対的な位置埋め込みは範囲 [0, config.max_position_embeddings – 1] 内で選択されます。幾つかのモデルは sinusoidal (正弦波) 位置埋め込み or 相対的位置埋め込みのような他のタイプの位置埋め込みを利用します。
ラベル
ラベルはオプション引数で、モデルが損失自体を計算するために渡すことができます。これらのラベルはモデルの期待される予測であるべきです : それは予測と期待値 (ラベル) の間の損失を計算するために標準的な損失を利用します。
これらのラベルはモデルヘッドに従って異なります、例えば :
- シークエンス分類モデル (e.g., BertForSequenceClassification) については、モデルはシークエンス全体の期待されるラベルに対応するバッチの各値を持つ次元 (batch_size) の tensor を想定します。
- トークン分類モデル (e.g., BertForTokenClassification) については、モデルは各個々のトークンの期待されるラベルに対応する各値を持つ次元 (batch_size, seq_length) の tensor を想定します。
- masked 言語モデリング (e.g., BertForMaskedLM) については、モデルは各個々のトークンの期待されるラベルに対応する各値を持つ次元 (batch_size, seq_length) の tensor を想定します : masked トークンのためのトークン ID であるラベルの場合、値は残りのためには無視されます (通常は -100)。
- sequence to sequence タスク (e.g., BartForConditionalGeneration, MBartForConditionalGeneration) については、モデルは各入力シークエンスに関連するターゲット・シークエンスに対応する各値を持つ次元 (batch_size, tgt_seq_length) の tensor を想定します。訓練の間、BART と T5 は適切な decoder_input_ids と decoder attention マスク内部的に作成します。それらは通常は供給される必要はありません。これは Encoder-Decoder フレームワークを活用するモデルには当てはまりません。各特定のモデルのラベル上のより多くの情報については各モデルのドキュメントを見てください。
ベースモデル (e.g. BertModel) はラベルを受け取りません、何故ならばこれらはベース transformer モデルで、単純に特徴を出力するだけだからです。
Decoder 入力 ID
この入力はエンコーダ・デコーダモデル特有で、デコーダに供給される入力 ID を含みます。これらの入力は翻訳や要約のような、sequence to sequence タスクのために使用されるべきで、通常は各モデルに固有の方法で構築されます。
殆どのエンコーダ・デコーダモデル (BART, T5) はラベルから独自に decoder_input_ids を作成します。そのようなモデルでは、ラベルを渡すことは訓練を扱うために好まれる方法です。
sequence to sequence 訓練のためにそれらが入力 ID をどのように処理するかを見るには各モデルの docs を確認してください。
順伝播 Chunking
transformer の各残差 attention ブロックでは self-attention 層には通常は 2 つの順伝播層が続きます。順伝播層の中間の埋め込みサイズはしばしばモデルの隠れサイズよりも大きいです (e.g., bert-base-uncased について)。
サイズ [batch_size, sequence_length] の入力について、中間の順伝播埋め込み層 [batch_size, sequence_length, config.intermediate_size] をストアするために必要なメモリはメモリ使用量の大きな割合を占める可能性があります。Reformer: The Efficient Transformer の著者は、計算が sequence_length 次元から独立であるために、順伝播層 [batch_size, config.hidden_size]_0, …, [batch_size, config.hidden_size]_n の出力埋め込みを個別に計算してそれらを n = sequence_length を持つ [batch_size, sequence_length, config.hidden_size] に後で連結することと数学的に同値であることに気付きました、これは増大する計算時間を削減されるメモリ使用に対してトレードオフしますが、数学的には同値な結果を生成します。
関数 apply_chunking_to_forward() を使用するモデルについては、chunk_size は並列に計算される出力埋め込みの数を定義し、メモリと時間計算量の間のトレードオフを定義します。chunk_size が 0 に設定されている場合、順伝播 chunking は行なわれません。
以上