AI・機械学習
中級

SentencePiece BPEモード(センテンスピース ビーピーイーモード)

SentencePieceライブラリに実装されたByte Pair Encodingアルゴリズムで、空白を「▁」記号として扱う前処理不要の設計により、LLaMA・Mistral・CodeLlama等のデコーダー系LLMで標準的に使用されている。

0 回閲覧
0 いいね

SentencePiece BPEモードとは

SentencePiece BPEモードは、SentencePieceライブラリ内でByte Pair Encoding(BPE)アルゴリズムを実行するトークン化方式である。オリジナルのBPE(Sennrich et al., 2016)は空白で事前分割された単語単位で動作するが、SentencePiece BPEは空白を「▁」(U+2581)に変換して文字列全体を一括処理する点が決定的に異なる。これにより、日本語や中国語のように空白を使わない言語でも前処理なしでBPEを適用できる。

オリジナルBPEとの違い

項目オリジナルBPESentencePiece BPE
前処理空白分割 + 単語末尾マーカー不要(「▁」自動付与)
入力形式事前トークン化済みテキスト生のUnicodeテキスト
空白の扱い分割境界として除外「▁」としてトークンに含む
可逆性不完全(空白情報の損失)完全(ロスレス復元)
日本語対応形態素解析器が必要そのまま処理可能
Unicode正規化外部処理内蔵(NFKC等)
実装言語PythonC++(Pythonバインディング)
処理速度低速高速(10〜50倍)

アルゴリズムの動作

学習フェーズ

  1. コーパスの全文字をユニコード単位で分解し、初期語彙とする
  2. 隣接する文字ペアの出現頻度をカウントする
  3. 最頻出ペアを結合して新しいサブワードを語彙に追加する
  4. 目標語彙サイズに達するまでステップ2-3を繰り返す
import sentencepiece as spm

spm.SentencePieceTrainer.train(
    input='corpus.txt',
    model_prefix='bpe_model',
    vocab_size=32000,
    model_type='bpe',
    byte_fallback=True,
    character_coverage=0.9995,
    split_digits=True,
    num_threads=16
)

推論フェーズ

学習済みのマージルール(結合順序テーブル)を上から順に適用し、入力テキストを分割する:

sp = spm.SentencePieceProcessor()
sp.load('bpe_model.model')

text = '深層学習モデルの推論最適化'
tokens = sp.encode(text, out_type=str)
# ['▁深', '層', '学習', 'モデル', 'の', '推論', '最適', '化']

ids = sp.encode(text, out_type=int)
decoded = sp.decode(ids)
assert decoded == text  # 完全復元を保証

採用モデルと実装詳細

モデル語彙サイズbyte_fallbacksplit_digits特記事項
LLaMA32,000YesYesMeta初のオープンLLM
LLaMA 232,000YesYes商用利用可能
Code Llama32,000YesYesコード特化
Mistral 7B32,000YesYesLLaMA互換語彙
Mixtral 8x7B32,000YesYesMoEアーキテクチャ
Baichuan 2125,696YesNo中国語強化

byte_fallbackオプション

LLaMA系モデルで重要なbyte_fallback=Trueは、語彙に含まれない文字をUTF-8のバイト列に分解して処理する仕組みである。これによりUNKトークンが発生しないことが保証される。例えば珍しい絵文字や特殊記号も、バイト単位のトークン(<0xE2>, <0x9C>, <0x85>等)として表現できる。

tiktoken(OpenAI)との比較

GPT-4で使用されるtiktokenもBPEベースだが、SentencePiece BPEとは実装が大きく異なる:

項目SentencePiece BPEtiktoken
前処理なし(「▁」変換のみ)正規表現による事前分割
実装C++ + protobufRust + 正規表現
バイトフォールバックオプション標準
マージファイル形式.model(protobuf).tiktoken(テキスト)
処理速度高速最高速
カスタム学習可能困難

トレーニングのベストプラクティス

コーパスの前処理

SentencePiece BPEの学習品質はコーパスの質に大きく依存する:

  • データ量:最低100MB、推奨1GB以上のテキストデータ
  • 言語比率:多言語モデルでは各言語のサンプリング比率を調整(temperature sampling推奨)
  • 重複排除:同一文書の重複は語彙の偏りを生む
  • 正規化:全角半角統一、異体字正規化を事前に実施

語彙サイズの選択

用途推奨語彙サイズ理由
小規模単言語16,000〜32,000パラメータ効率重視
大規模単言語32,000〜64,000カバレッジと効率のバランス
多言語64,000〜256,000言語間の公平性確保
コード特化32,000〜100,000プログラミング記号の網羅

よくある質問(FAQ)

Q1: SentencePiece BPEの学習にはどのくらいの時間がかかりますか?

A: 32,000語彙をGBクラスのコーパスから学習する場合、16スレッドで30分〜2時間程度である。語彙サイズとcharacter_coverageの設定が計算時間に大きく影響する。

Q2: LLaMA 3はなぜSentencePiece BPEからtiktokenに移行したのですか?

A: LLaMA 3は語彙サイズを128,256に拡張し、多言語トークン効率を大幅に改善するためtiktokenベースに移行した。tiktokenの正規表現ベースの前処理がコードや数式のトークン化で有利だった点も理由の一つである。

Q3: byte_fallbackを無効にするとどうなりますか?

A: 語彙に含まれない文字がUNK(未知語)トークンになり、情報が失われる。LLM用途では常にbyte_fallback=Trueを推奨する。唯一の例外は、対象言語の文字セットが完全に既知で限定される場合(例:ASCII英語のみ)である。

まとめ

  • SentencePiece BPEは前処理不要のBPE実装で、空白を「▁」記号として扱う
  • LLaMA、Mistral、Mixtral等のデコーダー系LLMで標準採用
  • byte_fallbackによりUNKトークンゼロを保証
  • C++実装で高速処理、Python/Javaバインディング提供
  • tiktokenとは前処理方式と実装言語が異なる
  • 多言語対応にはcharacter_coverage=0.9995の設定が重要