出版日: 2025年7月5日
バイトペアエンコーディング(BPE)は、GPTやBERTなどの現代の言語モデルを支えるサブワードトークン化アルゴリズムです。元々はデータ圧縮用に設計されましたが、現在はNLPに欠かせない技術となっています。
アルゴリズムはシンプルです:個別の文字から始めて、最も頻度の高い隣接ペアを反復的にマージし、目標の語彙サイズに達するまで続けます。これにより文字レベルの粒度と単語レベルの意味論のバランスが取れます。
従来のトークン化手法には大きな制限があります:
特に日本語では、BPEは一般的な漢字の組み合わせ、助詞、文法パターンを明示的な言語知識なしに自動的に学習できるため、特に価値があります。
日本語テキストでBPEがどのように段階的に動作するかを見てみましょう:
ステップ 0 / 5
ライブドアニュースコーパスを使用しました。日本語ニュース記事を含み、トークナイザーの学習に最適です:
# 日本語ニュースコーパスのダウンロードと読み込み
import tarfile
import urllib.request
import os
filename = "ldcc-20140209.tar.gz"
if not os.path.exists(filename):
print("ダウンロード中...")
urllib.request.urlretrieve("https://www.rondhuit.com/download/ldcc-20140209.tar.gz", filename)
text = ""
articles = []
article_count_limit = 1000
with tarfile.open(filename, "r") as tar:
for member in tar.getmembers():
if member.isfile() and member.name.endswith(".txt"):
file_content = tar.extractfile(member).read().decode("utf-8")
lines = file_content.split("\n")
if len(lines) >= 4: # URL、日付、タイトルをスキップ
content = "\n".join(lines[3:]).strip()
if content:
articles.append(content)
text += content + "\n\n"
print(f"テキスト長: {len(text):,}")
print(f"記事数: {len(articles):,}")
print(f"初期語彙サイズ: {len(set(text)):,}")
BPEアルゴリズムは2つの主要な関数で構成されます:頻度の高いペアの発見とマージ:
def get_pairs(tokens):
"""隣接する文字ペアとその頻度を見つける"""
pairs = defaultdict(int)
for i in range(len(tokens) - 1):
pairs[(tokens[i], tokens[i + 1])] += 1
return pairs
def merge_tokens(tokens, pair):
"""最も頻度の高いペアを単一のトークンにマージ"""
new_tokens = []
i = 0
while i < len(tokens):
if (i < len(tokens) - 1 and
tokens[i] == pair[0] and tokens[i + 1] == pair[1]):
new_tokens.append(pair[0] + pair[1]) # ペアをマージ
i += 2
else:
new_tokens.append(tokens[i])
i += 1
return new_tokens
個別の文字から始めて、最も頻度の高いペアを反復的にマージします:
# 文字レベルのトークンで初期化
tokens = list(text) # 個別の文字に分割
vocab = set(tokens)
target_vocab_size = 5000
while len(vocab) < target_vocab_size:
# 最も頻度の高い隣接ペアを見つける
pairs = get_pairs(tokens)
if not pairs:
break
best_pair = max(pairs, key=pairs.get)
# このペアのすべてのインスタンスをマージ
tokens = merge_tokens(tokens, best_pair)
vocab.add("".join(best_pair))
if merge_count % 100 == 0:
print(f"マージ {merge_count}: 語彙 {len(vocab)}, トークン {len(tokens)}")
マージ# | マージされたペア | 新しいトークン | 頻度 |
---|---|---|---|
1 | 最 + 近 | 最近 | 847 |
2 | T + V | TV | 523 |
3 | で + も | でも | 412 |
4 | 人 + 気 | 人気 | 389 |
5 | 者 + の | 者の | 301 |
学習後、BPE語彙を適用して新しいテキストをトークン化できます:
def tokenize_with_bpe(text):
"""学習したBPEマージを新しいテキストに適用"""
tokens = list(text) # 文字から開始
changed = True
while changed:
changed = False
new_tokens = []
i = 0
while i < len(tokens):
# 隣接ペアが語彙に存在するかチェック
if (i < len(tokens) - 1 and
tokens[i] + tokens[i + 1] in vocab):
new_tokens.append(tokens[i] + tokens[i + 1])
i += 2
changed = True
else:
new_tokens.append(tokens[i])
i += 1
tokens = new_tokens
return tokens
結果は日本語テキストに対するBPEの効果を示しています:
# 学習結果:
テキスト長: 659,423
記事数: 1,000
初期語彙サイズ: 2,913
BPE後語彙サイズ: 5,000
# 圧縮結果:
元の文字数: 659,423
BPEトークン: 379,352
圧縮率: 42.5%
659,423
文字
379,352
BPEトークン
42.5%
削減
学習したBPEモデルで日本語の文がどのようにトークン化されるかの例:
元のテキスト: 最近TVでも人気者のお笑いコンビ「しずる」のメンバーで...
BPEトークン:
BPEが言語学的前処理なしに「最近」(最近)、「人気」(人気)、「者の」(〜の人)などの意味のあるサブワード単位を自動的に学習していることに注目してください!
日本語はトークン化にユニークな課題を提示します:
完全な実装はGitHubでインタラクティブなJupyterノートブックとして利用できます。以下ができます:
BPEは文字レベルの堅牢性と単語レベルの意味論の完璧なバランスを実現します。シンプルから始めてデータ駆動型マージにより複雑性を構築し、コンパクトかつ意味のある語彙を作成します。
特に日本語テキストでは、BPEが言語パターンを自動的に発見する能力により、現代のNLPアプリケーションに理想的な選択となります。意味的意味を維持しながら達成した42.5%の圧縮がその効果を実証しています。
言語モデル、機械翻訳システム、テキスト分析ツールを構築する場合、BPEの理解と実装は、あらゆる言語、特に日本語などの形態論的に豊富な言語で作業する際に不可欠です。
このブログは英語からLLMによって翻訳されました。不明な点がある場合は、お問い合わせページからご連絡ください。
コメントを残す
コメント
現在コメントがありません。
その他のブログ
2025/07/07
Q学習:インタラクティブ強化学習の基礎
2025/07/06
最適化アルゴリズム:SGD、モメンタム、Adam
2024/06/19
SvelteとJavaScriptを使用してシンプルで動的なツールチップを作成する
2024/06/17
JavaScriptを用いて東京都のインタラクティブな地図を作成する
2024/06/14
Matplotlibで日本語文字化けを解決できる簡単な方法
2024/06/13
書評 | トーキング・トゥ・ストレンジャーズ 「よく知らない人」について私たちが知っておくべきこと by マルコム・グラッドウェル
2024/06/07
日本語で最もよく使われる3000字の漢字
2024/06/07
VSCodeでRegexを使用してReplaceする方法
2024/06/06
SvelteではReadable Storeを使用するな
2024/06/05
GzipとPakoでデータを圧縮してWebサイトのローディング速度を上げる方法
2024/05/31
JavaScriptを使用してWebページ上でマウスが指している単語を特定する
2024/05/29
SvelteとSVGを用いてインタラクティブな地図を作成する
2024/05/28
書評 | Originals 誰もが「人と違うこと」ができる時代 by アダム・グラント & シェリル・サンドバーグ
2024/05/27
Javascriptを使用して数独を解く方法
2024/05/26
ウェブサイトへのトラフィックを1か月で10倍に増やした方法
2024/05/24
人生はサイクリングに似ている
2024/05/19
JavaScriptでバックトラッキング・アルゴリズムを用いて完全な数独グリッドを生成する
2024/05/16
Tailwindが素晴らしい理由とWeb開発をいかに楽にするか
2024/05/15
PythonとGitフックを使用してサイトマップを自動的に生成する
2024/05/14
書評 | Range (レンジ) 知識の「幅」が最強の武器になる by デイビッド・エプスタイン
2024/05/13
SvelteとSvelteKitはなんですか?
2024/05/12
SvelteKitで国際化(多言語化)
2024/05/11
SvelteでCachingを用いてDeploy時間を短縮する方法
2024/05/10
SvelteとIntersection Oberverによるレイジーローディング
2024/05/10
遺伝的アルゴリズムで最適な株式ポートフォリオを作る方法
2024/05/09
Pythonを用いてShapeFileをSVGに変換できる方法
2024/05/08
Svelteの反応性:変数、バインディング、およびキー関数
2024/05/07
書評 | 孫子の兵法
2024/05/06
スペシャリストは終了。ゼネラリスト万歳!
2024/05/03
トルコ人の有権者の投票行動をPythonでの分析
2024/05/01
Seleniumを用いてトルコ投票データベースを作る方法
2024/04/30
SvelteとTailwindを使用してInfinite Scrollできる方法
2024/04/29
1年間以内で日本語を駆使できるようになるための方法
2024/04/25
SvelteとTailwindを用いたWebサイトテンプレート
2024/01/29
怠惰なエンジニアとひどいデザイン
2024/01/28
偉大さについて
2024/01/28
MacBook で PDF を PNG に変換する
2023/12/31
2023年振り返り:24冊の読んだ本のまとめ
2023/12/30
Python PILを使用して写真コラージュを作成する方法
2024/01/09
ウェブサイトの訪問者のデバイスとブラウザを検出する方法
2024/01/19
ChatGPT回答の解析