HuggingFace Transformers 4.6 : ノートブック : Getting Started トークナイザー (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/11/2021 (4.6.1)
* 本ページは、HuggingFace Transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Transformers Notebooks : Getting Started Tokenizers
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
スケジュールは弊社 公式 Web サイト でご確認頂けます。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
人工知能研究開発支援 | 人工知能研修サービス | テレワーク & オンライン授業を支援 |
PoC(概念実証)を失敗させないための支援 (本支援はセミナーに参加しアンケートに回答した方を対象としています。) |
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
ノートブック : Getting Started トークナイザー
イントロダクション
機械学習や深層学習の自然言語処理モデルに深く潜る前に、総ての実践者は raw 入力文字列を訓練可能なモデルにより理解可能な表現にマップする方法を見つけるべきです。
一つの非常に単純なアプローチは総ての空白に渡り入力を分割して各単語に識別子を割り当てることです。このアプローチは Python の下のコードに類似して見えます。
s = "very long corpus..."
words = s.split(" ") # Split over space
vocabulary = dict(enumerate(set(words))) # Map storing the word to it's corresponding id
このアプローチは貴方の語彙が少ないままなら上手く動作するかもしれません、というのはそれは元の入力に存在する総ての単語 (or トークン) をストアするからです。更に、”cat” と “cats” のような単語のバリエーションはそれらの意味が非常に近い場合でさえも同じ識別子を共有しないでしょう。
サブトークンのトークン化
上で説明された問題を乗り越えるために、最近のワークは「サブトークン」トークン化を活用した、トークン化上で成されてきました。サブトークン は前の分割ストラテジーを単語を (データから学習された) 文法的にロジカルなサブコンポーネントに更に分解するように拡張します。
単語 cat と cats の前の例を取れば、単語 cats のサブトークン化は [cat, ##s] になります。ここで prefix “##” は初期入力のサブトークンを示します。そのような訓練アルゴリズムは英語コーパスに渡り “##ing”, “##ed” のようなサブトークンを抽出するかもしれません。
貴方が考えるかもしれないように、「ピース」全体の組合せを活用したこの種類のサブトークン構築は (機械学習モデルを訓練するために持ち運ばなければならない) 語彙のサイズを削減します。一方で、一つのトークンが複数のサブトークンに分解されるかもしれないので、モデルの入力が増加して入力シークエンスの長さにわたる非線形の複雑さを伴うモデルについて問題になるかもしれません。
総てのトークン化アルゴリズムの中で、Transformers ベースの SoTA モデルで利用された幾つかのサブトークン・アルゴリズムにハイライトを当てることができます :
- Byte Pair Encoding (BPE) – Neural Machine Translation of Rare Words with Subword Units (Sennrich et al., 2015)
サブワード・ユニットによる稀な単語のニューラル機械翻訳
- Word Piece – Japanese and Korean voice search (Schuster, M., and Nakajima, K., 2015)
Word Piece – 日本語と韓国語の音声検索
- Unigram Language Model – Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates (Kudo, T., 2018)
Unigram 言語モデル – サブワード正則化 : 複数のサブワード候補によるニューラルネットワーク翻訳モデルの改良
- Sentence Piece – A simple and language independent subword tokenizer and detokenizer for Neural Text Processing (Taku Kudo and John Richardson, 2018)
Sentence Piece – ニューラルテキスト処理のための単純で言語独立なサブワード・トークナイザーと detokenizer
それら総てを通り抜けることはこのノートブックの範囲外ですので、それをどのように利用できるかにだけハイライトします。
@huggingface/tokenizers ライブラリ
transformers ライブラリとともに、@huggingface は一般的なマルチコアマシン上で数十 Gb/s でテキストを訓練、トークン化そしてデコードできる非常に高速なトークン化ライブラリを提供しています。
ネイティブなメモリ-aware な方法でマルチコア並列計算を活用することを可能にするためにライブラリは Rust で書かれていて、その上に Python と NodeJS のためのバインディングを提供しています (より多くのバインディングが将来追加される可能性があります)。
ライブラリが取り替え可能な end-to-end なトークナイザーを作成するために必要な総てのブロックを提供するように設計しました。その意味で、これらの様々なコンポーネントを提供します :
- Normalizer : 初期入力文字列に渡り初期変換の総てを実行します。例えばあるテキストを小文字化し、多分それを strip し、あるいは一般的な unicode 正規化プロセスの一つを適用することさえ必要である場合、Normalizer を追加します。
- PreTokenizer : 初期入力文字列の分割を担当します。元の文字列をどこでどのように事前にセグメント化するかを決定するコンポーネントです。最も単純な例は前に見たように空白で単純に分割することです。
- モデル : 総てのサブトークンの発見 (= discovery) と生成を処理します、この部分は訓練可能で実際には入力データに依存しています。
- Post-Processor : Transformers ベースの SoTA モデルの幾つかと互換な進んだ構築機能を提供します。例えば、BERT についてそれはトークン化されたセンテンスを [CLS] と [SEP] トークンでラップします。
- Decoder : トークン化された入力を元の文字列にマップし戻すことを担当します。デコーダは通常は前に使用した PreTokenizer に従って選択されます。
- Trainer : 各モデルに訓練機能を提供します。
上のコンポーネントの各々のために複数の実装を提供します :
- Normalizer : Lowercase, Unicode (NFD, NFKD, NFC, NFKC), Bert, Strip, …
- PreTokenizer : ByteLevel, WhitespaceSplit, CharDelimiterSplit, Metaspace, …
- Model : WordLevel, BPE, WordPiece
- Post-Processor : BertProcessor, …
- Decoder : WordLevel, BPE, WordPiece, …
動作するトークン化パイプラインを作成するためにこれらのビルディング・ブロックの総てを組み合わせることができます。次のセクションで最初のパイプラインを調べます。
Alright, 今では tokenizers を通して最初のトークン化パイプラインを実装する準備ができました。
このため、このノートブックの目的で Byte-Pair エンコーディング (BPE) トークナイザーを非常に小さい入力上で訓練します。Peter Norving からのファイル で作業します。このファイルはおよそ 130,000 行の raw テキストを含みます、これは動作するトークナイザーを生成するためにライブラリにより処理されます。
!pip install tokenizers
BIG_FILE_URL = 'https://raw.githubusercontent.com/dscape/spell/master/test/resources/big.txt'
# Let's download the file and save it somewhere
from requests import get
with open('big.txt', 'wb') as big_f:
response = get(BIG_FILE_URL, )
if response.status_code == 200:
big_f.write(response.content)
else:
print("Unable to get the file: {}".format(response.reason))
訓練データを持った今、トークナイザーのためのパイプライン全体を作成する必要があります。
# For the user's convenience `tokenizers` provides some very high-level classes encapsulating
# the overall pipeline for various well-known tokenization algorithm.
# Everything described below can be replaced by the ByteLevelBPETokenizer class.
from tokenizers import Tokenizer
from tokenizers.decoders import ByteLevel as ByteLevelDecoder
from tokenizers.models import BPE
from tokenizers.normalizers import Lowercase, NFKC, Sequence
from tokenizers.pre_tokenizers import ByteLevel
# First we create an empty Byte-Pair Encoding model (i.e. not trained model)
tokenizer = Tokenizer(BPE())
# Then we enable lower-casing and unicode-normalization
# The Sequence normalizer allows us to combine multiple Normalizer that will be
# executed in order.
tokenizer.normalizer = Sequence([
NFKC(),
Lowercase()
])
# Our tokenizer also needs a pre-tokenizer responsible for converting the input to a ByteLevel representation.
tokenizer.pre_tokenizer = ByteLevel()
# And finally, let's plug a decoder so we can recover from a tokenized input to the original one
tokenizer.decoder = ByteLevelDecoder()
このノートブックで先にダウンロードしたコーパス上でパイプライン全体が訓練される準備が今は整いました。
from tokenizers.trainers import BpeTrainer
# We initialize our trainer, giving him the details about the vocabulary we want to generate
trainer = BpeTrainer(vocab_size=25000, show_progress=True, initial_alphabet=ByteLevel.alphabet())
tokenizer.train(files=["big.txt"], trainer=trainer)
print("Trained vocab size: {}".format(tokenizer.get_vocab_size()))
Trained vocab size: 25000
Et voilà ! tokenizers を使用して貴方の本当に最初のトークナイザーをスクラッチから訓練しました。もちろん、これは基本だけをカバーしており、そして貴方は Trainer クラスの add_special_tokens や special_tokens パラメータを見ることを望むかもしれませんが、プロセス全体は非常に類似しているはずです。
モデルの内容をそれを後で再利用するためにセーブできます。
# You will see the generated files in the output.
tokenizer.model.save('.')
['./vocab.json', './merges.txt']
今は、訓練モデルをロードして新たに訓練されたトークナイザーを利用し始めましょう。
# Let's tokenizer a simple input
tokenizer.model = BPE('vocab.json', 'merges.txt')
encoding = tokenizer.encode("This is a simple input to be tokenized")
print("Encoded string: {}".format(encoding.tokens))
decoded = tokenizer.decode(encoding.ids)
print("Decoded string: {}".format(decoded))
Encoded string: ['Ġthis', 'Ġis', 'Ġa', 'Ġsimple', 'Ġin', 'put', 'Ġto', 'Ġbe', 'Ġtoken', 'ized'] Decoded string: this is a simple input to be tokenized
エンコーディング構造は複数のプロパティを公開しています、それらは transformers モデルで作業するときに有用です。
- normalized_str: 正規化 (小文字化、unicode、stripping 等) 後の入力文字列
- original_str: それが提供されたときの入力文字列
- tokens: 文字列表現による生成されたトークン
- input_ids: 整数表現による生成されたトークン
- attention_mask: 入力がトークナイザーによりパディングされている場合、これは任意のパディングされていないトークンのために 1、パディングされているもののためには 0 のベクトルです。
- special_token_mask: 入力が [CLS], [SEP], [MASK], [PAD] のような特殊トークンを含む場合、これは特殊トークンが追加された場所で 1 を持つベクトルになります。
- type_ids: 入力が (質問、コンテキスト) のような複数の「パート」から成る場合、これは各トークンについてそれが属するセグメントのベクトルになります。
- overflowing: 入力が長さ制限のために複数のサブパートに切り捨てられた場合 (例えば BERT についてはシークエンス長は 512 に制限されています)、これは総ての残りのオーバーフローしたパートを含みます。
以上