徹底解説!Hugging Face TransformersライブラリのTokenizer入門 🚀

自然言語処理

自然言語処理(NLP)の世界では、テキストデータをコンピュータが理解できる形式に変換することが不可欠です。この重要なプロセスを担うのが「トークナイザー(Tokenizer)」です。特に、Hugging FaceのTransformersライブラリは、最新のNLPモデルを手軽に利用できる強力なツールキットであり、その中核機能の一つとして高機能なTokenizerを提供しています。 この記事では、TransformersライブラリのTokenizerに焦点を当て、その基本的な概念から実践的な使い方、さらには注意点まで、詳細に解説していきます。初心者の方でも理解できるよう、具体例を交えながら丁寧に説明しますので、ぜひ最後までお付き合いください。😊

Tokenizerとは何か? なぜ必要なのか?

Tokenizer(トークナイザー)とは、一言で言えば、テキスト(文章)をより小さな単位(トークン)に分割するプログラムです。人間にとっては自然な文章も、コンピュータ(特に機械学習モデル)はそのままでは理解できません。モデルが処理できるのは数値データ、具体的には数値の配列(テンソル)です。

そこでTokenizerは、以下のステップを通じてテキストを数値データに変換します。

  1. トークン化 (Tokenization): テキストを意味のある最小単位(トークン)に分割します。トークンは単語、サブワード(単語の一部)、文字、記号など、モデルや言語によって異なります。
  2. IDへの変換 (Conversion to IDs): 分割された各トークンを、あらかじめ定義された語彙(Vocabulary)に基づいて一意の数値IDに変換します。
  3. 特殊トークンの追加 (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_idstoken_type_idsattention_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` で示し、モデルにどのトークンに注目すべきかを伝えます。

Padding と Truncation の戦略

引数 説明
padding True or 'longest' バッチ内の最長のシーケンスに合わせてパディングします。
'max_length' max_length で指定された長さになるようにパディングします。
False or 'do_not_pad' (デフォルト) パディングを行いません。
truncation True or 'longest_first' max_length を超える場合に、バッチ内で最も長いシーケンスから切り捨てを開始します。
'only_first' 文ペア入力の場合、最初のシーケンスのみを切り捨てます。
'only_second' 文ペア入力の場合、2番目のシーケンスのみを切り捨てます。
False (デフォルト) 切り捨てを行いません。
max_length 整数 or None パディングまたはトランケーションの最大長を指定します。None の場合はモデルの最大許容長が使われます。
return_tensors 'pt', 'tf', 'np', or None (デフォルト) 返すテンソルの形式を指定します (PyTorch, TensorFlow, NumPy)。Noneの場合はPythonのリストを返します。

特殊トークン (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モデルを活用した様々なタスクに挑戦できます。ぜひ、この記事を参考に、自然言語処理の世界を探求してみてください!🌍💬

コメント

タイトルとURLをコピーしました