Chuyển đến nội dung chính

レッスン 3: トークン化の詳細 — Word から BPE、WordPiece、SentencePiece まで

トークン化方法を比較します: ホワイトスペース、BPE、WordPiece、Unigram、SentencePiece。語彙のサイズとトレードオフ。トークナイザーをゼロからトレーニングします。ハグフェイストークナイザーライブラリ。ベトナム語および特定のトークン化の課題。

🧠 AI と ML — レッスン 2 レッスン 3: トークン化の詳細 - Word から BPE、WordPiece、SentencePiece へ

NLP の基礎から上級まで: 自然言語処理をマスターする

パート 1: NLP の基礎 — コンピューターのレンズを通して言語を理解する

xdev.asia

はじめに

トークン化は、すべての NLP パイプラインにおける最初で最も重要なステップです。これはモデルがテキストをどのように「見る」かを決定し、パフォーマンスに直接影響します。

💡 すべての最新の LLM (GPT-4、Gemini、Claude、LLaMA) は サブワード トークン化 を使用します。この記事ではその理由を説明します。


1. Word レベルのトークン化ではなぜ不十分なのでしょうか?

OOV (語彙不足) 問題

vocab = {"hello", "world", "natural", "language"}

# Gặp từ mới → OOV!
text = "unhappiness"  # Không có trong vocab → [UNK]

# Word-level vocab cần KHỔNG LỒ
# Tiếng Anh: ~170,000 từ
# + Tên riêng, thuật ngữ, viết tắt → 500,000+
# + Đa ngôn ngữ → Hàng triệu từ

3 つの主な問題

問題単語レベルサブワードキャラクターレベル
語彙サイズ巨大 (500K+)中程度 (32K–128K)非常に小さい (256)
OOVたくさんの[UNK]めったに決して
意味論的な意味良い良い悪い(各キャラクター)
シーケンスの長さ短い中程度とても長い

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

2.1 アルゴリズム

Bước 1: Bắt đầu với tất cả characters làm vocab
         Vocab: {a, b, c, ..., z, _}

Bước 2: Đếm tần suất các cặp adjacent tokens
         "l o w" → (l,o): 5, (o,w): 5
         "l o w e r" → (l,o): 5, (o,w): 5, (w,e): 2, (e,r): 2
         "n e w e r" → (n,e): 1, (e,w): 1, (w,e): 2, (e,r): 2

Bước 3: Merge cặp có tần suất cao nhất
         (l,o) → "lo"     Vocab: {a, b, ..., z, _, lo}

Bước 4: Lặp lại bước 2-3 cho đến khi đạt vocab size mong muốn
         "lo w" → (lo,w) → "low"
         Vocab: {a, b, ..., z, _, lo, low, ...}

2.2 BPE の実際

from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace

# 1. Khởi tạo BPE tokenizer
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
tokenizer.pre_tokenizer = Whitespace()

# 2. Training
trainer = BpeTrainer(
    vocab_size=30000,
    special_tokens=["[UNK]", "[PAD]", "[CLS]", "[SEP]", "[MASK]"],
    min_frequency=2,
)
tokenizer.train(files=["corpus.txt"], trainer=trainer)

# 3. Tokenize
output = tokenizer.encode("Xử lý ngôn ngữ tự nhiên rất thú vị")
print(output.tokens)
# ['X', 'ử', 'lý', 'ngôn', 'ngữ', 'tự', 'nhiên', 'rất', 'thú', 'vị']

使用者: GPT-2、GPT-3、GPT-4、LLaMA、RoBERTa


3. ワードピース

WordPiece は BPE に似ていますが、頻度の代わりに 尤度 を使用します。

BPE:       Merge cặp có tần suất CAO nhất
WordPiece: Merge cặp tối đa hóa LIKELIHOOD của training data
from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")

text = "unhappiness is unbelievable"
tokens = tokenizer.tokenize(text)
print(tokens)
# ['un', '##happiness', 'is', 'un', '##believable']
# '##' = tiếp nối từ trước (không phải đầu từ)

使用者: BERT、DistilBERT、PhoBERT


4. センテンスピースとユニグラム

文の一部

テキストを 生のバイト として扱います。スペースの事前トークン化は必要ありません。

import sentencepiece as spm

# Train
spm.SentencePieceTrainer.Train(
    input='corpus.txt',
    model_prefix='my_model',
    vocab_size=32000,
    model_type='unigram',  # hoặc 'bpe'
)

# Load & use
sp = spm.SentencePieceProcessor()
sp.Load('my_model.model')

text = "Xử lý ngôn ngữ tự nhiên"
tokens = sp.EncodeAsPieces(text)
print(tokens)
# ['▁Xử', '▁lý', '▁ngôn', '▁ngữ', '▁tự', '▁nhiên']
# '▁' = đầu từ mới

使用者: T5、ALBERT、XLNet、LLaMA (結合 BPE)


5. 比較の概要

方法マージ方法事前にトークン化しますか?記号モデル
BPE最高周波数必要 (空白)—GPT、LLaMA、ロベルタ
ワードピース最も高い可能性必要 (空白)## (続き)バート、フォバート
ユニグラムトークンの種類はほとんど影響しません。必要ありません▁ (単語の始まり)T5、アルバート
センテンスピースBPE またはユニグラム必要ありません▁ (単語の始まり)T5、ラマ

6. ハグフェイストークナイザー — 練習

from transformers import AutoTokenizer

# So sánh tokenization giữa các model
models = [
    "bert-base-uncased",
    "gpt2",
    "google/flan-t5-base",
]

text = "Tokenization is surprisingly important for NLP"

for model_name in models:
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    tokens = tokenizer.tokenize(text)
    ids = tokenizer.encode(text)
    print(f"\n{model_name}:")
    print(f"  Tokens ({len(tokens)}): {tokens}")
    print(f"  IDs: {ids}")

7. ベトナム語のトークン化

from transformers import AutoTokenizer

# PhoBERT tokenizer (WordPiece, có word segmentation)
phobert_tok = AutoTokenizer.from_pretrained("vinai/phobert-base-v2")
text = "Xử lý ngôn ngữ tự nhiên rất thú vị"
print(phobert_tok.tokenize(text))

# Gemma/LLaMA tokenizer (BPE, byte-level)
gemma_tok = AutoTokenizer.from_pretrained("google/gemma-2b")
print(gemma_tok.tokenize(text))
# Tiếng Việt thường bị tách thành nhiều subword hơn tiếng Anh
# → Sequence dài hơn → Tốn cost inference hơn!

🇻🇳 洞察: GPT-4 / Gemini のトークナイザーは、ベトナム語を英語よりも 多くのトークンに分割し (~1.5 ~ 2 倍)、その結果、API コストが高くなります。


概要

重要なポイント詳細
単語レベル語彙が大きすぎて、OOV が多い → 実行不可能
BPE頻度によるマージ、最も一般的 (GPT、LLaMA)
ワードピース可能性によってマージし、使用します ## (バート)
センテンスピース事前のトークン化は不要、言語に依存しない
ベトナム語English Tokenizer はより多くのトークンに分割 → コストに注意

次の記事

レッスン 4: Bag of Words、TF-IDF、N グラム — 古典的なテキスト表現方法ですが、依然として多くの問題で効果的です。