فاز 5 · درس 19

توکن‌سازی زیرکلمه: راهنمای جامع BPE، WordPiece، Unigram و SentencePiece

نوع
مفهومی
زمان
حدود 60 دقیقه
زبان‌ها
Python
پیش‌نیاز
فاز 5 · بخش 01 (پردازش متن)، فاز 5 · بخش 04 (مدل‌های GloVe / FastText / Subword)
بلوک‌های ساختمانی چوبی در ابعاد گوناگون که بخش‌های مختلف یک ساختار یکپارچه را کنار هم شکل داده‌اند
فهرست مطالب
  1. صورت مسئله
  2. مفهوم پایه
  3. پیاده‌سازی
  4. گام 1: پیاده‌سازی BPE از صفر
  5. گام 2: کدگذاری با قوانین merge آموخته‌شده
  6. گام 3: پیاده‌سازی عملی با SentencePiece
  7. گام 4: استفاده از tiktoken برای واژگان سازگار با OpenAI
  8. دام‌هایی که در سال 2026 هنوز به پروداکشن راه پیدا می‌کنند
  9. استفاده‌ی عملی
  10. تحویل خروجی
  11. تمرین‌ها
  12. اصطلاحات کلیدی
  13. برای مطالعه‌ی بیشتر

اگر در پردازش متن با مدل‌های زبانی با مشکل کلمات ناشناخته (توکن‌های [UNK]) روبه‌رو شده باشید یا شکستن متون به سطح کاراکتر طول توالی‌های پردازشی‌تان را به شکل سرسام‌آوری افزایش داده باشد، توکن‌سازی زیرکلمه (Subword Tokenization) راه‌حل کلیدی این چالش است. این الگوریتم‌ها با شکستن واژگان نادر به قطعات معنادار و حفظ کلمات پرتکرار در قالب یک توکن واحد، ستون فقرات تمامی مدل‌های زبانی امروزی از جمله سری GPT، Llama و Gemma را شکل می‌دهند.

در زبان‌هایی مانند فارسی که وندهای صرفی پرتکرار و ساختارهای پیوندی متعدد دارند، آشنایی عمیق با نحوه‌ی قطعه‌بندی واژگان و تفاوت الگوریتم‌هایی چون BPE، WordPiece و Unigram اهمیتی دوچندان دارد. توکن‌سازهای نامناسب می‌توانند یک کلمه‌ی معمولی فارسی را به چندین توکن بشکنند که نتیجه‌ی مستقیم آن مصرف بی‌رویه‌ی ظرفیت پنجره‌ی زمینه (Context Window) و افزایش هزینه‌های استنتاج خواهد بود.

در این درس پیاده‌سازی BPE از صفر، نحوه‌ی آموزش واژگان به کمک SentencePiece و استفاده از ابزارهای فوق‌سریع مثل tiktoken و HF Tokenizers را بررسی می‌کنیم تا بتوانید متناسب با کاربرد مدل و منابع محاسباتی خود بهترین ابزار را انتخاب کنید.

توکن‌سازهای کلمه‌ای در مواجهه با کلمات ندیده به بن‌بست می‌خورند. توکن‌سازهای کاراکتری طول توالی را بیش از حد بالا می‌برند. توکن‌سازهای زیرکلمه (Subword) راه‌حلی میانه‌ی این دو ارائه می‌دهند و تمام مدل‌های زبانی بزرگ مدرن بر پایه‌ی یکی از آن‌ها عرضه می‌شوند.

صورت مسئله

واژگان شما 50,000 کلمه دارد. کاربر واژه‌ی «untokenizable» را تایپ می‌کند. توکن‌ساز شما توکن [UNK] را برمی‌گرداند. اکنون مدل هیچ نشانه‌ای از این کلمه دریافت نمی‌کند. بدتر اینکه در صدک 90 اسناد مجموعه‌داده‌تان، 40 کلمه‌ی نادر وجود دارد؛ یعنی به ازای هر سند، 40 بیت اطلاعاتِ ازدست‌رفته.

توکن‌سازی زیرکلمه این مشکل را حل می‌کند. کلمات پرتکرار در قالب یک توکن واحد باقی می‌مانند، در حالی که کلمات نادر به تکه‌های معنادار تجزیه می‌شوند: untokenizable به un، token و izable خرد می‌شود. داده‌های آموزشی همه‌چیز را پوشش می‌دهند، زیرا هر رشته‌ای در نهایت توالی‌ای از بایت‌هاست.

تمامی مدل‌های بزرگ پیشرو در سال 2026 بر پایه‌ی یکی از سه الگوریتم اصلی (BPE، Unigram یا WordPiece) و درون یکی از سه کتابخانه‌ی مطرح (HF Tokenizers ،SentencePiece یا tiktoken) عرضه می‌شوند. برای ارائه‌ی یک مدل زبانی چاره‌ای ندارید جز اینکه یکی از این روش‌ها را انتخاب کنید.

مفهوم پایه

BPE در برابر Unigram و WordPiece، کاراکتر به کاراکتر

الگوریتم BPE (رمزگذاری جفت‌بایت / Byte-Pair Encoding): کار را با واژگانی در سطح کاراکتر شروع کنید. تعداد تکرار هر جفتِ مجاور را بشمارید. پرتکرارترین جفت را در یک توکن جدید merge کنید. این فرایند را تکرار کنید تا به حجم واژگان هدف برسید. این الگوریتم، روش غالب در GPT-2/3/4، Llama، Gemma، Qwen2 و Mistral است.

الگوریتم Byte-level BPE: همان الگوریتم است، اما به جای کاراکترهای یونیکد، مستقیماً روی بایت‌های خام (256 توکن پایه) اجرا می‌شود. این رویکرد صفر بودن توکن‌های [UNK] را تضمین می‌کند؛ چرا که هر توالی از بایت‌ها قابل رمزگذاری است. مدل GPT-2 از 50,257 توکن استفاده می‌کند (شامل 256 بایت خام، 50,000 عملیات merge و 1 توکن ویژه).

الگوریتم Unigram: کار را با مجموعه‌ای بسیار بزرگ از توکن‌ها شروع کنید. به هر توکن، یک احتمال یونی‌گرام اختصاص دهید. توکن‌هایی را که حذفشان کمترین افزایش را در درست‌نمایی لگاریتمی (log-likelihood) داده‌ها ایجاد می‌کند، به‌صورت مکرر هرس کنید. این روش در زمان استنتاج به‌صورت احتمالات عمل می‌کند و می‌تواند توکن‌سازی‌های متفاوتی را نمونه‌برداری کند (ویژگی بسیار مفیدی برای غنی‌سازی داده‌ها از طریق منظم‌سازی زیرکلمه‌ای). مدل‌های T5، mBART، ALBERT، XLNet و Gemma از این الگوریتم بهره می‌برند.

الگوریتم WordPiece: به جای بسامد خام، جفت‌هایی را merge می‌کند که درست‌نمایی مجموعه‌داده‌ی آموزشی را به حداکثر می‌رسانند. این روش در BERT، DistilBERT و ELECTRA به کار رفته است.

تفاوت SentencePiece و tiktoken: کتابخانه‌ی SentencePiece برای آموزش واژگان (BPE یا Unigram) مستقیماً روی متن خام یونیکد طراحی شده و فاصله‌ها را با نماد ▁ کدگذاری می‌کند. در مقابل، tiktoken صرفاً یک کدگذار بسیار سریع متعلق به OpenAI برای واژگانِ ازپیش‌ساخته است و کار آموزش واژگان را انجام نمی‌دهد.

قاعده‌ی سرانگشتی:

  • آموزش واژگان جدید: SentencePiece (برای پشتیبانی چندزبانه، بدون نیاز به پیش‌توکن‌سازی) یا HF Tokenizers.
  • استنتاج سریع بر پایه‌ی واژگان GPT: کتابخانه‌ی tiktoken (با واژگان cl100k_base یا o200k_base).
  • هر دو مورد با هم: HF Tokenizers — یک کتابخانه، هم برای آموزش و هم سرویس‌دهی.
BPE MERGEگام‌به‌گام با mergeها
کدگذاری جفت‌بایت (BPE) از نویسه‌ها شروع می‌کند و به‌طور مکرر پرتکرارترین جفت مجاور را در یک نماد جدید merge می‌کند. هر merge یک ورودی به دایره واژگان می‌افزاید و پیکره متنی را کوتاه‌تر می‌سازد. توالی‌های متداول مثل «es» و «est» به توکن‌های تکی تبدیل می‌شوند، بنابراین متن‌های پرتکرار در توکن‌های کمتری فشرده می‌شوند، درحالی‌که کلمات نادر همچنان به اجزای کوچک‌تر شکسته می‌شوند.

پیاده‌سازی

گام 1: پیاده‌سازی BPE از صفر

کد مربوطه را در فایل code/main.py ببینید. حلقه‌ی اصلی:

def train_bpe(corpus, num_merges):
    vocab = {tuple(word) + ("</w>",): count for word, count in corpus.items()}
    merges = []
    for _ in range(num_merges):
        pairs = Counter()
        for symbols, freq in vocab.items():
            for a, b in zip(symbols, symbols[1:]):
                pairs[(a, b)] += freq
        if not pairs:
            break
        best = pairs.most_common(1)[0][0]
        merges.append(best)
        vocab = apply_merge(vocab, best)
    return merges

سه واقعیتی که این الگوریتم کدگذاری می‌کند: نشانه‌ی </w> پایان کلمه را مشخص می‌کند تا میان پسوند «low» و پیشوند در «lower» تمایز ایجاد شود. وزن‌دهی بر اساس بسامد باعث می‌شود جفت‌های پرتکرار زودتر برنده شوند. همچنین فهرست mergeها دارای ترتیب است؛ بنابراین در فاز استنتاج، mergeها به همان ترتیبی اعمال می‌شوند که آموزش دیده‌اند.

گام 2: کدگذاری با قوانین merge آموخته‌شده

def encode_bpe(word, merges):
    symbols = list(word) + ["</w>"]
    for a, b in merges:
        i = 0
        while i < len(symbols) - 1:
            if symbols[i] == a and symbols[i + 1] == b:
                symbols = symbols[:i] + [a + b] + symbols[i + 2:]
            else:
                i += 1
    return symbols

پیاده‌سازی ابتدایی با پیچیدگی زمانی O(n⋅∣merges∣)O(n \cdot \lvert \text{merges} \rvert). در محیط‌های پروداکشن (نظیر tiktoken و HF Tokenizers) از جست‌وجوی رتبه-merge با صف‌های اولویت‌دار استفاده می‌شود و زمان اجرا تقریباً خطی است.

گام 3: پیاده‌سازی عملی با SentencePiece

import sentencepiece as spm

spm.SentencePieceTrainer.train(
    input="corpus.txt",
    model_prefix="my_tokenizer",
    vocab_size=8000,
    model_type="bpe",          # or "unigram"
    character_coverage=0.9995, # lower for CJK (e.g. 0.9995 for English, 0.995 for Japanese)
    normalization_rule_name="nmt_nfkc",
)

sp = spm.SentencePieceProcessor(model_file="my_tokenizer.model")
print(sp.encode("untokenizable", out_type=str))
# ['▁un', 'token', 'izable']

نکات کلیدی: نیازی به پیش‌توکن‌سازی نیست؛ فاصله به شکل ▁ کدگذاری می‌شود؛ و پارامتر character_coverage میزان حفظ کاراکترهای نادر را در مقایسه با نگاشت شدن به <unk> تعیین می‌کند.

گام 4: استفاده از tiktoken برای واژگان سازگار با OpenAI

import tiktoken
enc = tiktoken.get_encoding("o200k_base")
print(enc.encode("untokenizable"))        # [127340, 101028]
print(len(enc.encode("Hello, world!")))   # 4

صرفاً برای کدگذاری است. سرعت فوق‌العاده‌ای دارد (با هسته‌ی Rust) و خروجی توکن‌سازی آن برای شمارش بایت، تخمین هزینه‌ها و بودجه‌بندی پنجره‌ی زمینه (Context window) با GPT-4 و GPT-5 کاملاً همخوان است.

دام‌هایی که در سال 2026 هنوز به پروداکشن راه پیدا می‌کنند

  • تغییر توکن‌ساز (Tokenizer drift): آموزش روی واژگان A و استقرار با واژگان B. شناسه‌ی توکن‌ها مغایرت پیدا می‌کند و خروجی مدل بی‌معنی می‌شود. حتماً هش فایل tokenizer.json را در CI بررسی کنید.
  • ابهام در فاصله‌ها: در الگوریتم BPE، رشته‌های "hello" و " hello" توکن‌های متفاوتی تولید می‌کنند. همواره add_special_tokens و add_prefix_space را صریح مشخص کنید.
  • آموزش ناکافی در چندزبانگی: مجموعه‌داده‌های عمدتاً انگلیسی واژگانی تولید می‌کنند که خط‌های غیرلاتین را به 5 تا 10 برابر توکن بیشتری خرد می‌کنند. همان پرامپت در GPT-3.5 برای زبان‌های ژاپنی یا عربی 5 تا 10 برابر گران‌تر تمام می‌شود. واژگان o200k_base تا حدی این مشکل را حل کرد.
  • تکه‌تکه شدن ایموجی‌ها: یک ایموجی ممکن است تا 5 توکن فضا بگیرد. هنگام بودجه‌بندی زمینه، چک‌پوینتِ نحوه‌ی رفتار با ایموجی‌ها را بررسی کنید.

استفاده‌ی عملی

پشته‌ی ابزارهای سال 2026:

شرایط انتخاب
آموزش یک مدل تک‌زبانه از صفر HF Tokenizers (الگوریتم BPE)
آموزش یک مدل چندزبانه SentencePiece (الگوریتم Unigram با character_coverage=0.9995)
سرویس‌دهی API سازگار با OpenAI tiktoken (واژگان o200k_base برای GPT-4 به بالا)
واژگان تخصصی یک دامنه (کدنویسی، ریاضی، پروتئین) آموزش BPE سفارشی روی داده‌های دامنه و سپس merge با واژگان پایه
استنتاج روی Edge، مدل کوچک Unigram (واژگان کوچک‌تر عملکرد بهتری دارند)

اندازه‌ی واژگان یک تصمیم مرتبط با مقیاس است، نه یک عدد ثابت. تخمین سرانگشتی: 32k برای مدل‌های کمتر از 1 میلیارد پارامتر، 50 تا 100k برای مدل‌های 1 تا 10 میلیارد، و بیش از 200k برای مدل‌های چندزبانه یا مرزی.

تحویل خروجی

محتوا را با عنوان outputs/skill-bpe-vs-wordpiece.md ذخیره کنید:

---
name: tokenizer-picker
description: Pick tokenizer algorithm, vocab size, library for a given corpus and deployment target.
version: 1.0.0
phase: 5
lesson: 19
tags: [nlp, tokenization]
---

Given a corpus (size, languages, domain) and deployment target (training from scratch / fine-tuning / API-compatible inference), output:

1. Algorithm. BPE, Unigram, or WordPiece. One-sentence reason.
2. Library. SentencePiece, HF Tokenizers, or tiktoken. Reason.
3. Vocab size. Rounded to nearest 1k. Reason tied to model size and language coverage.
4. Coverage settings. `character_coverage`, `byte_fallback`, special-token list.
5. Validation plan. Average tokens-per-word on held-out set, OOV rate, compression ratio, round-trip decode equality.

Refuse to train a character-coverage <0.995 tokenizer on corpora with rare-script content. Refuse to ship a vocab without a frozen `tokenizer.json` hash check in CI. Flag any monolingual tokenizer under 16k vocab as likely under-spec.

تمرین‌ها

  1. ساده. روی مجموعه‌داده‌ی کوچک داخل code/main.py یک توکن‌ساز BPE با 500 مرحله‌ی merge آموزش دهید. سه کلمه‌ی جدید (دیده نشده در آموزش) را کدگذاری کنید. چند مورد دقیقاً 1 توکن و چند مورد بیش از 1 توکن تولید کردند؟
  2. متوسط. تعداد توکن‌های 100 جمله‌ی ویکی‌پدیای انگلیسی را بین cl100k_base، o200k_base و یک BPE که خودتان با SentencePiece و vocab=32k آموزش داده‌اید مقایسه کنید. نسبت فشرده‌سازی هر کدام را گزارش دهید.
  3. سخت. همان مجموعه‌داده را با سه روش BPE، Unigram و WordPiece آموزش دهید. با استفاده از هر توکن‌ساز روی یک دسته‌بند کوچک تحلیل احساسات، دقت نهایی را بسنجید. آیا انتخاب توکن‌ساز می‌تواند امتیاز F1 را بیش از 1 واحد جابه‌جا کند؟

اصطلاحات کلیدی

اصطلاح در گفتار عامه معنای دقیق فنی
BPE رمزگذاری جفت‌بایت merge حریصانه‌ی پرتکرارترین جفت کاراکترها تا زمان رسیدن به حجم واژگان مورد نظر.
Byte-level BPE نبود هیچ توکن ناشناخته BPE روی 256 بایت خام؛ روش به‌کاررفته در GPT-2 و Llama.
Unigram توکن‌ساز احتمالات هرس کردن از میان مجموعه‌ای بزرگ از کاندیداها با استفاده از درست‌نمایی لگاریتمی؛ به‌کاررفته در T5 و Gemma.
SentencePiece همانی که فاصله‌ها را تغییر می‌دهد کتابخانه‌ای که BPE و Unigram را مستقیماً روی متن خام آموزش می‌دهد؛ فاصله را به شکل ▁ کدگذاری می‌کند.
tiktoken ابزار سریع کدگذار BPE از سوی OpenAI بر پایه‌ی Rust برای واژگان ازپیش‌ساخته؛ بدون بخش آموزش.
Merge list اعداد جادویی فهرست مرتب‌شده‌ی mergeهای (a, b) → ab؛ در استنتاج دقیقاً به ترتیب اعمال می‌شوند.
Character coverage چقدر نادر زیادی نادر است؟ نسبتی از کاراکترهای داده‌های آموزش که توکن‌ساز باید پوشش دهد؛ معمولاً حدود 0.9995.

برای مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درستوکن‌سازی زیرکلمه‌ای (subword) چه مزیتی نسبت به واژگان سطح کلمه دارد؟
  2. پیش از درسچرا GPT-2 به‌جای BPE در سطح نویسه از BPE در سطح بایت استفاده می‌کند؟
  3. حین درستوکن‌ساز Unigram چگونه دایره واژگان خود را می‌سازد؟
  4. حین درسچه چیزی معیار merge در WordPiece را از BPE متمایز می‌کند؟
  5. حین درسکدام ابزار، توکن‌ساز را مستقیماً روی متن چندزبانه و خام یونیکد آموزش می‌دهد؟
  6. پس از درسچرا فرایند CI در محیط پروداکشن باید هشِ فایل tokenizer.json مستقرشده را بررسی کند؟
  7. پس از درسدلیل متداول این‌که یک ایموجی منفرد توکن‌های متعددی مصرف می‌کند چیست؟
  8. پس از درسچه روش تجربی برای تعیین اندازه واژگان یک ترنسفورمر تک‌زبانه جدید به کار می‌رود؟

سؤالات متداول

تفاوت اصلی الگوریتم‌های BPE و WordPiece در چیست؟

الگوریتم BPE جفت‌کاراکترها یا بایت‌های مجاور را صرفاً بر اساس فراوانی تکرار ادغام می‌کند، در حالی که WordPiece جفت‌هایی را ادغام می‌کند که درست‌نمایی (Likelihood) داده‌های آموزشی را به حداکثر برسانند.

تفاوت کاربرد SentencePiece و tiktoken چیست؟

کتابخانه‌ی SentencePiece برای آموزش واژگان جدید (BPE یا Unigram) مستقیماً روی متن خام استفاده می‌شود، در حالی که tiktoken صرفاً یک کدگذار فوق‌سریع برای کار با واژگانِ ازپیش‌آموزش‌دیده‌ی مدل‌های OpenAI است و قابلیت آموزش ندارد.

چرا Byte-level BPE هرگز خطای کلمه‌ی ناشناخته ([UNK]) تولید نمی‌کند؟

چون این الگوریتم کار را به جای کاراکترهای یونیکد با 256 بایت خام پایه آغاز می‌کند؛ بنابراین هر متنی در قالب توالی بایت‌ها قابل نمایش و کدگذاری خواهد بود.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.