自然言語処理(NLP)の世界では、テキストデータをコンピュータが理解できる形式に変換することが不可欠です。この重要なプロセスを担うのが「トークナイザー(Tokenizer)」です。特に、Hugging FaceのTransformersライブラリは、最新のNLPモデルを手軽に利用できる強力なツールキットであり、その中核機能の一つとして高機能なTokenizerを提供しています。 この記事では、TransformersライブラリのTokenizerに焦点を当て、その基本的な概念から実践的な使い方、さらには注意点まで、詳細に解説していきます。初心者の方でも理解できるよう、具体例を交えながら丁寧に説明しますので、ぜひ最後までお付き合いください。😊
Tokenizerとは何か? なぜ必要なのか?
Tokenizer(トークナイザー)とは、一言で言えば、テキスト(文章)をより小さな単位(トークン)に分割するプログラムです。人間にとっては自然な文章も、コンピュータ(特に機械学習モデル)はそのままでは理解できません。モデルが処理できるのは数値データ、具体的には数値の配列(テンソル)です。
そこでTokenizerは、以下のステップを通じてテキストを数値データに変換します。
- トークン化 (Tokenization): テキストを意味のある最小単位(トークン)に分割します。トークンは単語、サブワード(単語の一部)、文字、記号など、モデルや言語によって異なります。
- IDへの変換 (Conversion to IDs): 分割された各トークンを、あらかじめ定義された語彙(Vocabulary)に基づいて一意の数値IDに変換します。
- 特殊トークンの追加 (Adding Special Tokens): モデルによっては、文章の開始や終了、区切りを示す特別なトークン(例: `[CLS]`, `[SEP]`)が必要です。Tokenizerはこれらを自動的に追加します。
このプロセスにより、自然言語のテキストがモデルへの入力に適した数値のシーケンスに変換されるのです。TransformersライブラリのTokenizerは、様々なモデルに対応した高機能なトークン化を提供し、NLPタスクの精度向上に貢献しています。
サブワードトークン化:未知語問題への対応策
トークン化の最もシンプルな方法は、テキストをスペースや句読点で区切る「単語トークン化」です。しかし、この方法にはいくつかの課題があります。
- 語彙爆発: 大規模なテキストデータでは、語彙(ユニークな単語の種類)が非常に多くなり、モデルが扱うパラメータ数が増大します。
- 未知語 (Out-of-Vocabulary, OOV) 問題: モデルの学習時に存在しなかった単語(新語、固有名詞、スペルミスなど)が登場すると、モデルはそれを理解できません。通常、`
` (Unknown) のような特別なトークンに置き換えられますが、情報が失われてしまいます。 - 形態素の無視: “running”, “ran”, “runs” のような単語は、語源が同じでも異なるトークンとして扱われ、関連性が捉えにくくなります。
これらの課題を解決するために登場したのがサブワードトークン化 (Subword Tokenization) です。サブワードトークン化は、単語をさらに意味のある小さな単位(サブワード)に分割する手法です。これにより、頻出する単語はそのままトークンとしつつ、未知語や稀な単語は既知のサブワードの組み合わせで表現できます。
代表的なサブワードトークン化アルゴリズムには以下のようなものがあります。
主なサブワードトークン化アルゴリズム
- BPE (Byte-Pair Encoding): 元々はデータ圧縮アルゴリズム。テキストデータ中で最も頻繁に出現するバイト(文字)ペアを繰り返し結合し、語彙を構築します。GPTシリーズなどで利用されています。
- WordPiece: BERTやDistilBERTなどで利用されているアルゴリズム。BPEと似ていますが、ペアを結合する基準として、ペアの出現頻度ではなく、語彙に追加した際の尤度(likelihood)の最大化を用います。単語の先頭以外のサブワードには `##` を付けるのが特徴です。
- SentencePiece: Googleによって開発された、言語に依存しないトークナイザー。テキストを生のまま(Unicode文字シーケンスとして)扱い、空白を含む全ての文字を処理対象とします。BPEまたはUnigram言語モデルアルゴリズムに基づいてトークン化を行います。多言語モデル(T5、ALBERTなど)でよく利用されます。
- Unigram: 各サブワードが独立して出現する確率(ユニグラム確率)に基づいて、最も尤度の高いサブワード分割を見つけます。SentencePieceで利用されるアルゴリズムの一つです。
これらのアルゴリズムにより、語彙サイズを適切に保ちつつ、未知語問題に頑健に対応できるようになりました。Transformersライブラリは、これらの様々なアルゴリズムに基づいたTokenizerをサポートしています。
TransformersのTokenizerを使ってみよう!
Transformersライブラリの最大の利点の一つは、AutoTokenizer
クラスの存在です。AutoTokenizer
を使うと、モデル名を指定するだけで、そのモデルに対応する学習済みのTokenizerをHugging Face Hubから自動的にダウンロードしてロードできます。これにより、モデルごとにどのTokenizerクラスを使うべきか意識する必要がなくなります。
まずは、ライブラリをインストールしましょう。(日本語モデルを使う場合は、追加の依存関係もインストールすると便利です)
pip install transformers[ja] sentencepiece
次に、日本語BERTモデル(`cl-tohoku/bert-base-japanese-whole-word-masking`)に対応するTokenizerをロードしてみましょう。
from transformers import AutoTokenizer
# モデル名を指定してTokenizerをロード
model_name = "cl-tohoku/bert-base-japanese-whole-word-masking"
tokenizer = AutoTokenizer.from_pretrained(model_name)
print(f"{model_name} の Tokenizer をロードしました: {tokenizer.__class__.__name__}")
# 出力例: cl-tohoku/bert-base-japanese-whole-word-masking の Tokenizer をロードしました: BertJapaneseTokenizer
これで、`tokenizer` オブジェクトを使ってテキストを処理する準備ができました! 🎉
テキストのエンコード(トークンIDへの変換)
Tokenizerの最も基本的な機能は、テキスト(文字列)を受け取り、モデルが入力として受け取れる形式(通常はトークンIDのリスト)に変換することです。これは、Tokenizerオブジェクトを直接呼び出すことで簡単に行えます。
text = "私はHugging FaceのTransformersライブラリを学んでいます。"
# テキストをエンコード
encoded_input = tokenizer(text)
print("エンコード結果:")
print(encoded_input)
# エンコードされたIDをトークンに戻して確認
tokens = tokenizer.convert_ids_to_tokens(encoded_input["input_ids"])
print("\nトークン:")
print(tokens)
出力を見ると、辞書形式で input_ids
、token_type_ids
、attention_mask
が返されていることがわかります。
input_ids
: 各トークンに対応する数値IDのリストです。これがモデルへの主要な入力となります。token_type_ids
: (主にBERTのようなモデルで)2つの文を入力する場合に、どちらの文に属するトークンかを示すIDのリストです。通常、最初の文は0、2番目の文は1となります。単一の文の場合はすべて0です。attention_mask
: どのトークンが実際の入力で、どれがパディング(後述)かをモデルに示すためのマスクです。実際のトークンは1、パディングトークンは0となります。
また、トークンを見ると、元のテキストがサブワードに分割されていること、そして文頭に `[CLS]`、文末に `[SEP]` という特殊トークンが自動的に追加されていることが確認できます。
トークンIDのデコード(テキストへの変換)
モデルの出力など、トークンIDのシーケンスを元のテキストに戻したい場合は、decode()
メソッドを使います。
input_ids = encoded_input["input_ids"]
# トークンIDをデコード
decoded_text = tokenizer.decode(input_ids)
print("デコード結果:")
print(decoded_text)
# 出力例: [CLS] 私 は Hugging Face の Transformers ライブラリ を 学ん で い ます 。 [SEP]
デフォルトでは特殊トークンもデコードされますが、skip_special_tokens=True
を指定することで、これらを無視してデコードすることも可能です。
decoded_text_no_special = tokenizer.decode(input_ids, skip_special_tokens=True)
print("\n特殊トークンを除外してデコード:")
print(decoded_text_no_special)
# 出力例: 私 は Hugging Face の Transformers ライブラリ を 学ん で い ます 。
バッチ処理とPadding/Truncation
実際の機械学習タスクでは、複数のテキストデータをまとめて処理(バッチ処理)するのが一般的です。しかし、バッチ内のテキストの長さは通常異なります。一方、多くのTransformerモデルは固定長の入力を期待します。この問題を解決するのがパディング (Padding) とトランケーション (Truncation) です。
- パディング (Padding): バッチ内で最も長いシーケンスに合わせて、短いシーケンスの末尾に特別なパディングトークン(通常は `
` または `[PAD]`)を追加し、長さを揃える処理。 - トランケーション (Truncation): モデルが受け入れられる最大長(または指定された最大長)を超えるシーケンスを、末尾から切り捨てる処理。
TransformersのTokenizerでは、これらの処理をTokenizer呼び出し時に引数で簡単に制御できます。
sentences = [
"今日は良い天気です。",
"明日は雨が降るかもしれないので、傘を持っていきましょう。"
]
# パディングとトランケーションを有効にしてエンコード
# max_lengthを指定しない場合、モデルのデフォルト最大長が使われるか、
# padding='longest' の場合はバッチ内の最長に合わせる
encoded_batch = tokenizer(
sentences,
padding=True, # パディングを有効化 ('longest' や 'max_length' も指定可)
truncation=True, # トランケーションを有効化
max_length=20, # 最大長を指定 (指定しない場合はモデル固有の最大長)
return_tensors="pt" # PyTorchテンソルで結果を返す ('tf' or 'np'も可)
)
print("バッチエンコード結果:")
print(encoded_batch)
print("\n各文のトークン:")
for i in range(len(sentences)):
tokens = tokenizer.convert_ids_to_tokens(encoded_batch['input_ids'][i])
print(f"文 {i+1}: {tokens}")
上記の例では、`max_length=20` を指定したため、両方の文がトークン数20になるように、短い文にはパディングトークン(`[PAD]`、IDは通常0)が追加され、長い文は末尾が切り捨てられています。
ここで重要になるのが attention_mask
です。パディングされたトークンは実際の情報を持たないため、モデルのAttention計算(どのトークンに注目するかを決める計算)で無視されるべきです。`attention_mask` は、実際のトークンの位置を `1`、パディングトークンの位置を `0` で示し、モデルにどのトークンに注目すべきかを伝えます。
特殊トークン (Special Tokens)
多くのTransformerモデルは、特定の目的のために特殊トークンを利用します。Tokenizerは、モデルが必要とするこれらの特殊トークンを自動的に処理(追加・認識)します。
よく使われる特殊トークンには以下のようなものがあります。
[CLS]
(Classification Token): BERT系のモデルで、文全体の意味を集約するために文頭に追加されます。分類タスクなどで、このトークンの最終層の隠れ状態ベクトルが利用されることが多いです。[SEP]
(Separator Token): 文の終わりや、二つの文の区切りを示すために使われます。[PAD]
(Padding Token): シーケンスの長さを揃えるためのパディングに使われます。[UNK]
(Unknown Token): 語彙にない未知語を表すために使われます。(サブワードトークン化ではあまり使われなくなりました)[MASK]
(Mask Token): マスク言語モデル(MLM)の事前学習タスクで、予測対象のトークンを隠すために使われます。
Tokenizerオブジェクトの属性を通じて、これらの特殊トークンやそのIDを確認できます。
print("CLSトークン:", tokenizer.cls_token, " ID:", tokenizer.cls_token_id)
print("SEPトークン:", tokenizer.sep_token, " ID:", tokenizer.sep_token_id)
print("PADトークン:", tokenizer.pad_token, " ID:", tokenizer.pad_token_id)
print("UNKトークン:", tokenizer.unk_token, " ID:", tokenizer.unk_token_id)
print("MASKトークン:", tokenizer.mask_token, " ID:", tokenizer.mask_token_id)
# すべての特殊トークンマップ
print("\n特殊トークンマップ:", tokenizer.special_tokens_map)
Tokenizerを呼び出す際、デフォルトでは add_special_tokens=True
となっており、モデルに必要な特殊トークン(通常は [CLS]
と [SEP]
)が自動で追加されます。これを無効にしたい場合は add_special_tokens=False
を指定します。
まとめ
この記事では、Hugging Face TransformersライブラリのTokenizerについて、その基本的な概念から主要な機能、実践的な使い方までを解説しました。
Tokenizerは、自然言語処理モデルがテキストデータを理解するための重要な「翻訳者」です。主な機能は以下の通りです。
- テキストをトークン(単語、サブワード、文字など)に分割するトークン化
- トークンを数値IDに変換するエンコード
- 数値IDをテキストに戻すデコード
- モデルが必要とする特殊トークンの自動追加
- バッチ処理のためのパディングとトランケーション
- パディングされたトークンを区別するためのアテンションマスク生成
特に AutoTokenizer
を使うことで、様々なモデルに対応したTokenizerを簡単に利用開始できます。パディングやトランケーションのオプションを適切に設定することで、効率的なバッチ処理が可能になります。
TransformersライブラリとTokenizerを使いこなすことで、最新のNLPモデルを活用した様々なタスクに挑戦できます。ぜひ、この記事を参考に、自然言語処理の世界を探求してみてください!🌍💬
コメント