huggingface-tokenizers について
HuggingFace Tokenizersは、Rustを基盤とし、PythonとNode.jsのバインディングを備えたテキストトークナイザーライブラリです。独自学習やバッチエンコード、トークンと原文の位置合わせに対応します。
主な機能
- 01BPE、WordPiece、Unigramモデル
- 02独自トークナイザーの学習
- 03パディング付きバッチエンコード
- 04トークンとテキスト位置の対応
- 05テキストの正規化と処理
活用シーン
- 01大規模コーパスでのトークナイザー学習
- 02NLPモデル用バッチの準備
- 03予測結果を原文の範囲に対応付け
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ orchestra-research/ ai-research-skills --skill huggingface-tokenizersインストール後、Claude Code で/huggingface-tokenizersを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/algorithms.mdintegration.mdpipeline.mdtraining.md詳細
HuggingFace Tokenizers - NLP 向けの高速トークナイゼーション
Rust による高いパフォーマンスと Python の使いやすさを兼ね備えた、高速で本番環境に対応したトークナイザーです。
HuggingFace Tokenizers を使うべき場面
HuggingFace Tokenizers を使うとよい場合:
- 極めて高速なトークナイズが必要な場合(テキスト 1GB あたり 20 秒未満)
- カスタムトークナイザーをゼロから学習させる場合
- アライメントの追跡(トークン → 元テキストの位置)が必要な場合
- 本番環境の NLP パイプラインを構築する場合
- 大規模なコーパスを効率的にトークナイズする必要がある場合
パフォーマンス:
- 速度: CPU で 1GB のトークナイズに 20 秒未満
- 実装: Rust コアと Python/Node.js バインディング
- 効率: 純粋な Python 実装より 10〜100 倍高速
代わりに使用できるもの:
- SentencePiece: 言語非依存で、T5/ALBERT で使用
- tiktoken: GPT モデル向けの OpenAI の BPE トークナイザー
- transformers AutoTokenizer: 学習済みのものを読み込むだけの場合(内部でこのライブラリを使用)
クイックスタート
インストール
# Install tokenizers
pip install tokenizers
# With transformers integration
pip install tokenizers transformers
学習済みトークナイザーの読み込み
from tokenizers import Tokenizer
# Load from HuggingFace Hub
tokenizer = Tokenizer.from_pretrained("bert-base-uncased")
# Encode text
output = tokenizer.encode("Hello, how are you?")
print(output.tokens) # ['hello', ',', 'how', 'are', 'you', '?']
print(output.ids) # [7592, 1010, 2129, 2024, 2017, 1029]
# Decode back
text = tokenizer.decode(output.ids)
print(text) # "hello, how are you?"
カスタム BPE トークナイザーの学習
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace
# Initialize tokenizer with BPE model
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
tokenizer.pre_tokenizer = Whitespace()
# Configure trainer
trainer = BpeTrainer(
vocab_size=30000,
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"],
min_frequency=2
)
# Train on files
files = ["train.txt", "validation.txt"]
tokenizer.train(files, trainer)
# Save
tokenizer.save("my-tokenizer.json")
学習時間: 100MB のコーパスで約 1〜2 分、1GB で約 10〜20 分
パディングを使ったバッチエンコーディング
# Enable padding
tokenizer.enable_padding(pad_id=3, pad_token="[PAD]")
# Encode batch
texts = ["Hello world", "This is a longer sentence"]
encodings = tokenizer.encode_batch(texts)
for encoding in encodings:
print(encoding.ids)
# [101, 7592, 2088, 102, 3, 3, 3]
# [101, 2023, 2003, 1037, 2936, 6251, 102]
トークナイゼーションのアルゴリズム
BPE(Byte-Pair Encoding)
仕組み:
- 文字レベルの語彙から開始する
- 最も頻出する文字ペアを見つける
- それを新しいトークンとしてマージし、語彙に追加する
- 語彙サイズに達するまで繰り返す
使用例: GPT-2、GPT-3、RoBERTa、BART、DeBERTa
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import ByteLevel
tokenizer = Tokenizer(BPE(unk_token="<|endoftext|>"))
tokenizer.pre_tokenizer = ByteLevel()
trainer = BpeTrainer(
vocab_size=50257,
special_tokens=["<|endoftext|>"],
min_frequency=2
)
tokenizer.train(files=["data.txt"], trainer=trainer)
利点:
- OOV 単語をうまく扱える(サブワードに分割される)
- 語彙サイズを柔軟に設定できる
- 形態論的に豊かな言語に適している
トレードオフ:
- トークナイズ結果がマージの順序に依存する
- 一般的な単語が予想外に分割されることがある
WordPiece
仕組み:
- 文字の語彙から開始する
- マージ候補のペアを
frequency(pair) / (frequency(first) × frequency(second))でスコア付けする - 最もスコアの高いペアをマージする
- 語彙サイズに達するまで繰り返す
使用例: BERT、DistilBERT、MobileBERT
from tokenizers import Tokenizer
from tokenizers.models import WordPiece
from tokenizers.trainers import WordPieceTrainer
from tokenizers.pre_tokenizers import Whitespace
from tokenizers.normalizers import BertNormalizer
tokenizer = Tokenizer(WordPiece(unk_token="[UNK]"))
tokenizer.normalizer = BertNormalizer(lowercase=True)
tokenizer.pre_tokenizer = Whitespace()
trainer = WordPieceTrainer(
vocab_size=30522,
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"],
continuing_subword_prefix="##"
)
tokenizer.train(files=["corpus.txt"], trainer=trainer)
利点:
- 意味のあるマージを優先する(スコアが高いほど意味的に関連が強い)
- BERT で良好な結果(最先端の性能)を達成するのに使用された
トレードオフ:
- サブワードに一致しない場合、未知語は
[UNK]になる - マージルールではなく語彙を保存するため、ファイルが大きくなる
Unigram
仕組み:
- 大きな語彙(すべての部分文字列)から開始する
- 現在の語彙でコーパスの損失を計算する
- 損失への影響が最も小さいトークンを削除する
- 語彙サイズに達するまで繰り返す
使用例: ALBERT、T5、mBART、XLNet(SentencePiece 経由)
from tokenizers import Tokenizer
from tokenizers.models import Unigram
from tokenizers.trainers import UnigramTrainer
tokenizer = Tokenizer(Unigram())
trainer = UnigramTrainer(
vocab_size=8000,
special_tokens=["<unk>", "<s>", "</s>"],
unk_token="<unk>"
)
tokenizer.train(files=["data.txt"], trainer=trainer)
利点:
- 確率的である(最も尤もらしいトークナイズを見つける)
- 単語の境界がない言語でもうまく機能する
- 多様な言語的文脈を扱える
トレードオフ:
- 学習の計算コストが高い
- 調整すべきハイパーパラメータが多い
トークナイゼーションのパイプライン
完全なパイプライン: 正規化 → 事前トークン化 → モデル → 後処理
正規化
テキストをクリーニングして標準化します:
from tokenizers.normalizers import NFD, StripAccents, Lowercase, Sequence
tokenizer.normalizer = Sequence([
NFD(), # Unicode normalization (decompose)
Lowercase(), # Convert to lowercase
StripAccents() # Remove accents
])
# Input: "Héllo WORLD"
# After normalization: "hello world"
一般的な正規化器:
NFD、NFC、NFKD、NFKC- Unicode 正規化形式Lowercase()- 小文字に変換StripAccents()- アクセント記号を削除(é → e)Strip()- 空白を削除Replace(pattern, content)- 正規表現による置換
事前トークン化
テキストを単語らしい単位に分割します:
from tokenizers.pre_tokenizers import Whitespace, Punctuation, Sequence, ByteLevel
# Split on whitespace and punctuation
tokenizer.pre_tokenizer = Sequence([
Whitespace(),
Punctuation()
])
# Input: "Hello, world!"
# After pre-tokenization: ["Hello", ",", "world", "!"]
一般的な事前トークナイザー:
Whitespace()- スペース、タブ、改行で分割ByteLevel()- GPT-2 スタイルのバイトレベル分割Punctuation()- 句読点を分離Digits(individual_digits=True)- 数字を 1 桁ずつ分割Metaspace()- スペースを ▁ に置換(SentencePiece スタイル)
後処理
モデル入力用に特殊トークンを追加します:
from tokenizers.processors import TemplateProcessing
# BERT-style: [CLS] sentence [SEP]
tokenizer.post_processor = TemplateProcessing(
single="[CLS] $A [SEP]",
pair="[CLS] $A [SEP] $B [SEP]",
special_tokens=[
("[CLS]", 1),
("[SEP]", 2),
],
)
一般的なパターン:
# GPT-2: sentence <|endoftext|>
TemplateProcessing(
single="$A <|endoftext|>",
special_tokens=[("<|endoftext|>", 50256)]
)
# RoBERTa: <s> sentence </s>
TemplateProcessing(
single="<s> $A </s>",
pair="<s> $A </s> </s> $B </s>",
special_tokens=[("<s>", 0), ("</s>", 2)]
)
アライメントの追跡
元テキスト中のトークンの位置を追跡します:
output = tokenizer.encode("Hello, world!")
# Get token offsets
for token, offset in zip(output.tokens, output.offsets):
start, end = offset
print(f"{token:10} → [{start:2}, {end:2}): {text[start:end]!r}")
# Output:
# hello → [ 0, 5): 'Hello'
# , → [ 5, 6): ','
# world → [ 7, 12): 'world'
# ! → [12, 13): '!'
ユースケース:
- 固有表現認識(予測結果を元テキストに対応付ける)
- 質問応答(回答の範囲を抽出する)
- トークン分類(ラベルを元の位置に対応付ける)
transformers との統合
AutoTokenizer での読み込み
from transformers import AutoTokenizer
# AutoTokenizer automatically uses fast tokenizers
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Check if using fast tokenizer
print(tokenizer.is_fast) # True
# Access underlying tokenizers.Tokenizer
fast_tokenizer = tokenizer.backend_tokenizer
print(type(fast_tokenizer)) # <class 'tokenizers.Tokenizer'>
カスタムトークナイザーを transformers に変換
from tokenizers import Tokenizer
from transformers import PreTrainedTokenizerFast
# Train custom tokenizer
tokenizer = Tokenizer(BPE())
# ... train tokenizer ...
tokenizer.save("my-tokenizer.json")
# Wrap for transformers
transformers_tokenizer = PreTrainedTokenizerFast(
tokenizer_file="my-tokenizer.json",
unk_token="[UNK]",
pad_token="[PAD]",
cls_token="[CLS]",
sep_token="[SEP]",
mask_token="[MASK]"
)
# Use like any transformers tokenizer
outputs = transformers_tokenizer(
"Hello world",
padding=True,
truncation=True,
max_length=512,
return_tensors="pt"
)
よくあるパターン
イテレーターからの学習(大規模データセット)
from datasets import load_dataset
# Load dataset
dataset = load_dataset("wikitext", "wikitext-103-raw-v1", split="train")
# Create batch iterator
def batch_iterator(batch_size=1000):
for i in range(0, len(dataset), batch_size):
yield dataset[i:i + batch_size]["text"]
# Train tokenizer
tokenizer.train_from_iterator(
batch_iterator(),
trainer=trainer,
length=len(dataset) # For progress bar
)
パフォーマンス: 1GB を約 10〜20 分で処理
切り詰めとパディングの有効化
# Enable truncation
tokenizer.enable_truncation(max_length=512)
# Enable padding
tokenizer.enable_padding(
pad_id=tokenizer.token_to_id("[PAD]"),
pad_token="[PAD]",
length=512 # Fixed length, or None for batch max
)
# Encode with both
output = tokenizer.encode("This is a long sentence that will be truncated...")
print(len(output.ids)) # 512
マルチプロセッシング
from tokenizers import Tokenizer
from multiprocessing import Pool
# Load tokenizer
tokenizer = Tokenizer.from_file("tokenizer.json")
def encode_batch(texts):
return tokenizer.encode_batch(texts)
# Process large corpus in parallel
with Pool(8) as pool:
# Split corpus into chunks
chunk_size = 1000
chunks = [corpus[i:i+chunk_size] for i in range(0, len(corpus), chunk_size)]
# Encode in parallel
results = pool.map(encode_batch, chunks)
高速化: 8 コアで 5〜8 倍
パフォーマンスベンチマーク
学習速度
| コーパスサイズ | BPE(30k 語彙) | WordPiece(30k) | Unigram(8k) |
|---|---|---|---|
| 10 MB | 15 秒 | 18 秒 | 25 秒 |
| 100 MB | 1.5 分 | 2 分 | 4 分 |
| 1 GB | 15 分 | 20 分 | 40 分 |
ハードウェア: 16 コア CPU、英語版 Wikipedia でテスト
トークナイズ速度
| 実装 | 1 GB コーパス | スループット |
|---|---|---|
| 純粋な Python | 約 20 分 | 約 50 MB/分 |
| HF Tokenizers | 約 15 秒 | 約 4 GB/分 |
| 高速化率 | 80 倍 | 80 倍 |
テスト: 英語テキスト、平均文長 20 語
メモリ使用量
| タスク | メモリ |
|---|---|
| トークナイザーの読み込み | 約 10 MB |
| BPE の学習(30k 語彙) | 約 200 MB |
| 100 万文のエンコード | 約 500 MB |
対応モデル
from_pretrained() で利用できる事前学習済みトークナイザー:
BERT ファミリー:
bert-base-uncased,bert-large-caseddistilbert-base-uncasedroberta-base,roberta-large
GPT ファミリー:
gpt2,gpt2-medium,gpt2-largedistilgpt2
T5 ファミリー:
t5-small,t5-base,t5-largegoogle/flan-t5-xxl
その他:
facebook/bart-base,facebook/mbart-large-cc25albert-base-v2,albert-xlarge-v2xlm-roberta-base,xlm-roberta-large
すべてを閲覧: https://huggingface.co/models?library=tokenizers
参考資料
- 学習ガイド - カスタムトークナイザーの学習、トレーナーの設定、大規模データセットの扱い
- アルゴリズム詳解 - BPE、WordPiece、Unigram を詳しく解説
- パイプラインコンポーネント - 正規化器、プリトークナイザー、ポストプロセッサー、デコーダー
- Transformers 連携 - AutoTokenizer、PreTrainedTokenizerFast、特殊トークン
リソース
- ドキュメント: https://huggingface.co/docs/tokenizers
- GitHub: https://github.com/huggingface/tokenizers ⭐ 9,000+
- バージョン: 0.20.0+
- コース: https://huggingface.co/learn/nlp-course/chapter6/1
- 論文: BPE(Sennrich et al., 2016)、WordPiece(Schuster & Nakajima, 2012)