HuggingFace Transformers 4.5 : 利用方法 : トークナイザーの要点

HuggingFace Transformers 4.5 : 利用方法 : トークナイザーの要点 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/12/2021 (4.5.1)

* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料 Web セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。
スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
クラスキャットは人工知能・テレワークに関する各種サービスを提供しております :

人工知能研究開発支援 人工知能研修サービス テレワーク & オンライン授業を支援
PoC(概念実証)を失敗させないための支援 (本支援はセミナーに参加しアンケートに回答した方を対象としています。)

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com  ;  WebSite: https://www.classcat.com/  ;  Facebook

 

HuggingFace Transformers : 利用方法 : トークナイザーの要点

このページでは、トークン化をより詳しく調べます。前処理チュートリアル で見たように、テキストのトークン化はそれを単語やサブワードに分割します、これらはそれから検索テーブルを通して id に変換されます。単語やサブワードを id に変換することは簡単ですから、この要点では、テキストを単語やサブワードを分割することにフォーカスします (i.e. テキストのトークン化)。より具体的には、 Transformers で使用されるトークナイザーの 3 つの主要なタイプを見ます : Byte-Pair エンコーディング (BPE)、WordPiece と SentencePiece です、そしてどのトークナイザーがどのモデルにより使用されるかのサンプルを示します。

各モデルページでは、どのトークナイザー・タイプが事前訓練モデルにより使用されたかを知るために関連するトークナイザーのドキュメントを見ることができることに注意してください。例えば、BertTokenizer を見れば、モデルが WordPiece を使用していることを見ることができます。

 

イントロダクション

テキストをより小さいチャンクに分割することは思うよりも困難なタスクで、それを行なうための複数の方法があります。例えば、センテンス “Don’t you love 🤗 Transformers? We sure do.” を見ましょう。テキストをトークン化する単純な方法はそれをスペース (空白) で分割することです、それは次を与えるでしょう :

["Don't", "you", "love", "🤗", "Transformers?", "We", "sure", "do."]

これは良識ある最初のステップですが、トークン “Transformers?” と “do.” を見れば、句読点が単語 “Transformer” と “do” に装着されていることに気付きます、これは最適とは言えません。モデルが単語の異なる表現とそれに続くかもしれない句読記号を学習しなくても良いように句読点を考慮に入れるべきです、それはモデルが学習しなければならない表現の数を爆発させます。句読点を考慮に入れれば、模範となるテキストのトークン化は次を与えます :

["Don", "'", "t", "you", "love", "🤗", "Transformers", "?", "We", "sure", "do", "."]

より良いです。けれども、トークン化が単語 “Don’t” をどのように扱うかは不都合です。”Don’t” は “do not” を表しますので、[“Do”, “n’t”] としてトークン化されるほうがより良いです。これは物事が複雑になり始めるところで、各モデルが自身のトークナイザー・タイプを持つ理由の一部です。テキストのトークン化のために適用するルールに依拠して、同じテキストに対して異なるトークン化された出力が生成されます。事前訓練モデルは、訓練データをトークン化するために使用されたものと同じルールでトークン化された入力を供給する場合に限り、正しく遂行します。

spaCyMoses は 2 つのポピュラーなルールベースのトークナイザーです。サンプルに適用すると、spaCy と Moses は次のようなものを出力します :

["Do", "n't", "you", "love", "🤗", "Transformers", "?", "We", "sure", "do", "."]

見られるように、スペースと句読点のトークン化に加えて、ルールベースのトークン化がここで使用されています。スペースと句読点のトークン化とルールベースのトークン化は両者とも単語トークン化の例で、センテンスを単語に分割するものとして緩く定義されます。テキストをより小さいチャンクに分割することは最も直観的な方法である一方で、このトークン化方法は大規模なテキストコーパスのためには問題に繋がる可能性があります。この場合、スペースと句読点のトークン化は通常非常に大きな語彙 (使用される総ての一意の単語とトークンのセット) を生成します。E.g., Transformer XL はスペースと句読点トークン化を使用し、267,735 の語彙サイズという結果になります!

そのような大きな語彙サイズはモデルに入力と出力層として巨大な埋め込み行列を持つことを強制します、これは増大するメモリと時間コストの両者を引き起こします。一般に、transformer モデルは 50,000 より大きい語彙サイズは滅多に持ちません、特にそれらが単一の言語上で事前訓練される場合。

それでは単純なスペースと句読点トークン化が不十分であるならば、何故単純に文字でトークン化しないのでしょう?文字のトークン化が非常に単純であり、そしてメモリと時間コストを大きく減じる一方で、それはモデルが意味のある入力表現を学習することを遥かに困難にします。E.g. 文字 “t” のための意味のあるコンテキスト独立な表現を学習することは単語 “today” のためのコンテキスト独立な表現を学習することより遥かに困難です。従って、文字トークン化はしばしばパフォーマンスの損失を伴います。従って、両者の長所を活かすため、transformers モデルは subword (サブワード) トークン化と呼ばれる単語レベルと文字レベルトークン化のハイブリッドを使用します。

 

サブワード・トークン化

サブワード・トークン化アルゴリズムは、頻繁に使用される単語はより小さいサブワードに分割されるべきではないが、稀な単語は意味のあるサブワードに分解されるべきであるという原理に依拠しています。例えば、”annoyingly” は稀な単語と考えられるかもしれず、そして “annoying” と “ly” に分解できるでしょう。スタンドアロンのサブワードとして “annoying” と “ly” の両者はより頻繁に現れる一方で、同時に “annoyingly” の意味は “annoying” と “ly” の合成的な意味により保持されます。これは特にトルコ語のような膠着語で有用です、そこではサブワードを一緒に繋ぐことにより任意に長い複雑な単語 (群) を (殆ど) 形成できます。

サブワード・トークン化はモデルに合理的な語彙サイズを持つことを可能にする一方で、意味のあるコンテキスト独立な表現を学習することができます。更に、サブワード・トークン化はモデルが前に見たことがない単語を既知のサブワードに分解することにより処理することを可能にします。例えば、BertTokenizer は “I have a new GPU!” を次のようにトークン化します :

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
tokenizer.tokenize("I have a new GPU!")
["i", "have", "a", "new", "gp", "##u", "!"]

uncased モデルを考えていますので、センテンスは最初に小文字にされています。[“i”, “have”, “a”, “new”] はトークナイザーの語彙に存在していますが、単語 “gpu” はそうでないことがわかります。その結果、トークナイザーは “gpu” を既知のサブワード : [“gp” と “##u”] に分割します。”##” は (デコードやトークン化の反転のため) トークンの残りはスペースなしで前のものに装着されるべきであることを意味します。

もう一つの例として、XLNetTokenizer トークナイザーは前の典型例としてのテキストを次のようにトークン化します :

from transformers import XLNetTokenizer
tokenizer = XLNetTokenizer.from_pretrained("xlnet-base-cased")
tokenizer.tokenize("Don't you love 🤗 Transformers? We sure do.")
["▁Don", "'", "t", "▁you", "▁love", "▁", "🤗", "▁", "Transform", "ers", "?", "▁We", "▁sure", "▁do", "."]

SentencePiece を見るときこれらの “▁” の意味に戻ります。見れるように、稀な単語 “Transformers” はより頻度の高いサブワード “Transform” と “ers” に分割されています。

今は様々なサブワード・トークン化アルゴリズムがどのように動作するかを見ましょう。これらのトークン化アルゴリズムの総ては (通常は対応するモデルがその上で訓練されたコーパス上で成される) 訓練のある形式に依拠していることに注意してください。

 

バイトペア・エンコーディング (BPE)

バイトペア・エンコーディング (BPE) は Neural Machine Translation of Rare Words with Subword Units (Sennrich et al., 2015) で導入されました。BPE は訓練データを単語に分割する事前トークナイザーに依存しています。事前トークン化はスペース・トークン化のように単純であり得ます、e.g. GPT2, Roberta。より進んだ事前トークン化はルールベースのトークン化を含みます、e.g. XLM, FlauBERT、これは殆どの言語について Moses を使用しています、また GPT は訓練コーパスで各単語の頻度をカウントするために Space と ftfy を使用します。

事前トークン化後、一意の単語のセットが作成されて訓練データで出現した各単語の頻度が決定されます。次に、BPE は一意の単語のセットに出現する総てのシンボルから成るベース語彙を作成します、そしてベース語彙の 2 つのシンボルから新しいシンボルを形成するためのマージルールを学習します。語彙が望まれる語彙サイズを獲得するまでそれを行ないます。望まれる語彙サイズはトークナイザーを訓練する前に定義するハイパーパラメータであることに注意してください。

例として、事前トークン化後、頻度を含む次の単語のセットが定義されたと仮定します :

("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)

その結果、ベース語彙は [“b”, “g”, “h”, “n”, “p”, “s”, “u”] となります。総ての単語をベース語彙のシンボルに分割し、次を得ます :

("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)

そして BPE は各可能なシンボル・ペアの頻度をカウントして最も頻繁に出現するシンボル・ペアを選択します。上の例では、”u” が続く “h” は 10 + 5 = 15 回存在します (“hug” の 10 出現で 10 回、”hugs” の 5 出現で 5 回)。けれども、最も頻度の高いシンボル・ペアは “g” が続く “u” で、合計で 10 + 5 + 5 = 20 回出現します。こうして、トークナイザーが学習する最初のマージルールは “g” シンボルが続く “u” シンボル総てを一緒にグループ化することです。次に、”ug” は語彙に追加されます。そして単語のセットは次になります :

("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)

それから BPE は次の最も一般的なシンボル・ペアを識別します。それは “n” が続く “u” で、16 回出現します。”u”, “n” は “un” にマージされて語彙に追加されます。次に頻度の高いシンボル・ペアは “ug” が続く “h” で、15 回です。再度ペアがマージされて “hug” が語彙に追加できます。

この段階で、語彙は [“b”, “g”, “h”, “n”, “p”, “s”, “u”, “ug”, “un”, “hug”] でそして一意の単語のセットは次のように表されます :

("hug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("hug" "s", 5)

バイトペア・エンコーディングがこの時点で停止すると仮定すると、学習されたマージルールが新しい単語に適用されます (それらの新しい単語がベース語彙にないシンボルを含まない限りは)。例えば、単語 “bug” は [“b”, “ug”] にトークン化されますが “mug” は [“<unk>”, “ug”] としてトークン化されます、何故ならばシンボル “m” はベース語彙にないからです。一般には、”m” のような単一文字は “<unk>” シンボルで置き換えられません、何故ならば訓練データは通常は各文字の出現を少なくとも一つは含むからですが、絵文字のような非常に特殊な文字については発生しがちです。

前に述べたように、語彙サイズ、i.e. ベース語彙サイズ + マージの数、は選択するハイパーパラメータです。例えば GPT は 40,478 の語彙サイズを持ちます、何故ならばそれらは 478 ベース文字を持ちそして 40,000 マージの後に訓練を停止することを選択したからです。

 

バイト・レベル BPE

総ての可能なベース文字を含むベース語彙は、総てのユニコード文字がベース文字として考えられる場合などには、非常に大規模になり得ます。より良いベース語彙を持つために、GPT-2 はベース語彙としてバイトを使用します、これは賢いトリックでベース語彙にサイズ 256 であることを強制する一方で、総てのベース文字がその語彙に含まれることを確かなものにします。句読点を扱うための幾つかの追加ルールにより、GPT2 のトークナイザーは <unk> シンボルを必要とすることなく総てのテキストをトークン化できます。GPT-2 は 50,257 の語彙サイズを持ちます、これは 256 バイトのベーストークン、特殊な end-of-text (テキスト終了) トークンと 50,000 マージで学習されたシンボルに相当します。

 

WordPiece

WordPiece は BERT, DistilBERT と Electra のために利用されるサブワード・トークン化アルゴリズムです。このアルゴリズムは Japanese and Korean Voice Search (Schuster et al., 2012) で概説されて BPE に非常に良く似ています。WordPiece は最初に語彙を訓練データに存在する総ての文字を含めるように初期化して既定の数のマージルールを漸進的に学習します。BPE とは対照的に、WordPiece は最も頻度の高いシンボルペアではなく、語彙に追加された訓練データの尤度を最大化するものを選択します。

さてこれは正確には何を意味するのでしょう?前の例を参照すれば、訓練データの尤度を最大化することは、2 番目のシンボルが続く最初のシンボルの確率により除算される (シンボルペアの) 確率が総てのシンボルペアの中で最大であるような、シンボルペアを見つけることと同値です。E.g. “g” が続く “u” は “u”, “g” により除算される “ug” の確率が任意の他のシンボルペアよりも大きい場合にだけマージされます。直観的には、WordPiece は 2 つのシンボルをマージすることにより (それに値するかを確かなものにするために) それが失うものを評価するという点で BPE と僅かに異なります。

 

Unigram

Unigram は Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates (Kudo, 2018) で導入されたサブワード・トークン化アルゴリズムです。BPE や WordPiece とは対照的に、Uniram はベース語彙をシンボルの大規模な数に初期化してより小さい語彙を得るために各シンボルを漸次的に切り捨てていきます。
ベース語彙は例えば総ての事前トークン化された単語と最も一般的な部分文字列に対応できるでしょう。Unigram は transformers のどのモデルについても直接使用されていませんが、SentencePiece とともに利用されています。

各訓練ステップで、現在の語彙と Unigram 言語モデルが与えられて Unigram アルゴリズムは訓練データに渡る損失 (多くの場合、対数尤度として定義されます) を定義します。それから、語彙の各シンボルについて、アルゴリズムはシンボルが語彙から除去されたとすると全体的な損失がどのくらい増加するかを計算します。それから Unigram は損失の増加がもっとも少ないシンボル、つまり訓練データに渡る全体的な損失にもっとも影響を与えないシンボルの p (p は通常は 10% or 20%) パーセントを除去します。このプロセスは語彙が望まれるサイズに達するまで繰り返されます。Unigram アルゴリズムは任意の単語がトークン化できるようにベース文字を常に保持します。

Unigram は (BPE と WordPiece とは対照的に) マージルールに基づかないので、アルゴリズムは訓練後に新しいテキストをトークン化する幾つかの方法を持ちます。例として、訓練された Unigram トークナイザーが以下の語彙を示す場合 :

["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"],

“hugs” は [“hug”, “s”], [“h”, “ug”, “s”] or [“h”, “u”, “g”, “s”] の両者としてトークン化できるでしょう。それではどれを選択するのでしょう?Unigram は各可能なトークン化の確率を訓練後に計算できるように、語彙をセーブするのに加えて訓練コーパスの各トークンの確率をセーブします。アルゴリズムは実際い最も尤度の高いトークン化を単純に選択しますが、それらの確率に従って可能なトークン化をサンプリングする可能性も提供します。

これらの確率はその上でトークナイザーが訓練される損失により定義されます。訓練データが単語 $x_{1}, \dots, x_{N}$ から成り、そして単語 $x_{i}$ のための総ての可能なトークン化のセットが $S(x_{i})$ で定義されると仮定すると、全体的な損失は次で定義されます :

\[
\mathcal{L} = -\sum_{i=1}^{N} \log \left ( \sum_{x \in S(x_{i})} p(x) \right )
\]

 

SentencePiece

ここまで説明された総てのトークン化アルゴリズムは同じ問題を持ちます : 単語を分割するために入力テキストがスペースを使用していることが仮定されています。けれども、総ての言語が単語を分割するためにスペースを使用してはいません。一つの可能な解法は言語固有の事前トークナイザーを使用することです、例えば XML は固有の中国語、日本語、そしてタイ語の事前トークナイザーを使用しています。この問題をより一般的に解くため、SentencePiece : A simple and language independent subword tokenizer and detokenizer for Neural Text Processing (Kudo et al., 2018) は入力を raw 入力ストリームとして扱い、スペースを使用する文字のセット内に含めます。それから適切な語彙を構築するために BPE か unigram アルゴリズムを使用します。

XLNetTokenizer は例えば SentencePiece を使用しています、これはまた先の例で何故 “▁” 文字が語彙に含まれていたかです。SentencePiece によるデコードは非常に容易です、何故ならば総てのトークンは連結できて “▁” がスペースで置き換えられるだけからです。SentencePiece を使用するライブラリの総ての transformer モデルはそれを unigram との組合せで利用します。SentencePiece を使用するモデルの例は ALBERT, XLNet, Marian と T5 です。

 

以上