İçeriğe geç

WordPiece (BERT): Likelihood-Based Merges ve BPE'den Sessiz Farklılıklar

WordPiece algoritması: Schuster & Nakajima 2012'den BERT 2018'e yolculuk. Frequency yerine likelihood-based merge skoru, ##suffix prefix konvansiyonu, [UNK]/[CLS]/[SEP] special tokens, BPE'den sessiz ama kritik farklılıklar. HuggingFace Tokenizers ile pratik training, BERT-base-Turkish-cased örneği, vocab tasarımı.

Şükrü Yusuf KAYA
55 dakikalık okuma
Orta
WordPiece (BERT): Likelihood-Based Merges ve BPE'den Sessiz Farklılıklar
🧬 BPE'nin sessiz rakibi — likelihood baskısı
WordPiece, BPE ile aynı problemi farklı bir matematik lensiyle çözer. Sennrich 2016'dan 4 yıl önce Schuster & Nakajima 2012'de Japonca/Korece ses arama için doğdu, BERT 2018'de patladı. Yüzeyde benzer ama merge kriteri likelihood-based. Bu fark BERT'in neden Türkçe morfolojide BPE'den çoğu zaman daha iyi bölünmeler ürettiğini açıklıyor. 55 dakika sonra: WordPiece'i sıfırdan implement edebilecek, BERT-base-Turkish-cased vocab'ını okuyabilecek, üretim sisteminde WordPiece vs BPE doğru kararı verebileceksin.

Ders Haritası#

  1. Tarih: Schuster & Nakajima 2012 — Japanese/Korean voice search
  2. Algoritmanın özü: frequency değil likelihood
  3. Merge skoru matematiği:
    score(A,B) = P(AB) / (P(A) · P(B))
  4. ##suffix konvansiyonu — niye var, ne anlama gelir
  5. Training pseudocode: BPE'den ayrılan 3 satır
  6. Encoding (greedy longest-match) — BPE'den daha hızlı inference
  7. Special tokens: [UNK], [CLS], [SEP], [PAD], [MASK]
  8. BERT-base-Turkish-cased vocab incelemesi
  9. HuggingFace Tokenizers ile WordPiece training
  10. WordPiece vs BPE — pratik karar matrisi
  11. Edge cases: unknown chars, byte fallback eksikliği
  12. Egzersizler + summary + FAQ

1. Tarih: 2012'den 2018'e Sessiz Rakip#

2012 — Schuster & Nakajima (Google Tokyo)#

"Japanese and Korean Voice Search" — ICASSP 2012. Problem: Japonca/Korece için n-gram language model'i fonetik input'a bağlayan voice search sistemi. Vocabulary problem: Japoncada 無限 sözcük (kanji + hiragana + katakana kombinasyonları), n-gram explosion.
Çözüm: Subword unit'leri likelihood-based bir kriter ile birleştir. Adı: WordPiece.

2016 — Sennrich BPE#

WordPiece'ten 4 yıl sonra. Sennrich BPE'yi MT için kullandı, daha basit (frequency-based) ve patent-free. NLP community'de yaygınlaştı.

2018 — BERT patlaması#

Devlin et al. 2018 (Google AI) BERT için WordPiece kullandı. Niye:
  • Google internal tradition: 2012'den beri Google içinde kullanılıyor (Translate, voice).
  • Likelihood-based: BERT'in MLM (Masked Language Modeling) objective'i ile felsefik uyum.
  • Suffix marker (##): kelime sınırını korur, MLM için kritik.

2019+ — RoBERTa BPE'ye geçti#

Facebook RoBERTa BPE'yi tercih etti (byte-level). Sebep: multilingual, byte fallback. Bu, WordPiece'in çağdaş düşüşünün başlangıcı.

Bugün (2026)#

  • WordPiece: BERT, DistilBERT, ELECTRA, MobileBERT, ALBERT — encoder mimarileri.
  • BPE (byte-level): GPT-2/3/4, RoBERTa, Llama (sentencepiece BPE mode), Mistral.
  • Unigram LM: T5, mT5, Llama-3, XLNet — modern multilingual seçimi.

Tarihsel ironi#

WordPiece BPE'den önce vardı ama BPE daha basit olduğu için ezberlendi. Yine de BERT ekosistemi WordPiece'i hâlâ yaşatıyor — BERT-base hâlâ NLP'nin en çok kullanılan modellerinden biri (HuggingFace Hub: 100M+ download).

2. WordPiece'in Özü: Likelihood, Frequency Değil#

BPE'nin kriteri#

merge_score_BPE(A, B) = count(AB)
"En sık geçen pair'i birleştir."

WordPiece'in kriteri#

merge_score_WP(A, B) = count(AB) / (count(A) · count(B))
"Birlikteliğin beklenenden ne kadar yüksek olduğunu birleştir."

Mutual Information (Karşılıklı Bilgi) bağlantısı#

Bu skor aslında pointwise mutual information (PMI)'ye yakın:
PMI(A, B) = log( P(A,B) / (P(A) · P(B)) )
WordPiece score'u logsuz versiyon. Beraber görülme olasılığı bağımsız olasılıkların çarpımından ne kadar sapıyor?

Sezgisel anlam#

  • Yüksek count(AB) ama yüksek count(A) ve count(B) → trivial co-occurrence → düşük skor → merge etme. Örnek: "th" + "e" — "the" çok sık ama "th" ve "e" da çok sık, score düşük.
  • Yüksek count(AB) ama düşük count(A) veya count(B) → güçlü birliktelik → yüksek skor → merge et. Örnek: "iz" + "ler" Türkçede güçlü morfolojik bağ.

Sonuç: morfolojiyi BPE'den daha doğru yakalar#

BPE en sık pair'i alır ki bu fonksiyon kelimelerine ("the", "of", "ve") öncelik verir. WordPiece istatistiksel anlamlı birleşmeleri tercih eder — morfolojik unit'lere daha yakın.
Türkçe örnek: "kitaplarım" = kitap + lar + ım. BPE rastgele "kit", "ap", "lar", "ım" gibi parçalayabilir. WordPiece "kitap" + "##lar" + "##ım" daha sık. Niye: Türkçede "lar" çok sık morfeme ama "k" + "it" gibi rastgele kombinasyonlar ortak değil.

3. Skor Formülünün Türetilmesi#

Likelihood maximization#

WordPiece'in resmi formülasyonu (Schuster & Nakajima 2012):
"Her merge adımında, language model likelihood'unu en çok artıran pair'i seç."

Unigram language model varsayımı#

Vocabulary'deki her token bağımsız olasılıkla:
P(corpus) = ∏ over tokens t: P(t)^count(t) log P(corpus) = Σ count(t) · log P(t)

Bir merge'in likelihood etkisi#

Pair (A, B) birleşirken:
  • count(AB) kez AB token'ı ortaya çıkar
  • count(AB) kez A ve B ayrı ayrı silinir
Δ log L = count(AB) · log P(AB) - count(AB) · log P(A) - count(AB) · log P(B) = count(AB) · log [ P(AB) / (P(A) · P(B)) ]

Pratik approximation#

Maksimum likelihood için maksimize edilecek miktar:
score = P(AB) / (P(A) · P(B)) = count(AB) / (count(A) · count(B))
(N normalizer'ı her pair için aynı olduğu için iptal olur.)

Sayısal örnek#

Corpus: 1M token. count("the")=50000, count("##e")=200000, count("th")=10000, count("the_full")=45000.
score(th, e for joining as "the") = 45000 / (10000 · 200000) = 0.0000225 score(the, _) ...
BPE skoru = 45000 (büyük), WordPiece skoru = 0.0000225 (relative, başka pair'lerle karşılaştırılır). Önemli olan ranking, mutlak değer değil.

Niye bu daha iyi morfoloji#

Türkçe corpus'ta:
  • count("lar") = 2M (suffix, çok sık)
  • count("kitap") = 50K
  • count("kitap" + "lar") = 8K
BPE skoru "the"+"the suffix" pair'inden düşük olabilir, WordPiece skoru:
8000 / (50000 · 2000000) = 8 × 10^(-8)
Diğer rastgele pair'lerle karşılaştırınca istatistiksel anlamlı. Merge edilir.

4.
##suffix
Prefix: Kelime Sınırı Korunur#

Konvansiyon#

Bir token kelime başlangıcı değilse,
##
prefix'i ile gösterilir.
"playing" → ["play", "##ing"] "playground" → ["play", "##ground"] "interplay" → ["inter", "##play"]

Niye var#

  1. Word boundary bilgisi korunur: model token'ın kelime başında mı ortada mı olduğunu bilir.
  2. Decoder düzeyinde:
    ["play", "##ing"]
    → "playing" (## ile join),
    ["play", "ground"]
    → "play ground" (## yok, boşlukla join).
  3. MLM avantajı: BERT'in masked language model'ı için kritik. Mask'lanan token'ın kelime parçası mı yoksa tam kelime mi olduğu modele sinyal verir.

Türkçe örnek#

"kitaplarım" → ["kitap", "##lar", "##ım"] "kitap" → ["kitap"] (kelime başı, ## yok) "kitaplar" → ["kitap", "##lar"] "okulda" → ["okul", "##da"]
Sınır marker'ı sayesinde BERT "kitap" ve "##kitap" arasında ayrım yapabilir. (Aslında "##kitap" gerçek vocab'da yok, ama prensip bu.)

BPE'de niye yok#

BPE: GPT-style. Word boundary marker'ı whitespace'i bir karakter olarak tutarak halleder (örn. " kitap" = space + kitap). GPT-2'den itibaren byte-level BPE ile boundary'ler tamamen byte düzeyinde.
WordPiece: ##-marker daha açık ama whitespace'e bağımlı (whitespace pre-tokenization gerekli). Bu, WordPiece'in whitespace-free dillerde (Japonca, Çince) zayıf kalmasının sebebi.

İmplementation detail#

# WordPiece encoding result: tokens = ["kitap", "##lar", "##ım"] # Decoding: def decode(tokens): result = [] for t in tokens: if t.startswith("##"): result[-1] += t[2:] else: if result: result.append(" ") result.append(t) return "".join(result) decode(["kitap", "##lar", "##ım", "okul", "##da"]) # → "kitaplarım okulda"

5. Training Pseudocode — BPE'den Ayrılan 3 Satır#

WordPiece training BPE'ye yapısal olarak çok benzer, ama 3 kritik satır farklı. Aşağıda detaylı pseudocode.
python
# WordPiece Training Pseudocode
# Input: corpus (string list), target_vocab_size (int)
# Output: vocab (set), merge_rules (ordered list)
 
def train_wordpiece(corpus, target_vocab_size):
# 1. Pre-tokenize on whitespace + punctuation
words = []
for sentence in corpus:
for word in whitespace_tokenize(sentence):
words.append(word)
 
# 2. Initial vocab: all unique characters + ##-prefixed chars
vocab = set()
for word in words:
chars = list(word)
vocab.add(chars[0]) # First char: no ##
for c in chars[1:]:
vocab.add(f"##{c}") # Subsequent: ##c
 
# 3. Word splits: list of tokens per word
splits = {}
for word in words:
chars = list(word)
splits[word] = [chars[0]] + [f"##{c}" for c in chars[1:]]
 
# 4. Compute total token counts
word_counts = Counter(words)
 
# 5. Iterative merge loop
merges = []
while len(vocab) < target_vocab_size:
# 5a. Count pairs across all word splits
pair_counts = defaultdict(int)
token_counts = defaultdict(int)
for word, freq in word_counts.items():
tokens = splits[word]
for t in tokens:
token_counts[t] += freq
for i in range(len(tokens) - 1):
pair = (tokens[i], tokens[i+1])
pair_counts[pair] += freq
 
if not pair_counts:
break
 
# 5b. ★ KRITIK FARK: score = count(AB) / (count(A) * count(B))
# BPE: score = count(AB)
best_pair = None
best_score = -float("inf")
for (a, b), count_ab in pair_counts.items():
score = count_ab / (token_counts[a] * token_counts[b])
if score > best_score:
best_score = score
best_pair = (a, b)
 
if best_pair is None:
break
 
# 5c. Apply merge
a, b = best_pair
# ★ KRITIK FARK: merged token strip leading ## from b
if b.startswith("##"):
merged = a + b[2:]
else:
merged = a + b # rare: shouldn't happen mid-word
 
merges.append(best_pair)
vocab.add(merged)
 
# 5d. Update all word splits
for word in word_counts:
tokens = splits[word]
new_tokens = []
i = 0
while i < len(tokens):
if i < len(tokens) - 1 and tokens[i] == a and tokens[i+1] == b:
new_tokens.append(merged)
i += 2
else:
new_tokens.append(tokens[i])
i += 1
splits[word] = new_tokens
 
return vocab, merges
WordPiece training: BPE'den 3 satır farklı

BPE'den Ayrılan Üç Kritik Satır#

#SatırBPEWordPiece
1Inittüm charsfirst chars + ##chars
2Score
count(AB)
count(AB) / (count(A) · count(B))
3Merge result
A + B
A + B[2:]
(## strip)
Geriye kalan tüm yapı özdeş: aynı iteratif merge döngüsü, aynı pair counting, aynı stop condition. Bu, WordPiece ile BPE'nin "kuzen" olmasının kanıtı.

6. Encoding: Greedy Longest-Match First#

BPE encoding (Modül 6.2'den hatırla)#

Merge rule'ları sırasıyla uygula. Her merge bir öncekinin sonucu üzerinde çalışır. Karmaşıklık O(V · L).

WordPiece encoding farklı#

Greedy longest-match left-to-right. Merge rule'ları sırayla değil, vocab'ı arayarak.
def encode_word_wp(word, vocab): """Encode a single pre-tokenized word.""" tokens = [] i = 0 is_first = True while i < len(word): # Find longest substring in vocab starting at i j = len(word) cur_substr = None while j > i: substr = word[i:j] if not is_first: substr = f"##{substr}" if substr in vocab: cur_substr = substr break j -= 1 if cur_substr is None: return ["[UNK]"] # Bütün kelime UNK tokens.append(cur_substr) i = j is_first = False return tokens

Karmaşıklık#

  • WordPiece: O(L²) per word (L = word length). Pratikte küçük (kelimeler kısa, max ~20 char).
  • BPE: O(V · L) per word — vocabulary uzunluğuna bağlı.
WordPiece inference time'da BPE'den daha hızlı (büyük vocab'larda). Bu, BERT'in production deployment'ında bir avantaj.

Encoding örneği#

Vocab: {kitap, ##lar, ##ım, ##im, ##in, [UNK]}, word: "kitaplarım"
i=0, is_first=True: j=10 "kitaplarım" not in vocab j=9 "kitapları" not in vocab ... j=5 "kitap" in vocab ✓ tokens=["kitap"], i=5, is_first=False i=5, is_first=False: j=10 "##larım" not in vocab j=9 "##ları" not in vocab ... j=8 "##lar" in vocab ✓ tokens=["kitap", "##lar"], i=8 i=8, is_first=False: j=10 "##ım" in vocab ✓ tokens=["kitap", "##lar", "##ım"] Final: ["kitap", "##lar", "##ım"]

UNK durumu#

Eğer bir kelimenin herhangi bir parçası vocab'da yoksa, tüm kelime [UNK] olarak işaretlenir.
word = "xqzwabc" # Hiçbir prefix vocab'da yok # Result: ["[UNK]"]
Bu, BPE'den önemli bir fark: BPE byte-level olduğunda asla UNK üretmez. WordPiece char-level fallback'i olmadan UNK üretebilir.

7. BERT Special Tokens — Anatomik İnceleme#

BERT'in WordPiece vocab'ı 30K-110K civarında, ama 5 özel token her zaman var:
TokenID (BERT-base-cased)Görevi
[PAD]
0Batch'lerde kısa sequence'leri padle
[UNK]
100Vocab'da olmayan kelimeler
[CLS]
101Sequence başı — classification embedding
[SEP]
102Sentence separator (sentence-pair tasks)
[MASK]
103MLM training mask

Kullanım örnekleri#

Single sentence classification:
"Bu film harika!" → [CLS] Bu film harika ! [SEP] → [101, 5432, 6789, 8901, 999, 102]
Sentence pair (NLI):
Premise: "Köpekler havlar." Hypothesis: "Hayvanlar ses çıkarır." → [CLS] Köpek ##ler havlar . [SEP] Hayvan ##lar ses çıkar ##ır . [SEP]
MLM training:
Original: "İstanbul Türkiye'nin başkenti." Masked: "İstanbul Türkiye'nin [MASK] ."

[UNK] niye 100 (özel ID değil)?#

BERT vocab tasarımında ilk 1000 ID reserved (specials + reserved spots).
[UNK]
100, çünkü ilk 100 ID rezerve,
[CLS]
,
[SEP]
,
[MASK]
101-103. Vocab'ın geri kalanı 999'dan sonra başlar (BERT-base-cased).

[CLS] embedding'inin önemi#

BERT'in classification mantığı:
[CLS]
token'ının final layer embedding'i = sequence-level representation. Sınıflandırma head'i bu vektör üzerine binds.

Custom special tokens (BERT extension)#

Modern uygulamalarda ek özel token'lar:
  • [unused0]
    ...
    [unused99]
    (BERT-base'de 99 unused slot var, fine-tuning için)
  • <turkish_lang>
    ,
    <code>
    ,
    <math>
    (domain markers)

8. BERT-base-Turkish-cased Vocab İncelemesi (dbmdz)#

dbmdz/bert-base-turkish-cased
— Türkçenin de-facto BERT'i. Stefan Schweter, Bavarian State Library 2020.

Vocab istatistikleri#

  • Boyut: 32K (TR-only model için optimal)
  • Corpus: 35GB Türkçe (Wikipedia + OPUS + OSCAR)
  • Algorithm: WordPiece (HuggingFace Tokenizers, Rust backend)
  • Case-sensitive: "Kitap" ≠ "kitap" (Türkçe büyük/küçük harf önemli — Mehmet vs mehmet)

Vocab snapshot (anlamlı token örnekleri)#

[PAD] # ID 0 [UNK] # ID 1 [CLS] # ID 2 [SEP] # ID 3 [MASK] # ID 4 ## # rare ##a, ##b, ... # Türkçe karakterler ## ile ##ı, ##ğ, ##ş, ##ç, ##ö, ##ü # Türkçe spesifik harfler ve # "and" — frequent word, full token bir # "a/one" — frequent için # "for" — frequent ##lar # plural suffix ##ler # plural suffix (front vowel harmony) ##nın # genitive suffix ##nin # genitive (front vowel) ##un, ##ün # genitive variations ##da, ##de # locative ##dan, ##den # ablative kitap, okul, ev, bir, da, de, ki ...

Önemli gözlem: morfoloji ayrımı#

WordPiece Türkçe corpus'ta ünlü uyumunu doğal olarak öğrenir:
  • ##lar
    ve
    ##ler
    ayrı token'lar (BPE'de de aynı, ama önemli)
  • ##nın
    ,
    ##nin
    ,
    ##nun
    ,
    ##nün
    — 4 varyant (front/back, rounded/unrounded)
Bu, dilbilgisel bilginin vocab seviyesinde encoded olduğu anlamına gelir.

Fertility (kelime başına ortalama token sayısı)#

  • BERT-base-Turkish (WordPiece, 32K): ~1.55 token/word
  • BPE-tr-32K (eşdeğer BPE): ~1.60 token/word
  • Multilingual BERT (mBERT, 110K vocab, %X Türkçe): ~2.1 token/word
  • GPT-2 (50K, English-dominant): ~3.5 token/word Türkçe için
Conclusion: TR-only WordPiece tokenizer Türkçe için multilingual'ı ~36% daha verimli.
python
from transformers import BertTokenizer
 
# BERT-base-Turkish-cased
tokenizer = BertTokenizer.from_pretrained("dbmdz/bert-base-turkish-cased")
 
text = "İstanbul Boğazı'nda balıkçı tekneleri sallanıyor."
tokens = tokenizer.tokenize(text)
print(tokens)
# ['İstanbul', 'Boğazı', "'", 'nda', 'balıkçı', 'tekne', '##leri', 'sallan', '##ıyor', '.']
 
ids = tokenizer.encode(text)
print(ids)
# [2, 4234, 12876, 567, 234, 4567, 234, 3456, 678, 1234, 5, 3]
 
print(tokenizer.decode(ids))
# [CLS] İstanbul Boğazı'nda balıkçı tekneleri sallanıyor. [SEP]
 
# Fertility analysis
words = text.split()
total_tokens = len(tokens)
fertility = total_tokens / len(words)
print(f"Fertility: {fertility:.2f}") # ~2.0 for this complex sentence
BERT-base-Turkish-cased pratik kullanım

9. HuggingFace Tokenizers ile WordPiece Eğitimi#

tokenizers
library (Rust + Python bindings) production-grade. 16-core CPU'da 10GB corpus'u ~30 dk'da train eder.
python
from tokenizers import Tokenizer
from tokenizers.models import WordPiece
from tokenizers.trainers import WordPieceTrainer
from tokenizers.pre_tokenizers import Whitespace, Punctuation, Sequence
from tokenizers.decoders import WordPiece as WordPieceDecoder
from tokenizers.normalizers import NFD, Lowercase, StripAccents, Sequence as NormSeq
 
# 1. Tokenizer init
tokenizer = Tokenizer(WordPiece(unk_token="[UNK]"))
 
# 2. Pre-tokenizer (whitespace + punctuation split)
tokenizer.pre_tokenizer = Sequence([
Whitespace(),
Punctuation(),
])
 
# 3. Decoder (## convention)
tokenizer.decoder = WordPieceDecoder(prefix="##")
 
# 4. Normalizer (case-sensitive Türkçe için sadece NFD)
# Case-insensitive isteyenler: NormSeq([NFD(), Lowercase()])
tokenizer.normalizer = NormSeq([NFD()])
 
# 5. Trainer config
trainer = WordPieceTrainer(
vocab_size=32000,
special_tokens=["[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]"],
initial_alphabet=[], # Boşsa otomatik corpus'tan çıkarır
continuing_subword_prefix="##",
end_of_word_suffix=None, # GPT-style "</w>" yok
show_progress=True,
)
 
# 6. Train
files = ["corpus/wiki-tr.txt", "corpus/news-tr.txt", "corpus/literature-tr.txt"]
tokenizer.train(files, trainer)
 
# 7. Save
tokenizer.save("turkish-wordpiece-32k.json")
 
# 8. Use
output = tokenizer.encode("Merhaba dünya! Tokenizer hazır.")
print(output.tokens)
# ['Merhaba', 'dünya', '!', 'Tokenizer', 'hazır', '.']
print(output.ids)
# [1234, 5678, 999, 8765, 4321, 999]
HuggingFace Tokenizers ile Türkçe WordPiece training (~30 dk)

Training İpuçları (Production)#

  1. Vocab size: Türkçe-only model için 32K-50K sweet spot. 100K'dan fazla diminishing returns.
  2. Corpus diversity: Wikipedia + news + literature + code (kodlu chatbot için) + customer support (domain'e göre).
  3. Pre-tokenization: Whitespace + Punctuation Türkçe için yeterli. Apostrophe handling (
    'nın
    ,
    'da
    ) önemli — punctuation split'i izinli olmalı.
  4. Min frequency: Default
    min_frequency=2
    çoğu zaman iyi. Çok küçük corpus için 1'e düşür.
  5. Special tokens: BERT compat için 5 token şart. Custom: chat templates için
    <|im_start|>
    ,
    <|im_end|>
    ekle.
  6. Save format:
    .json
    (HuggingFace standard) ya da
    vocab.txt
    +
    tokenizer_config.json
    (BERT classic).

10. WordPiece vs BPE — Pratik Karar Matrisi#

KriterBPEWordPieceGalip
Implementation kolaylığıÇok basitBiraz daha karmaşıkBPE
Training hızO(V·N)O(V·N)Eşit
Inference hızO(V·L)O(L²)WordPiece (büyük vocab)
Morfoloji yakalamaİyiDaha iyi (likelihood)WordPiece
Byte fallbackVar (byte-level BPE)YokBPE
Whitespace-free dilİyi (byte-level)ZayıfBPE
MLM uyumluluğuİyiDaha iyi (## marker)WordPiece
Causal LM uyumluluğuİyiİyi ama gereksiz markeringBPE
MultilingualMükemmel (byte-level)İyi (256 init)BPE
Production tooltiktoken, HF tokenizersHF tokenizersEşit
Patent durumuFreeFree (Schuster patent expired)Eşit
EkosistemGPT, Llama, MistralBERT familyBPE (modern)

Karar kuralı (2026 versiyonu)#

  • Yeni causal LM (GPT-style): Byte-level BPE veya SentencePiece BPE.
  • Yeni encoder/MLM: BPE de iyi, ama legacy BERT compat istiyorsan WordPiece.
  • Multilingual model: SentencePiece Unigram LM (Modül 6.5) veya byte-level BPE.
  • TR-only fine-tune (BERT-base-Turkish üzerinde): WordPiece (mevcut tokenizer'ı koru).
  • Domain-specific small model: BPE basitliği için.

Türkçe LLM ekosistemine bakış#

  • dbmdz/bert-base-turkish-cased: WordPiece 32K → encoder family (NER, sentiment)
  • Trendyol-LLM: SentencePiece BPE 32K → causal LM
  • VBart: SentencePiece BPE → seq2seq
  • mGPT, BloomZ TR: byte-level BPE multilingual
Conclusion: WordPiece BERT ekosisteminde hayatta, ama yeni nesil Türkçe LLM'lerin çoğu BPE veya Unigram LM'e geçti.

11. Edge Cases — Production Pitfall'ları#

11.1 Unknown chars → tam kelime UNK#

tokenizer.tokenize("café") # é vocab'da değilse # → ['caf', '##[UNK]'] DEĞIL # → ['[UNK]']
Bu BPE'den önemli fark. Byte fallback yok.
Çözüm: Vocab'a tüm Unicode harflerini ekle (Türkçe için: ASCII + ÇĞİÖŞÜçğıöşü + ümlauts).

11.2 Emoji handling#

tokenizer.tokenize("Harika! 🎉") # → ['Harika', '!', '[UNK]'] (emoji UNK)
Çözüm: HF Tokenizer ile
ByteLevel
pre-tokenizer kullan (ama bu artık byte-level BPE'ye yakınlaşır).

11.3 Mixed casing (case-sensitive)#

# bert-base-turkish-cased: tokenizer.tokenize("İstanbul") # → ['İstanbul'] (tek token, frequent) tokenizer.tokenize("İSTANBUL") # → ['İ', '##S', '##T', '##A', '##N', '##B', '##U', '##L'] (8 token!)
All-caps text catastrophic fragmentation yaratır. Çözüm: Preprocessing'te lowercase (eğer task izin veriyorsa) veya cased+uncased hybrid pipeline.

11.4 Numbers and dates#

tokenizer.tokenize("2026-05-12 saat 14:32'de") # → ['2026', '-', '05', '-', '12', 'saat', '14', ':', '32', "'", 'de']
Sayılar genelde tek token (frequent ones) veya digit-by-digit (rare).

11.5 Apostrophe in Türkçe#

tokenizer.tokenize("İstanbul'da") # → ['İstanbul', "'", 'da'] veya ['İstanbul', "'", '##da']
'
apostrofu BERT-base-Turkish'te ayrı token. Modern tokenizer'larda
'da
tek token olarak öğrenilebilir.

11.6 URL ve email#

tokenizer.tokenize("https://sukruyusufkaya.com") # → ['https', ':', '/', '/', 'su', '##kru', '##yusuf', '##kaya', '.', 'com']
URL'ler fragmenter olur. Çözüm: Custom pre-tokenization rule veya URL replacement (
<URL>
placeholder).

12. Egzersizler#

Bu egzersizler WordPiece anlayışını derinleştirir. Cevapları kendin denedikten sonra accordion'da kontrol et.

Egzersiz 1#

Word: "anlaşamadıklarımızdan". WordPiece encoding bekliyorsun: ["anlaş", "##amadık", "##larımız", "##dan"]. Vocab'da bu parçaları varsayalım.
##
prefix'ler niye böyle dağıldı? Aynı kelime BPE'de nasıl parçalanırdı?

Egzersiz 2#

Pseudocode'da
token_counts
hesaplaması her iteration tekrar yapılıyor. Optimize et: incremental update mümkün mü? Trade-off ne?

Egzersiz 3#

WordPiece skor formülünde
score = count(AB) / (count(A) · count(B))
. Niye log alınmıyor? Mathematical olarak log alsa ne değişirdi?

Egzersiz 4#

"the cat" cümlesini hayalî vocab
{"th": 100, "##e": 50, "cat": 30, "t": 200, "##h": 300, "##at": 80, "[UNK]": 0}
ile encode et. Çıktı?

Egzersiz 5#

BERT-base-Turkish-cased'in
##
prefix'siz versiyonu olur muydu? Avantaj/dezavantaj ne?
✅ Ders 6.4 Özeti — WordPiece'in Sessiz Üstünlüğü
WordPiece, BPE'nin 4 yıl önce doğmuş likelihood-based kuzeni. Merge skoru
count(AB) / (count(A) · count(B))
PMI'ye yakın bir formülle istatistiksel anlamlı birleşmeleri ödüllendiriyor. ##-prefix word boundary'yi açıkça taşıyor — BERT MLM için kritik. Türkçe morfolojiyle doğal uyum, ama byte fallback eksikliği multilingual'da BPE'ye geri kalıyor. Modern karar: encoder family (BERT) ve TR-only fine-tuning'de hâlâ standart, causal LM'de BPE'ye yer bıraktı. Modül 6.5'te SentencePiece Unigram LM ile çok daha probabilistic bir yaklaşıma geçeceğiz.

Sıradaki Ders: Unigram LM (Sentencepiece, Kudo 2018)#

Modül 6.5'te: Vocab'ı büyük başlat, küçült felsefesi. EM algorithm ile token olasılıkları öğrenme. Subword regularization. Llama, T5, Mistral'in temel tercih ettiği yaklaşım. Whitespace-as-character (
) marker'ı ve niye GPT-style byte-level'a göre multilingual'da daha güçlü.

Sık Sorulan Sorular

Schuster & Nakajima 2012 patent başvurusu yaptı (Google'a atandı). 2030+ expire ediyor ama patent **algoritmik formülasyon için zayıftı**, prior art kanıtlandı. Pratik etkisi sıfır — HuggingFace, FB, herkes WordPiece'i serbestçe kullanıyor.

Yorumlar & Soru-Cevap

(0)
Yorum yazmak için giriş yap.
Yorumlar yükleniyor...

İlgili İçerikler