16  Türkçe ve Morfolojik Olarak Zengin Diller

Bölüm durumu: çevrildi. Kaynak metin: İngilizce 16. bölüm. Bu bölüme özgü ölçümler WMT16/17/18 Türkçe–İngilizce test kümelerinde yapıldı: 9.007 profesyonelce çevrilmiş cümle çifti. Bu çiftler aynı içeriği iki dilde verdiği için, alışıldık tek dilli derlemlerin izin vermediği karşılaştırmalara imkân tanıyor. Daha önceki bir bölümde ölçülmüş bir sayı burada yeniden ölçülmüyor; ilgili bölüme atıfla aktarılıyor. Yazılım: sacrebleu 2.6.0, snowballstemmer 3.1.1, transformers 5.15.1, PyTorch 2.13.0, Python 3.14.5.

Öğrenme hedefleri. Bu bölümün sonunda:

16.1 Eklemelilik gerçekte neye mal oluyor

Türkçe eklemeli bir dildir: kelimeleri bir gövdeye ekler yığarak kurar. Her ek bir dilbilgisi parçası taşır, eklerin sırası kuralla sabittir ve eklerin ünlüleri gövdeye uyar. Buna ünlü uyumu denir; aynı ekin kimi zaman -ler kimi zaman -lar olarak görünmesinin nedeni de budur.

Eklemeli — kelimeleri, her biri tek bir dilbilgisi parçası taşıyan ekleri kaynaştırarak ya da ayrı kelimeler kullanarak değil, uç uca dizerek kuran dil. Türkçe, Fince ve Macarca bu türdendir; bir Türkçe sözlüğün asla kapanmamasının nedeni de budur. ↩︎

Ünlü uyumu — bir ekin ünlülerinin gövdenin son ünlüsüne kalınlık–incelik bakımından, dört biçimli eklerde ise düzlük–yuvarlaklık bakımından da uyması kuralı; böylece tek bir ekin iki ya da dört yüzey biçimi olur (evler ama kitaplar; evim, kitabım, okulum, gözüm). Bu kural, bir tokenizer’ın hesaba katması gereken farklı dizgi sayısını katlar. ↩︎

Ev, evler, evlerimiz, evlerimizden. Sonuncusu tek bir Türkçe kelimedir ama dört morfem taşır: gövde artı çokluk, iyelik ve hâl ekleri. İngilizce aynı şeyi söylemek için, biri from edatı olmak üzere üç kelime kullanır: from our houses.

Bunu herkes bilir. Neye mal olduğu ise nadiren ölçülür ve ölçüm, iki dilin de aynı şeyi söylediği bir derlem gerektirir — profesyonel bir çeviri de böyle bir derlemdir.

16.1.1 Aynı içerik üzerinde sözlük büyümesi

O hâlde böyle bir derlem alalım: profesyonel çevirmenlerin çevirdiği dokuz bin haber cümlesi. İki taraftaki farklı kelime biçimlerini sayalım:

WMT16/17/18 tr-en, 9,007 aligned sentence pairs

  Turkish   141,412 tokens   32,866 distinct forms
  English   182,429 tokens   16,652 distinct forms

Türkçe, İngilizcenin token sayısının yalnızca %78’iyle iki kat büyük bir sözlük üretiyor. Aynı içerik, aynı olgular, aynı haberler. Ve oran sabit değil — derlemle birlikte büyüyor:

   tokens seen     TR forms    EN forms    ratio
         5,000        2,471       1,655     1.49
        10,000        4,192       2,575     1.63
        25,000        9,342       5,016     1.86
        50,000       15,963       7,827     2.04
       100,000       25,664      11,848     2.17
       141,412       32,866      14,251     2.31

Bu altı satır iki eğridir. İkisi de Bölüm 2.3.2’de gördüğümüz Heaps yasasına uyar ve ikisi de bükülür; farkları bükülme hızındadır:

Aynı içerik üzerinde iki sözlük ve açılmayı sürdüren fark
OKUNAN TOKEN'A KARŞI FARKLI KELİME BİÇİMLERİ — AYNI 9.007 CÜMLE ÇİFTİ, İKİ TARAFTA DA SAYILDI 010b 20b30b 5b25b 50b100b 141b 32.866 14.251 Türkçe İngilizce İki biçimin anlamı İki eğri de Heaps yasasına uyuyor ve bükülüyor. Fark üslerde: 0,78'e karşı 0,65. İngilizce daha hızlı düzleştiği için aradaki oran açılmayı sürdürüyor. AYNI ŞEY BİR KAT OLARAK — YUKARIDAKİ HER NOKTADA TÜRKÇE BİÇİM SAYISI BÖLÜ İNGİLİZCE 5b10b 25b50b 100b141b 1,491,63 1,862,04 2,172,31

İki eğri de eşit token sayılarında sayıldı; dolayısıyla aradaki fark, bir dilin aynı şeyi söylemek için daha çok kelimeye ihtiyaç duymasından doğan bir yapaylık değil. İki eğri de bükülüyor, ama İngilizce eğrisi daha hızlı: log-log eğimle kestirilen Heaps üssü Türkçede yaklaşık 0,78, İngilizcede yaklaşık 0,65. Bu yüzden aradaki oran, derlem bittiğinde hâlâ büyüyor.

Asıl önemli olan, aradaki farkın açılması. İki dilde de yeni biçimler gelmeye devam ediyor — İngilizce taraf bile 141.000’den 182.000 token’a giderken 2.401 yeni biçim ekliyor; doyum yok. Ama İngilizce eğri daha hızlı yavaşlıyor; Türkçe daha önce kullanmadığı biçimleri daha yüksek bir hızla üretmeyi sürdürüyor, çünkü biçimler bir listeden çekilmiyor, kuralla üretiliyor. Türkçe tarafta 100.000 ile 141.000 token arasında her 5.000 token başına hâlâ yaklaşık 870 yeni biçim geliyor. (İki üs de Bölüm 2.3.2’de verilen tipik 0,4–0,6 aralığının üstünde; bu kadar küçük bir derlemde eğimi eğrinin dik başlangıcı yukarı çekiyor. Önemli olan iki dil arasındaki fark.) Sözlük bir listedir ve üretken morfoloji bir listeye sığmaz.

Kuyruk da aynı şeyi gösteriyor. Aşağıdaki satır, derlemde yalnızca bir kez geçen biçimlerin payını iki dil için veriyor:

  forms occurring exactly once     Turkish   58.6%      English   44.1%

Derlemde yalnızca bir kez geçen biçime hapax denir (çoğulu hapax legomena). Bölüm 4 tümüyle farklı bir Türkçe derlemde — haber değil ürün yorumları, üstelik altı kat büyük — %58,6 hapax ölçmüştü; Bölüm 3 ise Türkçe Wikipedia’da %50,0. Buradaki birebir uyuşmayı tesadüf sayın: hapax payı derlemin büyüklüğüne ve metnin ne kadar gürültülü olduğuna bağlıdır. Üç ölçümün ortak söylediği şu: Türkçe yarının üzerinde ya da tam yarıda duruyor; yukarıdaki İngilizce haber metninin %44,1’inin epey üstünde.

16.1.2 Tek gövde, çok kelime

Sözlük büyüklüğü, maliyete bakmanın bir yolu. Diğeri, bu sayının arkasında ne olduğuna bakmak: o farklı biçimlerin kaçı aslında farklı ekler almış aynı kelime? Derlemi gövdeleyip her gövdenin ürettiği biçimleri saydığımızda:

  32,866 distinct forms  ->  17,891 stems       mean 1.84 forms per stem

  arkadaş   39 forms   arkadaş, arkadaşı, arkadaşım, arkadaşın, arkadaştı, ...
  ülke      35 forms   ülke, ülkem, ülkede, ülkeyi, ülkeye, ülkeden, ülkeler, ...
  el        34 forms   el, eli, ele, elim, elde, elin, elimi, ...
  çocuk     31 forms   çocuk, çocuğu, çocuğa, çocukla, çocuğun, çocukta, ...

1,84 ortalaması etkiyi olduğundan küçük gösteriyor ve bunun iki nedeni var. Birincisi, bu kadar küçük bir derlemde gövdelerin çoğu yalnızca bir kez geçiyor; bu da dilden bağımsız olarak ortalamayı 1’e doğru çekiyor. İkincisi, gövde, gövdeleyicinin kurallarının geri alamadığı bir biçimde değiştiğinde gövdeleyici biçimleri eksik birleştiriyor (aşağıda göreceğimiz 4. kural); aynı kelimenin bazı biçimleri iki ayrı gövde altında sayılıyor. Bilgi veren satır en üsttekidir: 141.000 token içinde sıradan bir ismin otuz dokuz biçimi ve liste tükenmeye hiç yakın değil. Bölüm 4 daha büyük bir derlemde kulla gövdesini paylaşan 895 biçim bulmuştu.

16.1.3 Biçimlerin arkasındaki kurallar

Türkçedeki hemen her yüzey biçimini dört kural üretiyor ve dördü de yukarıdaki listede zaten iş başında. Onları adlandırmak burada önemli, çünkü bölümün ilerleyen kısımlarında göreceğimiz gövdeleyiciler tam da dördüncü kuralda yanılıyor.

1. Ek sırası sabittir. Standart üretken kalıpta Türkçe bir isim GÖVDE (+ÇOKLUK) (+İYELİK) (+HÂL) (+EK EYLEM) düzenindedir ve bu sıra değişmez: ev-ler-imiz-den, asla *ev-den-ler-imiz. (Yapım ekleri ve birleşik kelimeler tabloyu karmaşıklaştırır — türemiş bir gövde de çekim eki alabilir — ama çekim yuvaları bu sırayı korur. Önemli bir istisna -ki: çekimli bir ismi yeniden isimleştirip çokluk–iyelik–hâl döngüsünü baştan başlatır: ev-de-ki-ler-in, hatta evdekilerinki. Kural tabanlı araçları en çok bozan yapılardan biri budur.)

2. Büyük ünlü uyumu (kalınlık–incelik uyumu) iki biçimli ekler doğurur: çokluk eki -lAr, ince ünlüden sonra -ler (ev-ler), kalın ünlüden sonra -lar (kitap-lar) olur.

3. Küçük ünlü uyumu (düzlük–yuvarlaklık uyumu), büyük ünlü uyumuyla birlikte dört biçimli ekler doğurur: 1. tekil iyelik -Im eki -im (ev-im), -ım (kitab-ım), -um (okul-um) ve -üm (göz-üm) biçimlerinde yüzeye çıkar. Biçimleri en hızlı çoğaltan kural bu ve ünlü uyumunun tek cümlelik özetlerinin genellikle atladığı kural da bu.

İki uyum kuralının da istisnaları var ve kural tabanlı gövdeleyiciler ile tokenizer’lar tam da bunlarda yanılır: bazı ekler uyuma hiç girmez (-yor, -ken, -ki, -leyin: geliyor, okurken, evdeki, sabahleyin), bazı alıntı kelimelerde ek, gövdenin son ünlüsüne uymaz (saat-ler, rol-ü, kalp-ler).

4. Ek sınırının iki yanında da sesler değişir. Ünlüyle başlayan bir ek gelince pek çok kelimede gövdenin son ünsüzü yumuşar (ünsüz yumuşaması: kitap → kitab-ı, çocuk → çocuğ-u; ama top → top-u), sert ünsüzden sonra ekin ilk ünsüzü sertleşir (ünsüz benzeşmesi: arkadaş + -(y)DI → arkadaş-tı), iki ünlü arasına kaynaştırma ünsüzü girer (ülke + -I → ülke-y-i) ve bazı kelimelerde gövdenin son hecesindeki ünlü düşer (ünlü düşmesi: ağız → ağz-ı, burun → burn-u). Bunların hiçbiri başka bir ek değil: biçim değiştiren, aynı gövde ya da aynı ektir.

Gövdeleyicileri bozan 4. kuraldır. Gövde sabit değil; dolayısıyla yalnızca ek soyan kural tabanlı bir gövdeleyici kitap ile kitabı’yı hiçbir şekilde birleştiremez. Bu türden her başarısızlık, bir sorgunun bulamayacağı bir belge demektir. Bu bölümde kullanılan Snowball Türkçe gövdeleyicisi en sık görülen durumu yamıyor: ekleri soyduktan sonra sondaki b, c, d ya da ğ’yi p, ç, t ya da k’ye geri çeviriyor. Yukarıdaki listede çocuğu’nun çocuk altında durması bu sayede; kitabı da aynı nedenle kitap’a iniyor. Öteki değişimleri ise geri alamıyor: ağzı ve burnu, ağız ve burun’dan; rengi de renk’ten ayrı kalıyor.

16.1.4 Bunun ortaya çıktığı yerler

Eklemelilik tek bir problem değildir; aynı problemin dört yerde ortaya çıkmasıdır. Tablonun son satırı ise eklemelilikten bağımsız ikinci bir Türkçe özgüllüğünden, alfabeden geliyor (eklemeli Fince bu sorunu yaşamaz; noktalı ve noktasız i’yi paylaşan Azerice yaşar), ama aynı hatları bozuyor. Kitap bunların her birini artık ölçmüş durumda:

Türkçenin beş tuzağı: dördü eklemelilikten, biri alfabeden
nerede ne olur nerede ölçüldü
Tokenization İngilizce ağırlıklı bir tokenizer’la aynı içerik için daha çok token, yani daha çok maliyet ve daha az etkin bağlam Bölüm 8
Sözlük iki kat farklı kelime biçimi (tür), daha uzun kuyruk, daha çok sözlük dışı kelime burada
Sözcüksel erişim belgedekinden farklı bir sorgu biçimi hiçbir şeyle eşleşmez Bölüm 16.4
Kelime düzeyinde metrikler cümle başına daha az token, yani her hata daha pahalı Bölüm 15
Büyük-küçük harf dönüşümü tek bir karakter bütün hattı bozar Bölüm 16.2

Neye bakacağız. Önce normalleştirme (metni karşılaştırılabilir ortak bir biçime getirme). Türkçede iki adımın varsayılan uygulaması bir tercih değil, doğruluk hatasıdır ve ikisi de kod incelemesinde gözden kaçar, çünkü kod doğru görünür. Sonra alt kelime tokenizer’larının büyük ölçüde yerini aldığı morfolojik çözümleme (morphological analysis: kelimeyi gövdesine ve dilbilgisel eklerine ayırma) ve onun hâlâ doğru araç olduğu dört iş. Sonra arama; tek bir ön işleme adımının recall@1’i %28’den %95’e taşıdığı yer. Sonra bu kitabın defalarca karşılaştığı örüntü: İngilizce dışında sessizce yanlış çalışan ve kaynak kodu okunarak değil, bir kontrolle yakalanan standart bir araç. Ardından Türkçe derlemlerin, modellerin ve benchmark’ların (kıyaslama) kısa bir haritası. Ve son olarak tek dilli ile çok dilli modelin karşılaştırması; soruyu ikisini de çalıştırarak karara bağlıyoruz ve sonuç beklediğimiz gibi çıkmıyor.

16.2 Türkçe normalleştirme ve incelemede gözden kaçan iki hata

İngilizcede normalleştirme bir ön işleme kararıdır. Türkçede ise, yukarıda dediğimiz gibi, iki adımın varsayılan uygulaması doğrudan hata üretir.

16.2.1 Birinci hata: str.lower() iki yönde de yanlış

İngilizcede tek harf olan yerde Türkçede iki harf vardır — noktalı ve noktasız i. Noktalı İ/i ile noktasız I/ı farklı sesleri gösteren farklı harflerdir ve aralarındaki büyük-küçük harf eşlemesi ASCII eşlemesi değildir:

        English rules          Turkish rules
  I  →  i                      ı
  İ  →  i + combining dot      i

Noktalı ve noktasız i — İngilizcede tek bir harfin iki biçimi (I/i) olan yerde Türkçede iki ayrı harfin dört biçimi vardır: İ/i ve I/ı. Bu yüzden aralarındaki büyük-küçük harf dönüşümü ASCII kuralını izlemez ve str.lower() iki büyük harfi yanlış dönüştürür: I, ı yerine i olur; İ ise i artı birleşen bir nokta olur. ↩︎

Python’un str.lower()’ı ve JavaScript’in toLowerCase()’i yerelden (locale) bağımsız Unicode varsayılan eşlemesini uygular; yukarıdaki blokta “English rules” diye gösterilen de budur ve Türkçe için yanlıştır. Java’nın toLowerCase()’i ve .NET’in ToLower()’ı ise varsayılan olarak makinenin yerel ayarını kullanır: aynı kod Türkçe yerelli bir dizüstünde bir sonuç, sunucuda başka bir sonuç verir (ünlü “Turkish I” hatası: Türkçe yerelde "TITLE", "tıtle" olur). İkisi de tehlikeli. Aşağıdaki blok WMT16 Türkçe kaynağındaki token sayısını, I ya da İ içeren token’ları ve bunların kaçında str.lower() çıktısının Türkçe kurala göre farklı olduğunu veriyor:

  tokens in the WMT16 Turkish source                      46,243
  tokens containing I or İ                                   438   (0.95%)
  of those, where str.lower() differs from Turkish rules     438   (100%, by construction)

    'İtiraf'      str.lower() 'i̇tiraf'       Turkish 'itiraf'
    'İngilizce'   str.lower() 'i̇ngilizce'    Turkish 'ingilizce'
    'İşlerin'     str.lower() 'i̇şlerin'      Turkish 'işlerin'

Buradaki %100 bir bulgu değil. İki büyük-küçük harf eşlemesi, iki harf için de farklı: I Türkçede ı, İngilizcede i oluyor; İ Türkçede i, İngilizcede i artı bir birleşen nokta oluyor. Dolayısıyla bu iki harften birini içeren her token’ın farklı çıkması zorunlu. Bu aritmetik; onu bir ölçüm diye sunmak, bu kitabın size sürekli kontrol etmenizi söylediği şeyin ta kendisi olurdu.

Bulgu, %0,95. Yüz token’dan biri sessizce bozuluyor ve bunlar rastgele bir yüzde bir değil: büyük noktalı İ, orantısız biçimde özel adlarda ve i ile başlayan her cümle başı kelimede görünüyor — yani bir erişim ya da NER sisteminin en çok önemsediği token’larda.

Kendiniz küçük harfe çevirin — İngilizce kurallara karşı Türkçe kurallar

Tarayıcınızda doğru eşleme yerleşik olarak var — toLocaleLowerCase("tr") — Java, .NET ve ICU’da da var; Python’un standart kütüphanesinde ise yok (aşağıya bakın). Hata hiçbir zaman düzeltmenin bulunmaması değil; varsayılanın yanlış ve sessiz olması.

16.2.2 İkinci hata: sonuç artık tek bir kelime bile değil

Birinci hata yanlış bir dizgi. İkincisi daha kötü ve Bölüm 11’in gerçek veride bulduğu hata bu:

  'İSTANBUL'.lower()  =  'i̇stanbul'

    code points  U+0069 U+0307 U+0073 U+0074 U+0061 U+006E U+0062 U+0075 U+006C
                   i     ̇      s      t      a      n      b      u      l
    categories   Ll     Mn     Ll     Ll     Ll     Ll     Ll     Ll     Ll

  re.findall(r"\w+", 'İSTANBUL'.lower())   →   ['i', 'stanbul']

U+0307 COMBINING DOT ABOVE bir nonspacing mark’tır (kendi başına yatay yer kaplamayan, önceki harfe eklenen birleşen işaret). Python’un re modülü onu kelime karakteri saymaz; bu yüzden \w+ üzerine kurulu bir tokenizer kelimeyi o noktada ikiye böler. Kendi regex motorunuzun da aynı davrandığını varsaymadan önce kontrol edin: \w’nin tanımı gerçeklemeye göre değişir; bazı motorlar nonspacing mark’ları bu tanıma katar, bazıları katmaz. İstanbul, i artı stanbul oluyor ve aşağı akıştaki hiçbir modelleme bu kaybı telafi edemiyor — model kelimeyi hiç görmüyor.

Ve normalleştirdiğinizde de geçmiyor:

  unicodedata.normalize("NFC",  'İSTANBUL'.lower())   →   ['i', 'stanbul']
  'TAVSİYE'.lower()                                   →   ['tavsi', 'ye']

NFC, Unicode normalleştirmesinin (eşdeğer Unicode gösterimlerini ortak bir biçime getirme) birleştirici biçimidir. Burada yeniden birleştirmez, çünkü NFC bir diziyi ancak onu karşılayan tek bir kod noktası varsa birleştirir; i + birleşen nokta için böyle bir kod noktası yok. Unicode normalleştirmesi düzeyinde bir çözüm yok; çözüm, Unicode’un dile özgü büyük-küçük harf kurallarını (SpecialCasing.txt’teki Türkçe ve Azerice koşulları) uygulayan bir kütüphanede, örneğin ICU’da.

Standart kütüphanede de çözüm yok ve yaygın olarak önerilen cevap yanlış: str.casefold() yerele duyarlı değildir ve TAVSİYE üzerinde, birleşen nokta dâhil, lower() ile birebir aynı sekiz kod noktasını üretir. “casefold, küçük harfe çevirmenin daha doğru yoludur” diye ona başvuran bir okur, tam da kaçınmaya çalıştığı hatayla karşılaşır. Python’un standart kütüphanesinde Türkçe büyük-küçük harf dönüşümü hiç yok; ICU’da var (PyICU, icu.UnicodeString(s).toLower(icu.Locale("tr"))). Çoğu hat için daha ucuz cevap, problemi hiç yaratmamak:

import unicodedata

def tr_lower(s):
    # Önce NFC: ayrışık bir İ (I + U+0307) birleşik karaktere dönmeli,
    # yoksa aşağıdaki replace onu ıskalar ve birleşen işaret ayakta kalır.
    s = unicodedata.normalize("NFC", s)
    return s.replace("İ", "i").replace("I", "ı").lower()

def tr_upper(s):
    s = unicodedata.normalize("NFC", s)
    return s.replace("i", "İ").replace("ı", "I").upper()

İki küçük fonksiyon, toplam altı satır; metne başka hiçbir şey dokunmadan önce uygulanır — ve NFC satırı isteğe bağlı değil. Metin, istediğinizden daha sık ayrışık geliyor: HTML formlarından, bazı macOS dosya adlarından, OCR’dan. NFC adımı olmadan tr_lower, ayrışık bir İstanbul üzerinde ı̇stanbul döndürüyor — birleşen nokta hâlâ orada ve artık yanlış ünlünün üstünde. Bu da başlangıçtaki durumdan daha kötü.

Hatanın fark edilmeden sürüp gitmesinin nedeni bu: ona yol açan kod text.lower(), yani doğru görünen, her yerde bulunan ve yazmadığınız her kütüphanenin içinde olan şey. Bölüm 11 bu hatayı, belgelerinin %94,7’si aynı yapaylığı taşıyan bir küme ortaya çıktığı için buldu — kimse onu aradığı için değil. İ içeren bir kelimeyi küçük harfe çevirip kod noktalarını yazdırarak kontrol edin.

16.2.3 Türkçe karakterler: deasciification ve neyi birleştirdiği

Türkçe klavye her yerde bulunmaz ve gerçek hayatta yazılan Türkçenin büyük bir kısmı Türkçeye özgü harfler olmadan, ASCII karşılıklarıyla yazılır — güzel yerine guzel, çok yerine cok. (İngilizce kaynaklar bunlara diacritic, yani aksan işareti der; ama ç, ğ, ı, ö, ş, ü işaretli harfler değil, ayrı harflerdir ve ı → i bir işaret silme değil, harf değiştirmedir.) Bunu ele almak ya Türkçe karakterleri geri koymak (deasciification, Türkçe karakter geri kazanımı) ya da iki biçim de eşleşsin diye Türkçe karakterleri her yerde ASCII’ye indirmek demektir.

Deasciification — ASCII harflerle yazılmış metne Türkçe karakterleri geri koymak (guzel → güzel). Tersi, yani iki biçim eşleşsin diye Türkçe karakterleri ASCII’ye indirmek daha kolaydır ve gerçekten farklı olan kelime çiftlerini birleştirir. ↩︎

ASCII’ye indirmek, cazip tek satırlık çözümdür. Aynı derlemde ölçüldü. Blok sırasıyla Türkçe karakter içeren kelimelerin payını, indirmeden önceki ve sonraki farklı biçim sayısını ve artık iki gerçek kelimeye karşılık gelen ASCII biçimlerini veriyor; alttaki örneklerde parantez içi iki kelimenin anlamlarıdır (oldu/öldü: bir şey oldu / biri öldü; bas/baş: düğmeye bas / baş ağrısı; sac/saç: sac levha / saç; yasa/yaşa: kanun / yaşa!):

  words containing a Turkish-specific character   19,318 / 46,243   (41.8%)
  distinct forms                                          15,173
  distinct forms after stripping diacritics               15,101
  ascii forms now ambiguous between 2+ real words             72

     'oldu'   <-  oldu, öldü          (it happened / he died)
     'bas'    <-  bas, baş            (press / head)
     'sac'    <-  saç, sac            (hair / sheet metal)
     'yasa'   <-  yasa, yaşa          (law / live!)

Yalnızca 72 çakışma; listeyi okuyana kadar zararsız görünüyor. Oysa oldu ile öldü arasındaki fark, “bir şey oldu” ile “biri öldü” arasındaki farktır. O 72 birleşmenin hepsi bir bedel ödetmiyor ve bunları saymak yerine tek tek kontrol etmek gerekiyor: mi ile mı da birleşiyor, ama ikisi ünlü uyumunun ürettiği aynı soru ekinin iki yüzey biçimi, yani hiçbir şey kaybolmuyor. Birleşme oranı düşük, birleşme başına maliyet ise tam bir kayıp. Bu, bir ön işleme kararının alabileceği en kötü biçim: toplu metriklerde görünmez, ama her biri tek başına felaket olan hatalar üretir.

Maliyetini karşılayabiliyorsanız Türkçe karakterleri silmek yerine geri koyun. Bunun için hazır araçlar var: Deniz Yüret’in karar listesi tabanlı Türkçe deasciifier’ı (Python ve JavaScript sürümleri de var), Zemberek’in gürültülü metin normalleştirmesi ve aşağıdaki tablodaki trnlp’nin önerileri. Doğrulukları metnin türüne göre değiştiği için birkaç yüz kelimelik elle düzeltilmiş bir örnekle kendi verinizde ölçün. ASCII’ye indirmek zorundaysanız bunu hem sorguda hem belgede aynı eşlemeyle yapın ve o çiftleri ayırt edilemez hâle getirdiğinizi bilin.

16.3 Morfolojik çözümleme ve hâlâ gerekli olup olmadığı

Alt kelime tokenizer’larından önce Türkçeyi ele almak onu çözümlemek demekti: evlerimizden’i alıp ev gövdesini ve üzerine yığılmış dilbilgisel işlevlerin sıralı listesini döndürmek. Bu konuda alanın büyük başarı hikâyelerinden biri Türkçeye ait — Oflazer (1994) dilin morfolojisini düzgün kapsayan iki düzeyli sonlu durum çözümleyicisini kurdu; bu çözümleyiciden türeyen araçlar hâlâ iş görüyor. (“İki düzeyli”, kuralların iki dizgiyi doğrudan ilişkilendirmesi demek: sözlük düzeyindeki biçim, örneğin kitap + -I, ile yüzey biçimi kitabı. Bir çözümleyici yukarıdaki 4. kurala takılmak yerine onu bu sayede geri alır.)

Çözümlemeyi kulağa geldiğinden zor kılan iki şey:

Belirsizlik. Yüzü dört farklı biçimde çözümlenebilir: isim yüz artı 3. tekil iyelik (onun yüzü), isim yüz artı belirtme hâli (yüzü yıkamak) ve sayı yüz “100” artı bu iki ekten biri. (Yüzün “surat” ile “yüzey” — suyun yüzü — anlamları arasındaki ayrım ise morfolojik değil anlamsal bir belirsizliktir; çözümleyici ikisine aynı çözümlemeyi verir.) Daha keskin bir örnek koyun: tek bir yüzey biçiminde üç ayrı kök — koyun (hayvan), koy “körfez” artı iyelik (senin koyun) ya da tamlayan hâli (koyun kıyısı) ve koy- fiilinin 2. çoğul emir kipi. Morfolojik bir çözümleyici olası bütün çözümlemeleri döndürür; doğrusunu seçmek morfolojik belirsizlik gidermedir ve cümle bağlamı ister. Yani “önce çözümle, sonra modelle” diye özetlenen derli toplu hattın daha ilk adımında cümle düzeyinde bir model gizlidir.

Kapsam. Bir çözümleyici, kurulurken kendisine verilen gövdeleri bilir. Yeni kelimeler ve türetmeler, marka adları, yabancı kökenli kelimeler, yazım hataları ve argo onun kapsamı dışında kalır. Bu durumda başarısızlık da tamdır: hiçbir çözümleme çıkmaz.

Gövde mi, sözlük biçimi mi. Bölüm 2 gövdelemeyi (eşleştirme anahtarı elde etmek için ekleri kırpmak) lemmatization’dan (sözlük biçimine indirgeme: kelimenin sözlükteki madde başını döndürmek) ayırmıştı. Türkçede ikisi arasındaki mesafe büyük. Snowball gövdeleyicisinin çıktısının bir kelime olması gerekmiyor: burun bur’a, ağız ise bambaşka bir kelime olan ak’a dönüşüyor. (Bu kitapta “gövde” NLP anlamında, yani gövdeleyicinin çıktısı anlamında kullanılıyor; bur ya da ak gibi kelime olmayan dizgiler de olabilir. Dilbilgisindeki gövde — kök artı yapım ekleri — ile karıştırmayın.) Üstelik isimlerin aldığı eklere odaklandığı için fiiller zamanlarını ve görünüşlerini koruyor: okuyorlar okuyor oluyor, gidiyor ise hiç değişmeden geri geliyor. Zemberek’inki gibi bir çözümleyici burnu için burun, gidiyor için git kökünü döndürür; NLP araçlarının lemma diye döndürdüğü de genellikle budur. Türk sözlükçülüğündeki madde başı, yani sözlük biçimi ise gitmektir (Bölüm 2’deki gidiyorum örneği). Çözümleyici bunu da ancak olası çözümlemeler arasından seçim yaptıktan sonra yapabilir; bu da yukarıdaki belirsizlik sorunudur.

16.3.1 Peki 2026’da gerekli mi?

Çoğu modelleme için hayır. Alt kelime tokenization’ı (Bölüm 8.3) morfolojiyi dilbilimsel değil istatistiksel olarak ele alır: -lerimizden’in bir gövdeye eklenmiş üç ek olduğunu bilmez, ama bu parçanın tekrarlandığını öğrenir. Bir modelin ihtiyacının çoğu da budur. BERTurk’ün işlem hattının hiçbir yerinde morfolojik çözümleyici olmadan çalışabilmesinin nedeni de bu.

Alt kelime modelinin vermediği bir şeye ihtiyacınız olduğunda gerçek bir çözümleyiciye başvurun:

  • Sözcüksel erişim: indeksi gövde üzerine kurmanız gereken durumlar — Bölüm 16.4 bunun ne kadar kazandırdığını ölçüyor.
  • Dilbilimsel etiketleme: çıktının bizzat dilbilgisel çözümleme olduğu durumlar.
  • Kural güdümlü ürünler — dilbilgisi denetleyicileri, yazım düzeltme, sözlük araması — yanlış bir cevabın açıklanabilir olması gereken yerler.
  • Verinin çok az olduğu durumlar: evlerimizden ile evimiz’in aynı gövdeyi paylaştığını bilmek bir inductive bias (modelin öğrenmesini yönlendiren, önceden verilmiş varsayım) sağlar ve bu önsel bilgi, elinizde olmayan verinin açığını kapatır.

Çoğu projenin vardığı orta yol, çözümleyici değil gövdeleyicidir: kabadır, hızlıdır, giderilecek belirsizlik yoktur ve — Bölüm 16.4’ün gösterdiği gibi — erişimdeki kazancın çoğunu sağlar. Bu bölüm boyunca kullanılan Snowball Türkçe gövdeleyicisi birkaç yüz satırlık bir kural kümesidir. Eksik birleştirir, fazla birleştirir ve recall@1’i %28,0’dan %95,3’e çıkarır.

16.4 Türkçe erişim: farkın ne kadarı morfoloji

Türkçede arama İngilizcede aramadan zordur ve uygulayıcılar bunu genellikle bilir. Asıl bilinmesi gereken, zorluğun ne kadarının yalnızca morfolojiden kaynaklandığıdır — çünkü o kısmın ucuz bir çözümü var, gerisinin yok.

Deney bunu yalıtıyor. 7.165 Türkçe cümleyi belge olarak alın, BM25 ile indeksleyin — BM25, bir belgeyi içerdiği sorgu kelimelerine göre puanlayan standart kelime eşleştirmeli sıralama işlevidir (Bölüm 2) — ve hedef bir belgeden alınan üç içerik kelimesiyle sorgulayın, ama belgenin kullandığından farklı bir yüzey biçiminde. Gerçek durum budur: kullanıcı İstanbul yazar, belgede İstanbul’da geçer. Metrik recall@1: hedef belgenin birinci sırada geldiği sorguların payı (recall@10: ilk on içinde herhangi bir yerde).

Deney düzeneği. Derlem: WMT16–18 Türkçe tarafından 8 ve daha çok kelimelik 7.165 cümle, her biri bir belge. Sorgu: hedef belgeden alınan üç içerik kelimesi; terimlerin %69’u belgedekinden farklı bir çekimde, derlemin başka bir yerinden çekilmiş. Sıralama: BM25, dört ayrı indeks/sorgu şemasıyla. Başarı: hedef belge birinci sıradaysa (recall@1).

7,165 Turkish documents (sentences of 8+ words)
1,481 queries of 3 terms each
69% of query terms are a different inflection than the document uses

index / query scheme      recall@1   recall@10   terms/doc
surface form                 28.0%       54.4%        15.7
5-char prefix                74.6%       92.6%        15.7
Snowball stem                95.3%       99.8%        15.7
character 4-grams            74.9%       94.9%        55.7

Yüzey biçimleriyle çalışan BM25 doğru belgeyi sorguların %28’inde buluyor. Gövdeleme bu oranı %95,3’e çıkarıyor. Tek bir ön işleme adımı, 3,4 kat iyileşme ve işin içinde hiç model yok.

Bu çarpıcı sonucu bir yere aktarmadan önce deney düzeneğini okuyun, çünkü her biri tek başına o 3,4 katı şişirebilecek üç ayrı etken var.

Sorguların nasıl üretildiği, sayının döngüsel olup olmadığını belirliyor. Bir sorgu terimi bir ek kuralı uygulanarak üretilseydi, aynı kural tabanlı gövdeleyici kendi işleminin tersiyle üretilmiş veride puanlanmış olurdu ve %95,3 neredeyse totolojik hâle gelirdi. Buradaki biçimler üretilmiyor, derlemin başka bir yerinden çekiliyor; bu, o tuzağı savuşturuyor. Ama tasarım yine de bilinen belge erişimi: sorgu hedef belgeden geldiği için gövdeleme az çok çalıştığı sürece bir gövde eşleşmesi garanti. %95,3’ü bir kullanıcı sorgusunda göreceğiniz sonuç olarak değil, gövdelemenin geri kazanabileceğinin üst sınırı olarak okuyun.

Kazancın bir kısmı da morfoloji değil, dizgi cerrahisi. snowballstemmer, 3.0.0 sürümünden beri Türkçe algoritmasında bir token’ı ilk kesme işaretinden itibaren kırpıyor (ilk iki karakter içindeki bir kesme işaretini atlayarak; O’Neill’in bu yüzden O’Neill kalıyor). Yani bölümün öne çıkardığı kendi örneği, İstanbul'da → İstanbul, morfolojik bir çözümleme değil; bir split("'"). Çekimli özel adlarla dolu bir haber derleminde tek başına bu adım farkın bir kısmını açıklıyor ve biz bu payı ayrıca ölçmedik. Tabloya eklenecek iki satır bunu ayırırdı: gövdeleme yapmadan yalnızca kesme işaretinden kırpma ve kesme işareti adımı kapatılmış Snowball. 3,4 katı bir yere aktarmadan önce çalıştırılacak ilk şey bunlar. (Pratik bir tuzak: yalnızca ASCII kesme işareti ' sayılıyor. Düzeltilmiş metinlerde sık görülen tipografik ’ tanınmıyor; gövdelemeden önce onu ' ile değiştirin.)

Son olarak sorgu terimlerinin %69’u bilerek farklı bir çekim olacak şekilde seçildi; bir sorgunun hedef belgeyi birinci sıraya taşıyabilmesi için de üç teriminden yeterince çoğunun indeksteki biçimle eşleşmesi gerekiyor. Bu, ortalama bir sorgudan sert, en kötüsünden yumuşaktır — Türkçe bir derlemde arama yapan kullanıcı genellikle sözlük biçimini yazar, derlemde ise kelime çoğu zaman bu biçimde geçmez.

Üç pratik sonuç:

  1. Türkçe sözcüksel aramada gövdeleme isteğe bağlı değildir — bunun gibi sorgularda. İngilizcede genellikle küçük bir iyileştirme olarak bildirilir. Burada çalışan bir arama kutusuyla çalışmayan arasındaki farktır. Bu koşulu sonuçtan ayırmayın: bu sorguların %69’u belgedekinden bilerek farklı bir çekimde kuruldu ve tam eşleşmeyi başarısız kılan da bu. Kullanıcılarının belgelerdeki biçimleri yazdığı bir derlemde fark daralır. Bu sonucu evrensel bir zorunluluk diye aktarmadan önce farkı kendi sorgu kaydınızda ölçün.
  2. Karakter n-gram’ları gürbüz yedektir. Hiçbir dilbilimsel bilgi olmadan %74,9 recall@1; bedeli 3,5 kat indeks boyutu (belge başına 15,7’ye karşı 55,7 terim). Bir dil için gövdeleyiciniz yoksa yapılacak hamle budur.
  3. Kelimeyi ilk beş karakterine kırpmak (prefix truncation) şaşırtıcı derecede iyi bir yaklaşımdır. Bu yöntem %74,6 recall@1 veriyor — karakter n-gram’larıyla neredeyse aynı, üstelik indeks maliyeti yok. Kabadır, kısa kelimelerde yanlıştır ve gerçek bir gövdeleyici yokken başvurulacak yöntemdir.

Bu aynı zamanda Türkçede yoğun (dense) erişim için en güçlü tek argümandır: İstanbul’da’nın embedding’i ile İstanbul’un embedding’i, tokenizer ne yapmış olursa olsun birbirine yakındır, çünkü model onları dizgi eşleştirerek değil bağlamdan öğrendi. Bölüm 19 bunu düzgün biçimde kuruyor; kelime eşleştiren seyrek (sparse) bir yarıyı embedding’e dayanan yoğun (dense) bir yarıyla birleştiren melez (hybrid) retriever da orada. Buradaki ölçüm, seyrek yarının Türkçede neye ihtiyaç duyduğunu söylüyor: gövdeleme. O olmadan bu yarı üzerine düşeni yapmıyor.

16.5 Beş bölümlük örüntü

Bu kitapta bir şey defalarca oldu ve bunu birkaç anekdot olarak bırakmak yerine bir örüntü olarak adlandırmak gerekiyor. Her seferinde standart, yaygın kullanılan bir araç Türkçede sessizce yanlış bir sayı üretti ve her seferinde onu açığa çıkaran şey daha iyi bir model değil bir kontrol ölçümü oldu.

Altı sessiz kusur ve her birini yakalayan kontrol
bölüm araç Türkçede ne yaptı nasıl ortaya çıktı
Bölüm 4 str.lower() IYI İngilizce kuralla iyi, Türkçe kuralla ıyı iki büyük-küçük harf eşlemesini yan yana karşılaştırmak
Bölüm 11 str.lower() İ, i artı birleşen işaret oluyor ve kelimeyi bölüyor %94,7’si tek bir yapaylık olan bir küme
Bölüm 13 WikiANN test kümesinin %13,06’sı eğitim kümesinde birebir geçiyor test girdilerini hash’leyip eğitim girdileriyle karşılaştırmak
Bölüm 14 rouge-score tokenizer’ı Türkçe kelimelerin %44,4’ünü sakatladı tek bir metriğin iki uygulamasının ayrışması
Bölüm 14 bir sadakat vekil ölçüsü (faithfulness proxy) insan gazetecilerin özetlerinin %56’sını sadakatsiz gösterdi kopyalanmış metni puanlamak; kopya sadakatsiz olamaz
Bölüm 15 BLEU cümle başına yaklaşık %22,5 daha az kelime token’ı (İngilizce %29 fazla kullanıyor), yani her hata daha pahalı karşılaştırılabilir bir hatayı iki dilde çalıştırmak (keşifsel)

Buradan üç genel ders çıkıyor ve hiçbiri Türkçeye özgü değil.

Araçlar bozuk değildi; varsayımlarının dışında sınanmamıştı. rouge-score özgün Perl davranışını sadakatle yeniden üretiyor. BLEU tanımının söylediğini yapıyor. WikiANN anlatıldığı gibi kurulmuş. Her biri doğrulandığı dilde doğrudur ve her biri belgelerinin belirtmediği bir varsayım taşır.

Her biri incelemeyle değil bir kontrolle yakalandı. Yan yana konmuş iki büyük-küçük harf eşlemesi; var olmaması gereken bir küme; hash’lenip eğitim girdileriyle karşılaştırılmış test girdileri; aynı metriğin karşılaştırılan iki uygulaması; kusursuz puan alması gereken kopyalanmış metin; iki dilde karşılaştırılabilir bir hata. Bir metriği doğrudan doğrulayamıyorsanız, ona doğru cevabını zaten bildiğiniz bir girdi verin. Bu alışkanlık hepsini buldu, kodu okumak hiçbirini bulmadı.

Kusurlar yapıları gereği sessizdi. İstisna yok, uyarı yok, eksik alan yok — yalnızca olması gerekenden %60 yüksek çıkan bir sayı (rouge-score’un Türkçedeki ROUGE-1’i, Bölüm 14) ya da %13’ü ezber olan bir benchmark. Açıkça hata veren bir hat, düzelteceğiniz bir hattır. Endişelenmeniz gerekenler makul görünen bir ondalık sayı döndürenlerdir.

İngilizce olmayan bir dilde çalışıyorsanız bunu bekleyin ve planınızda buna yer ayırın. Uygulamada bu şu demek: bir araca kendi dilinizde güvenmeden önce onu cevabı bilinen bir girdide çalıştırın — birebir aynı dizgiler, boş dizgiler, kopyalanmış bir belge, tek token’lık bir değişiklik — ve sayının olması gereken sayı olduğunu kontrol edin. Bu iş on dakika sürer ve İngilizce olmayan bir NLP projesinde harcayacağınız en yüksek getirili on dakikadır.

16.6 Türkçe derlemler, modeller ve benchmark’lar

Bu kısım kitaptaki her şeyden daha hızlı eskir. Adları bir sıralama tablosu değil, kaynak türlerinin haritası olarak görün ve birine bağlanmadan önce güncel durumu kontrol edin.

Neye güvenmeyeceğinizi bilmek işin yarısı. Diğer yarısı neyin var olduğunu bilmek: Türkiye dışında çoğu kişinin sandığından daha fazla Türkçe altyapı var.

Encoder’lar. BERTurk (Schweter 2020) varsayılan Türkçe encoder olmayı sürdürüyor ve Bölüm 13 ile Bölüm 12’nin fine-tuning (ince ayar) için kullandığı model bu. Cased (büyük-küçük harfi koruyan) ve uncased (metni küçük harfe çeviren) sürümleri var; Türkçe için neredeyse her zaman cased olan doğrudur. Uncased checkpoint’in yapılandırması yalnızca “küçük harfe çevir” diyor; kütüphanenin varsayılanlarıyla yüklendiğinde tokenizer’ı küçük harfe İngilizce kurallarla çeviriyor (Bölüm 16.2) ve küçük harfe çevirme açık olduğunda işaret silme (strip_accents) de varsayılan olarak açık olduğu için Türkçe karakterleri ASCII’ye indiriyor. IŞIK isik, öldü de oldu olarak çıkıyor — Türkçe karakterler kısmının uyardığı birleşme tam da bu — oysa modelin sözlüğü ş, ü ya da ç içeren ve bu durumda hiç kullanılmayan parçalarla dolu. Yine de kullanacaksanız strip_accents=False verin ve metni önce kendiniz tr_lower ile küçük harfe çevirin.

BERTurk’ün yanında yeni kuşak encoder’lar da çıkıyor; örneğin Boğaziçi Üniversitesi’nin ModernBERT mimarisindeki TabiBERT’i (2025). Aşağıdaki karşılaştırma protokolü bunlar için de aynen geçerli.

Çok dilli encoder’lar. mBERT ve XLM-R (Conneau vd. 2020) Türkçeyi kapsadıkları yaklaşık yüz dilden biri olarak ele alıyor. Bölüm 16.7 bunun neye mal olduğunu ölçüyor.

Üretici modeller. Türkçeye özgü üretici model yelpazesi — TURNA, Kanarya, Trendyol’un ve Cosmos’un LLM’leri, Türkçeye uyarlanmış Llama ve Qwen türevleri — birkaç ayda bir değişiyor. Değişmeyen şey her birine sorulacak soru: ne üzerinde eğitildi ve kullanabilir misiniz? Bölgesel olarak yayımlanan modellerde lisans koşulları büyük uluslararası yayımlardakinden çok daha fazla değişkenlik gösteriyor ve ticari olarak dağıtamayacağınız bir model aday değildir.

Benchmark’lar. Mukayese (Safaya vd. 2022) farklı görevler için Türkçe baseline’ları (karşılaştırma modelleri) bir araya getirdi. Bunu yapmasının nedeni, alanın birbiriyle karşılaştırılamayan Türkçe sayılar raporlamayı sürdürmesiydi. Standart benchmark süitlerinin Türkçe sürümleri de mevcut ve kullanılıyor. Yazıldığı sırada aranabilecek birkaç ad: çok alanlı genel bilgi için Türk sınav sorularından derlenen TurkishMMLU; soru cevaplama için İngilizceden çevrilmiş XQuAD’ın Türkçe bölümü ve Türkçe yazılmış TQuAD; LLM’ler için birleşik süitler olarak Cetvel ve TurkBench. Adlar eskir, türler kalır; aşağıdaki iki uyarı her biri için geçerli.

İki uyarının ikisini de kitap başka derlemlerde zaten gösterdi:

  1. Çeviri yapaylıkları. İngilizceden çevrilmiş bir benchmark, Türkçe yetkinliğini değil, Türkçeye aktarılmış İngilizce metinlerdeki yetkinliği sınar. Çeviri dilinde kelime sırası ve cümle uzunluğu farklıdır; sözcük dağarcığını da bir çeviri sistemi seçmiştir. Benchmark’ın Türkçe yazılmış mı yoksa Türkçeye çevrilmiş mi olduğunu kontrol edin.
  2. Bulaşma. Bölüm 13, standart bir Türkçe NER benchmark’ının test kümesinin %13,06’sını kendi eğitim kümesinde birebir buldu — yüzlerce makalenin kullandığı bir kaynakta. Bir puana inanmadan önce test girdilerinizi hash’leyip eğitim kümesiyle, yapabiliyorsanız modelin ön eğitim derlemiyle de karşılaştırın.

16.7 Çok dilli mi tek dilli mi: bir ölçümle karar vermek

Bu soru her Türkçe projede karşınıza çıkar ve genellikle tercihe göre cevaplanır. Burada ise iki model de çalıştırılarak cevaplanıyor.

bert-base-multilingual-cased ile dbmdz/bert-base-turkish-cased karşılaştırılabilir modeller — aynı mimari, aynı dönem, aynı fine-tuning tarifi — ve ön eğitildikleri veride ayrışıyorlar. Karşılaştırmayı Bölüm 13’ün NER kurulumu sağlıyor; model dışındaki her şey birebir aynı.

WikiANN Turkish NER, 20,000 training sentences, identical recipe

model                     span P  span R  span F1   macro   train s   infer s
BERTurk (monolingual)      91.49   92.35    91.92   91.82     476.6      10.3
mBERT  (multilingual)      92.25   93.27    92.76   92.67     537.5       8.8

Çok dilli model 0,84 span F1 farkla önde çıktı. Bu sonuç, bu kısmın göstermek üzere kurulduğu şeyin tam tersi. Geçiştirmek yerine adım adım inceleyelim; önce sayının neyi destekleyebileceğine bakalım. İki satır da tek bir tohumla yapılmış tek bir eğitim koşusu ve bu kitap, farklı bir tohumun bu görevde span F1’i ne kadar oynattığını ölçmedi (Bölüm 13 kendi tablosu için aynısını söylüyor). BERT-base boyutundaki bir modelin NER üzerinde fine-tuning’inde bu yayılım genellikle birkaç onda bir puan düzeyindedir; burada da öyleyse 0,84 bu yayılımın yaklaşık bir ila iki standart sapmasına denk gelir: fark edilmeye yeter, karar vermeye yetmez. Bu tablonun eksik ölçümü, satır başına beş tohumdur. Bu ölçüm yapılana kadar savunulabilir ifade şudur: bu deney iki modeli birbirinden ayırmadı. Aşağıdaki her şey kimin kazandığıyla değil, bu kadar küçük bir farkın neden şaşırtıcı olmadığıyla ilgili.

16.7.1 Birincisi, karşılaştırma göründüğünden adil

Bariz itiraz büyüklük — mBERT’in 177,3M parametresine karşı BERTurk’ün 110,0M’i. Ama farkın nerede olduğuna bakın:

model                    total    word-embedding table   everything else
BERTurk                 110.0M                  24.6M             85.5M
mBERT                   177.3M                  91.8M             85.5M

(“Everything else”, yani “geri kalan her şey” sütunu on iki transformer katmanını, küçük konum embedding’lerini ve etiketleme head’ini (çıktı katmanını) içeriyor; kelime embedding tablosu ise sözlük büyüklüğü × 768.)

Transformer gövdeleri birebir aynı. On iki katman, aynı genişlik, asıl hesaplamayı yapan aynı 85,5M parametre. Farkın tamamı, sözlük büyüklüğüyle indekslenen bir arama tablosu olan embedding tablosunda — 32.000 girdiye karşı 119.547. mBERT daha büyük bir model değil; daha büyük bir sözlük taşıyan aynı model.

Üstelik Türkçe için daha kötü bir tokenizer’a rağmen kazanıyor. Aynı test kümesinde ölçülen değerler:

model                     vocab    subwords/word   mean sequence length
BERTurk                  32,000             1.66                   14.5
mBERT                   119,547             1.97                   16.8

mBERT aynı Türkçe metne %19 daha fazla token harcıyor; üstelik 3,7 kat büyük bir sözlükle — çünkü o sözlüğün çoğu başka dillere ait.

16.7.2 İkincisi, sonucu büyük olasılıkla açıklayan karıştırıcı etken

WikiANN Wikipedia’dan kuruluyor ve iki model de Wikipedia gördü — ama çok farklı oranlarda.

mBERT yalnızca Wikipedia üzerinde, 104 dilde ön eğitildi. BERTurk’ün 35 GB’lık derlemi ise filtrelenmiş bir OSCAR dökümü, OPUS derlemleri, bir Wikipedia dökümü ve Kemal Oflazer’in katkıda bulunduğu bir derlemden oluşuyor; yani Wikipedia bu eğitim verisinin tamamı değil, küçük bir azınlığı. Dolayısıyla alan eşleşmesindeki fark bir tür farkı değil, bir derece farkı. Bir puanın altındaki farklar tam da bu türden bir etkiden doğar; daha fazla tohum farkın gerçek olduğunu gösterirse, bu büyüklükteki bir fark için en makul sistematik açıklama da budur.

Bu yüzden sonucun savunulabilir yorumu “çok dilli modeller Türkçe için daha iyidir” değil. Savunulabilir yorum şudur: Wikipedia türevi bir görevde, ön eğitimi tamamen Wikipedia olan model — dili daha kötü tokenize etmesine rağmen — tek bir tohumda 0,84 puan önde çıktı; tek bir tohum da bunu gürültüden ayırt edemez.

16.7.3 Yani bu kısmın size asıl verdiği şey bir protokol

Burada genel bir hüküm yok ve bir hüküm sunan herkes bir şey satıyordur. Elimizde olan ise bir karar yordamı: dört ölçüm. Bunlar bu sırayla yapılır, çünkü ucuz olanlar çoğu zaman pahalı olan daha çalışmadan kararı verir:

  1. Kendi metninizde fertility (kelime başına ortalama token sayısı). Her aday için kendi alanınızda ölçün. Sonucu maliyete ve etkin bağlam uzunluğuna çevirin (Bölüm 8). Bu bir saatlik iştir ve bazen tartışmayı bitirir.
  2. Alan örtüşmesi. Her model ne üzerinde ön eğitildi ve verinize ne kadar yakın? Yukarıdaki ölçüm çoğunlukla bunun ne kadar önemli olduğunun bir gösterimi.
  3. Görevin kendisi, iki model, aynı tarif. Aynı veri, aynı hiperparametre, aynı birkaç tohumdan oluşan küme. Başka her şey karşılaştırma değildir.
  4. Operasyonel sütunlar. Eğitim süresi, çıkarım gecikmesi, bellek. Burada mBERT %13 daha yavaş eğitildi ve — daha uzun dizilere rağmen — çıkarımda biraz daha hızlı çalıştı. Bu da işlem hacmi (throughput) konusunda akıl yürütmek yerine ölçüm yapmak gerektiğini hatırlatıyor.

Rust vd. (2021) bu soruyu sistematik biçimde inceliyor: tek dilli modelin avantajının ne kadarı modelden değil tokenizer’dan geliyor? Farklı dillerde vardıkları cevap epeyce büyük bir kısmı — bu da 1. adımı başlamak için doğru yer yapıyor.

Sonucun neyi çürütmediğine dikkat edin. mBERT Türkçeyi hâlâ %19 daha kötü parçalıyor. Bu, maliyet ve bağlam uzunluğu açısından kalıcı bir yüktür ve hiçbir doğruluk sayısı onu ortadan kaldırmaz. Bu görev, span üzerinden puanlanan bir etiketleme görevi değil de token başına faturalanan bir üretim görevi olsaydı, aynı tokenizer ölçümü — daha hiçbir doğruluk karşılaştırılmadan — seçimi tek başına belirleyebilirdi.

16.8 Sezgi kontrolleri

Her birini açmadan önce cevaplayın. Altısı da bu bölümün tartışmayla değil ölçümle çözdüğü sorular.

Sıralayıcıya değil, embedding’lere de değil. Yüzey biçimlerini indeksleyip indekslemediğinize bakın.

Ölçüm, 7.165 Türkçe belge üzerinde, terimleri belgelerdekinden farklı çekimlenmiş sorgularla yapıldı: yüzey biçimli BM25 %28,0 recall@1 alıyor, Snowball gövdeleme ise %95,3. Kullanıcı sözlük biçimini yazar; derlemde çekimli bir biçim vardır; tam dizgi eşleştirme hiçbir şey bulmaz.

Türkçe gövdeleyiciniz yoksa karakter 4-gram’ları %74,9 veriyor, ama indeks 3,5 kat büyüyor. Kelimeleri beş karaktere kırpmak ise hiçbir ek maliyet olmadan %74,6 veriyor.

İki neden ve ikincisi daha kötü.

İngilizcede bir harfin iki biçimi varken Türkçede iki ayrı harfin dört biçimi var: İ i I ı. Büyük-küçük harf eşlemesi de ASCII eşlemesi değil. I ya da İ içeren her kelime İngilizce kurallarla farklı çıkıyor — bu, iki eşlemenin doğrudan sonucu — ve WMT16 Türkçe kaynağında bu kelimeler bütün token’ların %0,95’ini oluşturuyor; birçoğu özel ad.

İkinci neden: 'İSTANBUL'.lower() önce i, ardından U+0307 COMBINING DOT ABOVE üretiyor. Bu bir nonspacing mark ve kelime karakteri sayılmıyor. Bu yüzden re.findall(r"\w+", ...) ['i', 'stanbul'] döndürüyor: kelime ikiye bölünüyor ve NFC normalleştirmesi de parçaları yeniden birleştirmiyor. Model istanbul’u hiç görmüyor.

Ancak ne yaptığınızı bilerek. Türkçe karakterleri ASCII’ye indirmek WMT16 kaynağında 15.173 biçimi 15.101’e indiriyor; yalnızca 72 çakışma. Çakışmaları tek tek okuyana kadar bu, maliyetsiz bir kazanç gibi görünüyor: oldu / öldü (“bir şey oldu” / “biri öldü”), bas / baş (“düğmeye bas” / “baş ağrısı”).

Bu, olabilecek en kötü türden bir ödünleşim (trade-off): toplu bir metrikte görünmeyecek kadar seyrek, her bir vakada ise felaket. Maliyetini karşılayabiliyorsanız Türkçe karakterleri geri getirin. İndirmek zorundaysanız bunu sorguda da belgede de aynı eşlemeyle yapın ve bu çiftlerin artık ayırt edilemediğini belgeleyin.

Birebir aynı içerikte — 9.007 profesyonelce çevrilmiş cümle çifti — Türkçe 141.412 token’dan 32.866 farklı biçim üretti; İngilizce 182.429’dan 16.652. Yani Türkçe, token sayısının %78’iyle iki kat büyük bir sözlük üretiyor.

Daha önemli olan sayı, oranın büyümesi: 5.000 token’da 1,49, 141.000’de 2,31. İki sözlük de Heaps yasasına uyar ve ikisi de büyümeyi sürdürür; ama Türkçenin üssü daha büyük (yaklaşık 0,78’e karşı 0,65), çünkü biçimlerini kuralla üretir. Bu yüzden aradaki oran derlem büyüdükçe açılır. Bir sözlüğün sayılabileceğini varsayan her tasarım — sabit bir kelime listesi, kapalı bir öznitelik kümesi, tam eşleşen bir indeks — bu gerçekle boğuşur.

Sırayla üç soru.

Benchmark Türkçe mi yazılmış, Türkçeye mi çevrilmiş? Çevrilmiş bir benchmark çeviri dilindeki yetkinliği ölçer.

Test kümesi eğitim kümesinde mi? Bölüm 13, yaygın kullanılan bir Türkçe NER benchmark’ında test kümesinin %13,06’sının benchmark’ın kendi eğitim bölmesinde birebir yer aldığını buldu. Hash’lemek dört satırlık iş.

Tokenizer ne yaptı? Bölüm 14, standart ROUGE uygulamasının Türkçe kelimelerin %44,4’ünü sakatladığını buldu. Puan İngilizce üzerinde doğrulanmış bir araçtan çıktıysa puan bir hipotezdir.

Pek çok dil için tek bir dağıtıma ihtiyacınız olduğunda, daha çok etiketli verisi olan bir dilden diller arası aktarım istediğinizde ya da diliniz için tek dilli bir model olmadığında.

Vazgeçtiğiniz şey gizemli değil, ölçülebilir: çok dilli bir tokenizer Türkçe kelime başına daha çok token harcar. Bu hem maliyeti artırır hem de bağlam penceresini daraltır (Bölüm 8). Üstelik tokenizer sözlüğünün bir kısmını da kullanmadığınız dillere ayırır.

Ama doğruluğun da buna paralel olarak düşeceğini varsaymayın. Bölüm 16.7 ikisini de aynı görevde çalıştırdı ve aralarındaki fark 0,84 span F1’i geçmedi. Çok dilli model, aynı metin için %19 daha çok token gerektirmesine rağmen öndeydi. Ancak bu sonuç, alanı çok dilli modelin ön eğitim derlemiyle örtüşen bir benchmark’ta ve tek bir tohumla alındı. Önce fertility’yi, sonra alanı, en son görevi ölçün. O büyüklükte bir farka sonuç demeden önce de deneyi birden fazla tohumla çalıştırın.

16.9 Mülakat soruları

Kaynak konusunda — Bölüm 2’deki çekincenin aynısı.

16.9.1 Dili anlayıp anlamadığınızı sınayanlar

S: Türkçe i problemini hiç görmemiş birine anlatın.

İngilizcede bir harfin iki biçimi (I/i) varken Türkçede iki ayrı harfin dört biçimi vardır: noktalı İ/i ve noktasız I/ı. Bunlar tek bir harfin farklı hâlleri değil, farklı harflerdir. Dolayısıyla aralarındaki eşleme ASCII eşlemesi değildir: I küçülünce ı, i büyüyünce İ olur. Sonuç, mülakatçının duymak istediği kısımdır: str.lower() Türkçede bir üslup tercihi değil, bir doğruluk hatasıdır. IŞIK’ı, Türkçenin gerektirdiği ışık yerine işik yapar. Bu harflerden birini içeren her kelimenin farklı çıkması iki eşlemenin doğrudan sonucudur; ölçülen sayı, bu kelimelerin ne sıklıkta geçtiğidir — WMT16 haber metninde kabaca yüz token’da bir, özellikle özel adlarda ve cümle başındaki kelimelerde. İkinci bir biçimde de yanlış sonuç verir: 'İstanbul'.lower(), i artı bir birleşen üst nokta döndürür. Çıktı dokuz kod noktasıdır, istanbul ise sekiz. Bu yüzden iki dizgi ekranda birebir aynı görünür ama karşılaştırıldığında eşit çıkmaz. Üstelik \w+ tokenizer’ı bu dizgiyi ['i', 'stanbul'] diye böler ve NFC normalleştirmesi bunu onarmaz. Çözüm, metrik kodunuzun içi dâhil her yerde uygulanan, yerele duyarlı bir küçük harf dönüştürücüdür.

S: Alt kelime tokenizer’ları Türkçede neden zorlanır ve bu neye mal olur?

Çünkü eklemelilik kelime biçimlerini listelemek yerine birleşimsel olarak üretir: bir gövde artı bir ek yığını, öyle ki tek bir derlemde arkadaş 39 farklı biçimde göründü. Çoğunlukla İngilizce üzerinde eğitilmiş bir tokenizer’ın sözlüğünde bu ekler için parçalar ya eksiktir ya da morfem sınırlarıyla her zaman örtüşmez (im|iz bölünmesi, Bölüm 8.3.3). Maliyet somuttur ve üç kalemde toplanır: aynı metin için daha çok token, yani para; bağlam penceresine daha az içerik, yani yetenek; ve daha hızlı büyüyen bir sözlük — iki dil de Heaps yasasına uyuyor, ama bu bölüm Türkçe/İngilizce farklı biçim oranının 5.000 token’da 1,49’dan 141.000’de 2,31’e büyüdüğünü ölçtü, çünkü İngilizce eğri daha hızlı düzleşiyor.

S: Türkçe için gövdeleme mi morfolojik çözümleme mi?

Gövdeleyiciyle başlayın; ne kadar iş gördüğüne şaşıracaksınız. Snowball kabadır: bazen ayrı kalması gereken biçimleri birleştirir, bazen de birleştirmesi gerekenleri ayrı bırakır. Yine de bu bölümün erişim görevinde recall@1’i %28,0’dan %95,3’e çıkardı: tek bir ön işleme adımıyla 3,4 kat iyileşme, işin içinde hiç model yok. Eşleştirme anahtarı yerine çözümlemenin kendisine ihtiyacınız olduğunda gerçek bir morfolojik çözümleyiciye başvurun: kimin kime ne yaptığına karar vermek için hâl bilgisini geri kazanmak, yüzü biçimini netleştirmek (onun yüzü mü, belirtme hâlindeki yüz mü, yoksa “100” anlamındaki yüz mü?) ya da biçim üretmek. Mühendislik cevabı şu: gövdeleyici varsayılandır; çözümleyici ise gerekçesini savunabilmeniz gereken bir ihtiyaçtır.

16.9.2 Bir şey yayına alıp almadığınızı sınayanlar

S: Testi olmayan bir Türkçe NLP sistemi devraldınız. Önce ne yaparsınız?

Hiçbir şey eğitmeyin. Kontrolleri çalıştırın, çünkü bu bölümün bütün savı, araçların İngilizce dışında sessizce bozulduğudur. I ve İ içeren bir kelime listesini küçük harfe çevirip doğru çalışan bir küçük harf dönüştürücünün çıktısıyla diff’leyin. Metriğinize tahmin olarak referansın bir kopyasını verin ve tam puan döndürdüğünü kontrol edin; bu, iki tarafı farklı işleyen bir düzeneği yakalar — Bölüm 14’ün, profesyonel gazetecileri %56 oranında sadakatsiz gösterirken yakaladığı, bizim yazdığımız sadakat vekil ölçüsü gibi. İki tarafı aynı biçimde bozan bir tokenizer’ı ise yakalamaz: Türkçe kelimelerin %44,4’ünü bölen rouge-score, Türkçe bir referansa kendisiyle karşılaştırıldığında yine tam puan verir. Bunun için tek bir Türkçe kelimesi farklı iki cümleyi puanlayın ya da ikinci bir uygulamayla karşılaştırın ve token’ları yazdırın: ortak hiçbir kelimesi olmayan güzel ile özel için rouge-score 0 yerine 0,67 ROUGE-1 veriyor. Sonra gerçek üretim metninde fertility’yi ölçün. Bunların her biri bir öğleden sonralık iş ve şimdiye kadar her biri gerçek bir hata yakaladı.

S: Türkçe bir LLM özelliğini nasıl bütçelersiniz?

İngilizce bir tahmini Türkçeye uyarlayarak değil, kendi metninizde fertility’yi ölçüp çarparak. Fertility’yi faturaya çevirirken dikkatli olun, çünkü ikisi aynı oran değil. Fertility kelime başına token’dır ve Türkçe aynı şeyi daha az kelimeyle söyler — Bölüm 15, İngilizcenin özdeş içerik için 1,29 kat kelime token’ı (yani %29 fazla) gerektirdiğini ölçtü. İkisi birlikte hesaba katılınca 1,5–2 katlık bir fertility oranı, özdeş içerikte kabaca 1,2–1,6 kat toplam token’a karşılık gelir. Bunu ölçülmüş bir fatura değil, açıklayıcı bir örnek sayın: iki oran farklı örneklemlerden geliyor. Üstelik faturada girdi ve çıktı fiyatları, önbellek ve yeniden denemeler ayrı kalemlerdir. Sayının kendisini istiyorsanız iki dilin toplam token’larını aynı paralel örneklemde sayın. Aynı toplam oran etkin bağlam penceresini de daraltır; özellikleri asıl bozan kısıt da budur. Model seçiminin bu sayıyı değiştirdiğini de söyleyin: dile özgü bir tokenizer bu sayıyı en çok etkileyen tek etkendir ve ön eğitim sırasında sabitlenir. Dolayısıyla sonradan ayarlanacak bir şey değil, bir tedarik kararıdır.

S: Türkçe benchmark’ınız 92 gösteriyor. Güvenir misiniz?

Kontrolün ne dediğini sorarım: basit bir baseline kaç alıyor, ikinci bir tohum sayıyı ne kadar oynatıyor? Bu bölüm aynı Türkçe görevde tek dilli ve çok dilli bir modeli fine-tune etti ve çok dilli olan, tek bir tohumla, 92,76’ya 91,92 F1 ile önde çıktı. Bu, yaygın kanının da bizim beklentimizin de tersiydi. Ama iki modelin transformer gövdesi aynı büyüklükte. Dolayısıyla doğru okuma şu: karşılaştırma mimariyle değil ön eğitim verisiyle ilgili ve tek bir görev hüküm vermeye yetmez. Güven kazandıran şey bir protokoldür: kendi metninizde ölçülmüş fertility, kontrol edilmiş alan örtüşmesi, kendi verinizde fine-tune edilmiş iki model ve herhangi bir sayı raporlanmadan önce bir bulaşma denetimi.

16.10 2026 alet çantası

Bu bölümdeki her şey aşağıdaki sürümlerle tek bir dizüstü bilgisayarda çalıştı.

Bu sayıların çıktığı yığın
kütüphane kullanılan sürüm burada ne işe yarıyor
snowballstemmer 3.1.1 %28,0 → %95,3 erişim sonucunun arkasındaki Türkçe gövdeleyici
transformers 5.15.1 Bölüm 16.7’de BERTurk ve mBERT’in fine-tuning’i
datasets 5.0.1 baştan sona kullanılan Türkçe veri bölmeleri

Yukarıda kullanılmayan ama bilinmesi yararlı araçlar:

Daha geniş ekosistem, yazıldığı andaki sürümler
kaynak güncel sürüm ne zaman kullanılır
zeyrek 0.1.3 saf Python morfolojik çözümleyici ve lemmatizer — gövde yetmediğinde tam çözümlemeler
zemberek-python 0.2.3 referans Türkçe NLP araç seti Zemberek’in kısmi, saf Python uyarlaması (Java gerekmez): belirsizlik gidermeli çözümleme, çekimli biçimleri üretmeniz gerektiğinde kelime üretimi, tokenization, gürültülü metin normalleştirmesi
turkish-morphology 1.2.5 Google’ın sonlu durum çözümleyicisi; bir çözümleme için ikinci bir görüş isterseniz
trnlp 0.2.3a0 gövdeleme, çözümleme ve Türkçe karakter yerine ASCII harflerle yazılmış kelimeler için öneriler
BERTurk / mBERT Hub’da yukarıda karşılaştırılan iki model; tek biriyle değil, ikisiyle birden başlayın
Mukayese GitHub’da Türkçe benchmark süiti — standartlaştırdığı görevler için kullanın ve bir puanı raporlamadan önce her görevin gerçekte neyi ölçtüğünü okuyun

16.11 Lab: güvenebileceğiniz bir Türkçe değerlendirme süiti

Bu labın amacı modelleri sıralamak değil. Araçların üzerinde doğrulanmadığı bir dilde, savunabileceğiniz bir değerlendirme kurmak.

16.11.1 Adım 1 — üç görevi kendiniz, Türkçe yazın

Her görev için elli madde: sınıflandırma, bilgi çıkarma ve üretici bir görev. İngilizceden çevirmek yerine Türkçe yazın, çünkü çevrilmiş bir süit çeviri dilini ölçer. Sıkıcı ve tek anlamlı tutun — bir zorluk kümesi değil bir ölçüm aleti kuruyorsunuz.

16.11.2 Adım 2 — bir şey puanlamadan önce puanlayıcıyı doğrulayın

Her metriğe kusursuz bir tahmin verin ve kusursuz puan döndürdüğünü teyit edin. Sonra kopyalanmış bir girdi, boş bir tahmin, tek karakter farklı bir tahmin ve tek bir Türkçe kelimesi farklı iki cümle verin. Çalıştırmadan önce her birinin ne döndürmesi gerektiğini yazın.

Labın tamamı bu adımdır — ve kusursuz tahmin kontrolü tek başına yetmez. Bölüm 14 standart bir metriğin Türkçe kelimelerin %44,4’ünü sakatladığını buldu ve o metrik kusursuz tahmin testini geçer: iki taraf da aynı biçimde bölündüğü için bir referans kendisiyle yine birebir eşleşir. Onu açığa çıkaran, cevabı kusursuz olmayan ve önceden bilinen bir çift (güzel ile özel’in ortak hiçbir kelimesi yok, ama 0,67 alıyor), aynı metriğin farklı sonuç veren ikinci bir uygulaması ya da düpedüz token’ları yazdırmaktır.

16.11.3 Adım 3 — kendi metninizde iki normalleştirme hatasını kontrol edin

Süitinizi küçük harfe çevirin ve U+0307 arayın. İ içeren kelimeleri sayın ve her birinde str.lower() ile tr_lower()’ı karşılaştırın. Süitiniz hatayı zaten içeriyorsa değerlendireceğiniz her model bozuk girdi üzerinden puanlanacaktır.

16.11.4 Adım 4 — fertility’yi ölçün ve paraya çevirin

Sınamayı planladığınız her model için kendi metninizde Türkçe kelime başına token sayısını ölçün. İstek hacminizle çarpın. Seçimi çoğu zaman doğruluktan önce bu sayı belirler.

16.11.5 Adım 5 — biri çok dilli olmak üzere üç model çalıştırın

Türkçeye özgü bir model, çok dilli bir model ve bir LLM. Doğruluk, istek başına token, gecikme ve bin istek başına maliyeti raporlayın — dört sütun, çünkü doğruluk tek başına hiçbir zaman bir dağıtım kararını belirlemedi.

16.11.6 Adım 6 — bulaşma denetimi yapın

Süitinizdeki maddelerin hash’lerini, modellerin eğitim verisi hakkında bildiğiniz her şeyle karşılaştırın. Bir ön eğitim derlemini genellikle kontrol edemezsiniz. Kontrol edemediğinizi üstü kapalı bırakmayın, açıkça yazın.

16.11.7 Neyi teslim edeceksiniz

Dört sütunlu tablo, 2. adımdaki puanlayıcı doğrulama kaydı (öngörülen ve gerçekleşen değerler sütunuyla) ve bir paragraf. Paragrafta hangi modeli yayına alacağınızı ve fikrinizi neyin değiştireceğini yazın.

16.12 Alıştırmalar

  1. Kendi dilinizde sözlük büyümesi. Profesyonelce çevrilmiş herhangi bir paralel derlem alın ve iki taraf için de farklı biçim sayısını token sayısına göre çizin. Oranı üç derlem büyüklüğünde raporlayın ve farkın açılıp açılmadığını söyleyin.

  2. Küçük harf dönüştürücüyü kırın. str.lower() ile küçük harfe çevrildikten sonra re.findall(r"\w+", ...) çağrısının ikiye böldüğü bir Türkçe kelime bulun. Kod noktalarını yazdırın. Sonra kendi yığınınızdaki kütüphanelerde aynı sorunun olup olmadığını kontrol edin.

  3. Erişim düzeltmesi, kendi verinizde. Bir Türkçe derlemi BM25 ile iki kez indeksleyin: yüzey biçimleri ve gövdeler. Sözlük biçimleriyle sorgulayın. İkisi için recall@1 raporlayın ve arama kutunuzun ne yapması gerektiğine karar verin.

  4. ASCII çakışma listesi. Bir Türkçe sözlükteki Türkçe karakterleri ASCII’ye indirin ve artık iki veya daha fazla gerçek kelimeye eşlenen her ASCII biçimi listeleyin. Karışıklığın alanınızda ne kadar kötü olacağına göre sıralayın.

  5. Fertility’den faturaya. Bir Türkçe belgeyi ve İngilizce çevirisini alın, ikisini de ürününüzün gerçekten kullandığı tokenizer’la tokenize edin ve farkı istek hacminizde aylık faturaya çevirin. Sonra aynısını Türkçe öncelikli bir tokenizer’la yapın ve farkı raporlayın (Bölüm 8 yöntemi veriyor).

  6. Bir Türkçe benchmark’ı denetleyin. Kullanacağınız birini seçin. Çeviriden kalan izleri kontrol edin, test ve eğitim kümelerinin hash’lerini karşılaştırın ve puanlama betiğini kusursuz bir tahmin üzerinde çalıştırıp kusursuz puan döndürdüğünü teyit edin — ardından tek kelimesi farklı iki Türkçe cümle üzerinde, çünkü iki tarafı eşit biçimde bozan bir tokenizer ilk kontrolden yine de geçer. Bulduklarınızı raporlayın; cevap “hiçbir sorun yok” olsa bile.

  7. Kontrol alışkanlığı. Güvendiğiniz herhangi bir metriği alın ve ona doğru cevabını kesin olarak bildiğiniz bir girdi verin — birebir aynı dizgiler, kopyalanmış bir belge, boş bir tahmin. Ne döndürmesi gerektiğini ve ne döndürdüğünü yazın. Bu alıştırmanın isabet oranı düşük, getirisi muazzamdır.

16.13 Daha derine

I ve İ içeren bir Türkçe kelime listesi üzerinde str.lower() çalıştırıp yerele duyarlı bir küçük harf dönüştürücüyle diff’leyerek başlayın. Bu bölümdeki geri kalan her şey, o sonuca inanmanıza dayanıyor.

Makalelerin ötesi
kaynak ne olduğu
Zemberek referans Türkçe NLP araç seti — morfoloji, yazım, tokenization; gövdeleyici yetmediğinde başvurulacak araç
Mukayese baseline’larıyla bir Türkçe benchmark süiti; bir puanı raporlamadan önce her görevin neyi ölçtüğünü okuyun
BERTurk burada kullanılan tek dilli modeller; derlemleri ve eğitimleri belgelenmiş
TDD — Türkçe Doğal Dil İşleme Türkçe derlemler, modeller ve araçlar tek bir yerde toplanmış
Speech and Language Processing — Jurafsky & Martin çevrimiçi ve ücretsiz; “Words and Tokens” bölümü morfemleri ve alt kelime tokenization’ını anlatıyor. Morfolojinin sonlu durum ele alınışı bu taslakta değil, basılı ikinci baskıda
Birincil kaynaklar
konu kaynak
Türkçe morfolojinin hakkıyla ele alınışı Oflazer (1994)
Türkçe benchmark süiti Safaya vd. (2022)
baştan sona kullanılan tek dilli encoder Schweter (2020)
dile özgü bir tokenizer’ın değeri Rust vd. (2021)
tek dilli encoder’ın karşılaştırıldığı çok dilli model — bert-base-multilingual-cased Devlin vd. (2019)
yukarıda anılan diğer çok dilli encoder, XLM-R Conneau vd. (2020)

16.14 Akılda kalması gerekenler

  • Eklemelilik ölçülebilir ve birikimlidir. Birebir aynı içerikte Türkçe 141.412 token’dan 32.866 farklı biçim, İngilizce 182.429’dan 16.652 üretti — token sayısının %78’iyle iki kat büyük bir sözlük. Derlem büyüdükçe oran da artıyor (1,49 → 2,31): iki eğri de Heaps yasasına uyuyor, ama Türkçenin üssü daha büyük (≈0,78’e karşı ≈0,65), çünkü Türkçe biçimleri bir listeden çekmiyor, kuralla üretiyor. Bir sözlüğün sayılabileceğini varsayan her tasarım bu gerçekle boğuşur.

  • str.lower() Türkçede iki ayrı açıdan doğruluk hatasıdır. I ya da İ içeren her kelime İngilizce kurallarla yanlış çıkıyor — bu kısmı aritmetik — ve bu kelimeler kabaca yüz token’da bir geçiyor (WMT16 kaynağının %0,95’i), özellikle özel adlarda. Üstelik 'İSTANBUL'.lower(), i artı bir birleşen işaret üretiyor; bu yüzden \w+ ['i', 'stanbul'] döndürüyor. Kelime ikiye bölünüyor ve NFC bunu onarmıyor. Metne başka hiçbir şey dokunmadan önce üç satırlık bir tr_lower çalıştırın.

  • Türkçe sözcüksel aramada gövdeleme isteğe bağlı değildir — burada sınanan türden sorgularda. O sorgu kümesinin %69’u belgeden çekim bakımından farklılaşacak şekilde kuruldu; dolayısıyla bunu bir zorunluluk saymadan önce kazancı kendi sorgu kayıtlarınızda ölçün. Yüzey biçimli BM25: %28,0 recall@1. Snowball gövdeleme: %95,3. Karakter 4-gram’ları hiçbir dilbilimsel bilgi kullanmadan %74,9 veriyor, ama indeks 3,5 kat büyüyor. İngilizcede bu genellikle küçük bir iyileştirme olarak bildirilir; burada ise arama kutusunun çalışıp çalışmaması demektir.

  • Türkçe karakterleri ASCII’ye indirmek yalnızca 72 çakışmaya yol açıyor, ama bazıları iki kelimeyi tamamen ayırt edilemez hâle getiriyor. oldu ile öldü — “bir şey oldu” ile “biri öldü” — aynı dizgi oluyor (mi/mı gibi birkaçı ise hiçbir şey kaybettirmiyor). Her toplu metrikten geçecek kadar seyrek, denk geldiği her seferde önemli olacak kadar ağır.

  • Bu görevde çok dilli model tek dilliden önde çıktı, 92,76’ya 91,92 span F1 — transformer gövdeleri birebir aynıyken (her biri 85,5M; parametre farkının tamamı embedding tablosu) ve Türkçeyi %19 daha kötü tokenize etmesine rağmen; ama tek bir tohumla, yani iki model henüz birbirinden ayrışmış sayılmaz. Fark kalıcı çıkarsa muhtemel neden alan: benchmark Wikipedia’dan kurulmuş ve mBERT’in ön eğitimi yalnızca Wikipedia üzerinde yapıldı. Burada genel bir hüküm yok, yalnızca bir protokol var — kendi metninizde fertility, alan örtüşmesi, kendi görevinizde aynı tarifle iki model, sonra operasyonel sütunlar.

  • Alt kelime tokenization’ı modellemede morfolojik çözümlemenin yerini aldı, ama her işte değil. Dilbilgisi çıktının kendisi olduğunda, yanlış bir cevabın açıklanabilir olması gerektiğinde ya da indeksleyeceğiniz gövdeye ihtiyacınız olduğunda gerçek bir çözümleyiciye başvurun. Birkaç yüz satırlık bir gövdeleyicinin erişimdeki kazancın çoğunu sağladığını da not edin.

  • Beş bölüm boyunca tekrar eden örüntü: standart araçlar İngilizce dışında sessizce bozulur. str.lower(), rouge-score, BLEU, bir benchmark’ın kendi bölmeleri ve bu kitap için yazılmış bir sadakat vekil ölçüsü: her biri Türkçede makul ama yanlış bir sayı üretti. Hiçbiri hata vermedi. Her biri bir kontrol ölçümüyle — doğru cevabı önceden bilinen bir girdiyle — yakalandı, hiçbiri kod okunarak değil. O listedeki son madde bizim; asıl mesele de bu. Bu hata türünün kaynağı başkalarının dikkatsizliği değil.

  • O yüzden önce kontrolü kurun. Bir araca kendi dilinizde güvenmeden önce ona cevabı şüpheye yer bırakmayan bir şey verin: birebir aynı dizgiler, kopyalanmış metin, kusursuz bir tahmin, ortak hiçbir kelimesi olmayan iki metin, çoğunluk sınıfı baseline’ı. Birebir aynı girdilerde tam puan gereklidir ama yeterli değildir — iki tarafı aynı biçimde bozan bir tokenizer’ı göremez. Bu on dakikanızı alır ve İngilizce dışındaki bir NLP projesinde en yüksek getirili on dakika olur.