4 Metin Temsillerini Karşılaştırmak: Sayımlar ve Embedding’ler
Öğrenme hedefleri. Bu bölümün sonunda:
- gerçek ve dengesiz bir veri kümesi için, önceki iki bölümün yöntemleriyle (Bölüm 2, Bölüm 3) ham metinden değerlendirilmiş tahmine uzanan bir pipeline (işlem hattı) kurabilirsiniz;
- bu dengesiz görevde doğruluğun (accuracy) neden tek başına yeterli olmadığını açıklayabilir, macro-F1’i sınıf başına aritmetiğiyle hesaplayabilir ve farklı iş hedeflerinde başka metriklerin seçilebileceğini tartışabilirsiniz;
- bir görevde sayım ve embedding temsilleri için başlangıç beklentisi oluşturabilir; etiketli ve etiketsiz veri miktarını, görevin yapısını, ön işlemeyi ve ayar bütçesini birlikte değerlendirip beklentinizi deneyle sınayabilirsiniz;
- Türkçe metinlerde out-of-vocabulary (OOV, sözlük dışı kelime) oranını ölçebilir; fastText’in hangi yeni biçimler için vektör üretebildiğini, bu vektörlerin niteliğini ve görev başarısını ayrı ayrı değerlendirebilirsiniz;
- unigram torbası ile kelime vektörü ortalamasının kaybettiği sıra bilgisini örnekle gösterebilir; daha uzun n-gram’ların ve sıraya duyarlı modellerin hangi ayrımları geri getirebildiğini açıklayabilirsiniz.
Neye bakacağız. Tek bir Türkçe yorum veri kümesinde sayım ve embedding temsillerini ortak bir değerlendirme düzeninde karşılaştıracağız. Mühendislik anlamında bir bake-off böyle kontrollü bir karşılaştırmadır: birkaç aday yöntem, tek görev, tek protokol ve hepsi için aynı metrik. Önce sınıf dengesizliğine uygun metriği ve ön işlemeyi belirleyecek, ardından yöntemlerin skorunu, kapsamasını, maliyetini ve hata örneklerini inceleyeceğiz. Son olarak etiketli veri miktarı değiştiğinde sonucun nasıl değiştiğini ve iki temsil ailesinin hangi sıra bilgisine duyarsız kaldığını göstereceğiz.
4.1 İki temsil ailesini aynı görevde karşılaştırmak
Bölüm 2 size kelimeleri saymayı öğretti. Bölüm 3 ise onları koordinat olarak yerleştirmeyi. Her iki bölüm de bir iddiayla bitti.
baseline (karşılaştırma modeli) — yeni bir yöntemin yararını değerlendirmek için aynı veri ve aynı metrik üzerinde kullanılan başvuru sonucu. Basit bir çoğunluk sınıfı kuralı da güçlü bir TF-IDF sistemi de baseline olabilir. Bir skoru yorumlamak için baseline’ın yanında sınıf dağılımı ve görevdeki hata maliyetleri de gerekir. ↩︎
agglutinative (eklemeli; Türkçe özelinde sondan eklemeli) — biçimbirimlerin (morpheme) çoğunlukla ayırt edilebilir ekler olarak kelimeye bağlandığı dil yapısı. Türkçede çekim ve türetim ekleri bir kökün ya da gövdenin birçok yüzey biçimini oluşturabilir; bu biçimlerin sayısı kullanıma ve derleme bağlıdır. ↩︎
2. bölüm, seyrek (sparse) sayım vektörlerinin güçlü, ucuz ve yorumlanabilir bir baseline (karşılaştırma modeli) olabildiğini gösterdi. 3. bölüm ise her kelime biçimine bağımsız bir öznitelik ayırmanın, agglutinative bir dil olan Türkçenin çekimli biçimlerinde kapsama sorunu yaratabileceğini anlattı. Oradaki ölçüm şuydu: bir Türkçe Wikipedia örnekleminin %90’ı üzerinde sözlük kurulup kalan %10’u sınandığında, test token’larının %7,33’ü eğitimde hiç görülmemiş çıkıyor — farklı kelime biçimlerinin ise %28,99’u. Bu oranlar o örnekleme ve o sözlük tanımına aittir; bütün Türkçe derlemler için sabit değildir.
İki iddia mantıken çelişmiyor ve ikisi birlikte doğru olabilir: seyrek bir sınıflandırıcı güçlü olabilir ve aynı anda kelime düzeyindeki bir sözlük, bir kelimenin çekimli biçimleri arasında kötü genelleme yapabilir. Belirli bir veri kümesinde hangisinin ağır bastığını ise ancak ölçerek öğrenirsiniz. Bu bölümde iki temsil ailesini aynı Türkçe yorum görevinde ve aynı test kümesinde karşılaştıracağız. Yedi satırın hepsinde lojistik regresyon kullanılıyor; ama vektörleştiricilerin ön işlemesi, sözlük eşiği, öznitelik ölçeği ve ek eğitim maliyeti aynı değil. Bu yüzden sonuçlar yöntemlerin bu somut kurulumlarını karşılaştırır; aradaki farkı tek başına “temsil ailesinin etkisi” diye yorumlamayacağız.
3. bölümün kendi karşılaştırması 20 Newsgroups üzerinde yapılmıştı: İngilizce, dengeli, dört sınıf, 2.327 eğitim belgesi. Buradaki Türkçe ürün yorumları veri, görev ve eğitim protokolü bakımından birlikte farklı. Sonuçlar ayrışırsa hangi etkenin ne kadar pay taşıdığını, bu etkenleri tek tek değiştiren karşılaştırmalar olmadan söyleyemeyiz.
Kurulum bilinçli olarak sade. Dört şey bütün satırlarda aynı: eğitim/test bölmesi, LogisticRegression sınıfı, sınıf ağırlıklandırması ve rastgele tohum. Satırdan satıra değişenler ise şunlar: vektörleştiricinin sözlük eşiği, tokenleştirme yolu, özniteliklerin ölçeği ve yoğun temsillerin etiketsiz metin üzerindeki ayrı eğitimi. Bu yüzden skor farklarını temsille birlikte, ona eşlik eden bu tasarım kararları da belirliyor olabilir.
Bir hiperparametreyi sabit tutmak, her temsile adil davranmakla aynı şey değil. Ana karşılaştırmada bütün satırlar C = 1.0 kullanıyor. C, lojistik regresyonun düzenlileştirme (regularization) ayarıdır; scikit-learn’de ceza gücünün tersi olarak tanımlanır, yani C küçüldükçe katsayılar daha sert küçültülür. Belirli bir C’nin ne kadar sert küçülttüğü özniteliklerin ölçeğine bağlıdır. TfidfVectorizer satırlarını varsayılan olarak L2-normalleştirir, yani TF-IDF satırlarında her belge 1,0 normuyla gelir; ortalaması alınmış word2vec ve fastText vektörleri ise normalleştirilmiyor ve normları değişiyor. Aynı C bu iki ölçekte aynı düzenlileştirmeye karşılık gelmeyebilir. Ana karşılaştırmada C hiçbir satır için aranmadı (ileride bir ablasyon — bileşenleri tek tek değiştirip etkisini ölçen bir deney — onu yalnızca iki seyrek satır için ayarlıyor). Daha adil bir tasarım, her temsilin C değerine ve normalleştirme seçeneğine karşılaştırılabilir bir doğrulama bütçesi ayırır; sözlüğün, IDF’in ve embedding’lerin hangi veride eğitildiğini açıkça belirtir ve test etiketlerini seçimde kullanmaz. Buradaki sürüm bunu yapmıyor; bu gerçek bir sınırlama ve önemli olduğu yerde tekrar işaretleniyor.
Deney tasarımı. Karşılaştırılan modellerde test kümesini ve metriği ortak tutmak, aradaki farkı yorumlamayı kolaylaştırır. Temsilin yanında sınıflandırıcı, ayar bütçesi ya da ön işleme de değişiyorsa, görülen skor farkı bunların bileşik etkisidir.
4.2 Problem
Karşılaştırmayı, sınıfları dengesiz ve yazımı değişken Türkçe ürün yorumlarında ikili duygu sınıflandırması görevi olarak kuruyoruz.
Türkçe ürün yorumları, olumlu ya da olumsuz etiketli. Fatih Barmanbay’ın yayımladığı veri kümesi 235.165 yorum içeriyor ve tek bir parquet dosyası olarak dağıtılıyor (Barmanbay 2020). Veri kümesi kartı yorumların çevrim içi toplandığını söylüyor; hangi siteden ve ne zaman toplandığını, etiketlerin nasıl üretildiğini belgelemiyor. Metinler kısa ve gündelik: yazım hataları, eksik Türkçe karakterler, birbirine yapışmış kelimeler taşıyor. Ham da değiller: dağıtılan metnin tamamı küçük harfe çevrilmiş durumda (bunu aşağıda ölçeceğiz).
Bu veri kümesini üç nedenle seçtik:
- Türkçe; 3. bölümün biçimbilim argümanını (Bölüm 3) gerçek kullanıcı metninde sınayabiliyoruz.
- Sınıfları dengesiz — olumlu sınıf 14,8 kat daha büyük — yani uygun değerlendirme metriğini tartışmak zorundayız.
- Altörnekleme yapacak kadar büyük; etiketli eğitim miktarı değiştikçe yöntemlerin nasıl davrandığını karşılaştırabiliyoruz. Bu son karşılaştırma, bu veride ve bu ayarlarda geçerli bir öğrenme eğrisidir.
import hashlib
import pandas as pd
from sklearn.model_selection import train_test_split
URL = ("https://huggingface.co/datasets/fthbrmnby/turkish_product_reviews/"
"resolve/main/data/train-00000-of-00001.parquet")
df = pd.read_parquet(URL).rename(
columns={"sentence": "text", "sentiment": "label"})
print(f"missing text or label {int(df.isna().any(axis=1).sum()):>7,}")
df["text"] = df["text"].astype(str).str.strip()
labels_per_text = df.groupby("text")["label"].nunique()
print(f"empty texts {int(df['text'].eq('').sum()):>7,}")
print(f"texts with both labels {int(labels_per_text.gt(1).sum()):>7,}")
df = df.drop_duplicates(subset="text")### checks before de-duplication
missing text or label 0
empty texts 21
texts with both labels 77
### the raw data
rows as downloaded 235,165
after de-duplication 233,508 (1,657 exact duplicates removed)
label 1 (positive) 218,747 93.7%
label 0 (negative) 14,761 6.3%
İlk üç satır tekilleştirmeden önceki kontroller. Eksik değer yok. 21 satırın metni boş; tekilleştirme bunları tek satıra indiriyor. 77 metin ise iki etiketi birden taşıyor (toplam 297 satır): aynı kısa yorum bir yerde olumlu, bir yerde olumsuz etiketlenmiş. drop_duplicates her metnin dosyada ilk geçtiği satırı tutar; bu dosyada olumlu yorumların hepsi olumsuzlardan önce geldiği için 77 metnin tamamı olumlu etiketiyle kaldı. Bu bölüm o tercihi olduğu gibi bıraktı; 77 metnin 17’si aşağıdaki 50.000’lik altörnekleme giriyor. Kendi verinizde çelişkili etiketler için politikayı — ilkini tut, hepsini at ya da elle karar ver — açıkça seçin ve raporlayın.
Sınıf sayılarını kaynakla karşılaştırabiliyoruz. Veri kümesi kartı 220.284 olumlu ve 14.881 olumsuz yorum bildiriyor. Metne göre tekilleştirme sonrası sayılar 218.747 ve 14.761; farklar 1.537 ve 120, toplamı da \(1.537 + 120 = 1.657\) — atılan tekrar sayısıyla aynı. Bu eşleşme sayımların tutarlı olduğunu gösterir; tekilleştirmenin hangi kayıtları bıraktığını göstermez. Onu yukarıdaki kontrol gösteriyor.
Kaynak ve belgelenmeyen noktalar. Veri kümesini Fatih Barmanbay derledi (Barmanbay 2020). Lisans bilgisi iki yerde farklı görünüyor: kartın lisans bölümü ve özgün GitHub deposundaki lisans dosyası CC BY-SA 4.0 diyor; Hugging Face sayfasının üstündeki lisans alanında ise “unknown” yazıyor (10 Ekim 2026’da kontrol edildi). CC BY-SA “aynı lisansla paylaş” (ShareAlike) koşulu taşır, yani bu kitabın kendi CC BY 4.0’ından daha kısıtlayıcıdır; veriyi ya da ondan türettiğiniz bir şeyi yeniden dağıtmadan önce özgün depodaki lisansı ve kartı birlikte kontrol edin. Kartın söylemediği üç şey: verinin hangi siteden toplandığı, ne zaman toplandığı ve olumlu/olumsuz etiketinin nasıl türetildiği — yıldız eşiği mi, elle etiketleme mi, başka bir şey mi. Bu son boşluk önemli, çünkü Bölüm 5 tümüyle bu derlemin etiket kalitesi üzerine kurulu ve etiketlerin nasıl üretildiğini bilmeden çalışmak zorunda.
Birebir aynı metnin hem eğitimde hem testte bulunması, özellikle kısa yorumlarda, ezberlenmiş bir cevabın genelleme diye puanlanmasına yol açabilir. Bu yüzden bu deneyde metne göre tekilleştirme bölmeden önce yapıldı; 1.657 tekrar dosyanın yalnızca %0,7’si. Bu adım gerekli ama tek başına yeterli değil: şablondan üretilmiş ya da birbirine çok benzeyen metinler elemeden geçebilir, aynı metnin farklı etiketler taşıdığı durumlar da ayrıca karar ister. Seçtiğiniz tekilleştirme politikasını veri kümesiyle birlikte raporlayın.
Ardından tekilleştirilmiş 233.508 yorumdan sınıf oranını koruyan (tabakalı, stratified) 50.000 yorumluk bir altörneklem alıp onu yine tabakalı olarak 80/20 bölüyoruz:
sub, _ = train_test_split(df, train_size=50_000,
stratify=df["label"], random_state=42)
train, test = train_test_split(sub, test_size=0.2,
stratify=sub["label"], random_state=42)
def fingerprint(frame):
rows = ",".join(map(str, sorted(frame.index)))
return hashlib.sha256(rows.encode()).hexdigest()[:12]
for name, part in [("train", train), ("test", test)]:
pos = int(part["label"].sum())
print(f"{name:<6} {len(part):>7,} {pos:>7,} positive "
f"{len(part) - pos:>6,} negative rows {fingerprint(part)}")### the split (stratified, seed 42)
train 40,000 37,471 positive 2,529 negative rows 8205c2be5ebf
test 10,000 9,368 positive 632 negative rows 634cdb3bb002
rows sütunu, seçilen satırların ham dosyadaki sıra numaralarından hesaplanan bir özettir. Kendi koşunuzda aynı 12 karakteri görüyorsanız aynı satırları seçmişsiniz demektir. Sınıf toplamları bunu göstermez; aynı toplamları veren başka pek çok bölme vardır.
Bu bölme hakkında iki uyarı.
Bölmenin yeniden üretimi. Bu bölümün ilk sürümü bölmeyi yalnızca “42 tohumuyla tabakalı” diye kaydetmişti. Bu ifade bir prosedürü adlandırmaz; bir prosedür ailesini adlandırır ve ailenin üyeleri birbirini tutmaz: örneklemenin hangi çağrıyla, hangi sırayla ve kaç aşamada yapıldığı belli değildir. Yukarıdaki iki çağrı sonradan geri kazanıldı; hikâyesi Bölüm 12 içinde. 50.000, 40.000 ve 10.000 sayıları ile bigram vektörleştiriciden çıkan 101.659 öznitelik güçlü tanılama işaretleridir — orada makul bir alternatif kurgunun 101.659 değil 100.350 öznitelik verdiğini göreceksiniz — ama aynı satırları seçtiğinizin kanıtı değildir. Kanıt, satır özetinin ya da tam örnekleme kodunun tutmasıdır. Bölüm 11 aynı kaynaktan aynı tohumla örneklem çektiği hâlde farklı 50.000 satır elde etti.
Test kümesi ve seçim. Aşağıdaki her sayı aynı 10.000 test yorumundan okunuyor: yedi temsil, dokuz eğitim boyutu, bir melez model, üç tanılama. Bu sonuçları keşif amaçlı okuyun: bir yöntemi ya da kesişim noktasını bu satırlardan seçip yine aynı satırlarda tarafsız bir nihai skor bildiremezsiniz. Gerçek işte train’i bir kez daha bölün, seçimi o doğrulama diliminde yapın ve test kümesini yalnızca son değerlendirmede kullanın. Bölüm 12 bunu yapacak ve neden zorunda kaldığını da söyleyecek.
50.000 yorumluk altörneklem bir kolaylık, zorunluluk değil: deney süresini kısaltıyor. Aynı 10.000 test yorumunu tutup modelleri geri kalan 223.508 yorumun tamamında eğittiğimizde sıralama değişmiyor ve bütün satırlar kazanıyor (macro-F1, tek koşu): bag-of-words 73,51 → 74,50; TF-IDF 71,95 → 73,00; bigram TF-IDF 76,21 → 76,69; karakter TF-IDF 70,39 → 71,12; word2vec ortalaması 61,39 → 62,89; fastText ortalaması 61,36 → 62,84; doc2vec 55,13 → 61,99.
4.3 İlk skorun sakladığı sınıf hatası
Yöntemleri karşılaştırmadan önce, dengesiz bir test kümesinde doğruluğun hangi hataları görünmez kılabildiğini, hep çoğunluk sınıfını seçen en basit kuralla göstereceğiz.
Her yoruma “olumlu” deyin. Metne hiç bakmayın.
### the majority-class baseline
accuracy 93.68%
Yalnızca “olumlu” tahmini veren bu kural, yorum metnini hiç kullanmadan %93,68 doğruluk elde eder; çünkü test kümesinin %93,68’i olumludur. Bu skor, kuralın olumsuz yorumları bulup bulamadığını göstermez. Onu karışıklık matrisi (confusion matrix) gösterir:
### majority baseline, in full
predicted neg predicted pos total
actual neg 0 632 632
actual pos 0 9,368 9,368
precision (neg) undefined — it never predicts negative
recall (neg) 0.0% — it finds none of the 632
F1 (neg) 0.00 — 2TP / (2TP + FP + FN) = 0 / 632
F1 (pos) 96.74
macro-F1 48.37
Macro-F1, sınıf başına F1 skorlarının eşit ağırlıklı ortalamasıdır; büyüklüğüne bakmaksızın her sınıfa aynı ağırlığı verir. Çoğunluk kuralı olumsuz sınıfta F1 = 0 aldığı için macro-F1’i 48,37’de kalır. %93,68’lik doğruluğun gizlediği eksiklik böylece görünür olur. Gerçek bir sistemde kullanılacak karar metriğini ise hata maliyetlerine göre ayrıca seçmek gerekir.
Demek ki bu veri kümesinde doğruluk tek başına karar metriği olamaz. Peki yerine ne geçiyor ve yerine geçen ölçüt neden aynı sorunu taşımıyor?
Tek bir sınıf için, \(TP\) doğru pozitif, \(FP\) yanlış pozitif ve \(FN\) yanlış negatif sayısıyla:
\[ \text{precision} = \frac{TP}{TP + FP}, \qquad \text{recall} = \frac{TP}{TP + FN}, \qquad F_1 = \frac{2 \cdot \text{precision} \cdot \text{recall}}{\text{precision} + \text{recall}} = \frac{2\,TP}{2\,TP + FP + FN} \]
\(F_1\), precision (kesinlik) ile recall’un (duyarlılık) harmonik ortalamasıdır. İkisinden biri sıfıra indiğinde \(F_1\) de sıfır olur: precision 1,00 ve recall 0,00 ise aritmetik ortalama 0,50, \(F_1\) ise 0,00’dır. Bu özellik, bir sınıftaki kaçırmaların tek bir yüksek precision değeriyle gizlenmesini önler.
Sıfır paydaya dikkat edin. Sınıf hiç tahmin edilmediyse (\(TP + FP = 0\)) precision tanımsızdır; \(F_1\) ise sayımlarla yazılan ikinci biçimden yine hesaplanır. \(F_1\) ancak \(TP = FP = FN = 0\) olduğunda, yani sınıfın ne gerçek ne tahmin edilmiş örneği varken tanımsız kalır; scikit-learn o durumda ne döndüreceğini zero_division argümanından okur.
Macro-F1 ardından bu skorların sınıflar üzerinden ortalamasını alır:
\[ \text{macro-}F_1 = \frac{1}{K}\sum_{k=1}^{K} F_1^{(k)} \]
Çoğunluk baseline’ında olumsuz sınıf için \(TP = 0\), \(FP = 0\) ve \(FN = 632\) olduğundan \(F_1^{(\text{neg})} = 0/632 = 0\) ve
\[ F_1^{(\text{pos})} = \frac{2 \cdot 0{,}9368 \cdot 1{,}0}{0{,}9368 + 1{,}0} = 0{,}9674, \]
dolayısıyla macro-F1 \(= (0 + 0{,}9674)/2 = 0{,}4837\).
Kütüphaneniz hangi F1’i bildiriyor? Tek başına “F1” belirsizdir; scikit-learn’de bunu average argümanı belirler. İki sınıf için varsayılan olan average="binary" yalnızca 1 numaralı sınıfın F1’ini verir — burada bu çoğunluk sınıfı olan olumlu sınıftır, yani çoğunluk kuralı 96,74 alır. average="micro" bölmeden önce bütün sayımları havuzda toplar; bütün sınıfların dâhil edildiği tek etiketli sınıflandırmada bu, doğruluğa eşittir (93,68). average="weighted" her sınıfın F1’ini o sınıfın örnek sayısıyla ağırlıklandırır; bu sınıf dağılımında 90,62 verir. Sınıflara eşit ağırlık veren average="macro" ise 48,37’dir. Argümanı her zaman açıkça yazın.
Doğruluk örneklere, macro-F1 sınıflara eşit ağırlık verir. Olumsuz yorumların yalnızca %6,32 olduğu bir test kümesinde herkese “olumlu” demek %93,68 doğruluk verir, ama hiçbir şikâyeti yakalamaz. Ürün yorumlarını önceliklendiren (triage) bir sistemde kaçırılan şikâyetin ve yanlış alarmın maliyetini ayrıca belirlemek gerekir. Macro-F1 burada iki sınıfa eşit ağırlık veren bir karşılaştırma metriğidir; olası tek ürün metriği değildir.
Aşağıdaki her modelde class_weight="balanced" kullanılıyor. Bu ayar sınıf ağırlıklarını eğitim kümesindeki sınıf sayılarının tersiyle belirler. Buradaki 37.471 olumlu ve 2.529 olumsuz eğitim örneğinde bir olumsuz örneğin kayıptaki sınıf katsayısı, bir olumlu örneğinkinin yaklaşık 14,8 katıdır. Bu, tek tek örneklerin gradyan büyüklüklerinin de aynı oranı taşıdığı anlamına gelmez; gradyan özniteliklere ve tahmin edilen olasılığa da bağlıdır. Ağırlıksız kurulumun etkisini bu bölüm ölçmedi; 2. alıştırma bunu ölçmenizi istiyor.
İkisini birbirine karıştırmayın: macro-F1’i manşet metrik olarak seçmek ile eğitim kaybını sınıf frekansına göre ağırlıklandırmak iki ayrı tasarım kararıdır. Biri değerlendirmenin neyi önemsediğini, öteki eğitimin neyi önemsediğini belirler; birini seçmek ötekini otomatik olarak getirmez. Dengeli sınıf ağırlıkları güçlü bir varsayılan tercihtir, ama ağırlıksız, ağırlıklı ve eşik ayarlanmış varyantları doğrulama kümesinde karşılaştırın.
Bu bölümde yöntemleri karşılaştırırken başlıca özet skor olarak macro-F1’i kullanacağız; doğruluğu da bağlam sağlaması için raporlayacağız. Tablolarda iki sütunun nasıl ayrıştığına dikkat edin. Macro-F1 evrensel bir çözüm değil: yorumları işleyen gerçek bir sistemde olumsuz sınıfın recall’u, belirli bir yanlış alarm bütçesindeki precision ya da beklenen iş maliyeti daha doğrudan karar metrikleri olabilir.
4.4 Türkçeyi token’lara ayırmak ve oradaki tuzak
Sayım ve embedding modellerinden önce, ikisinin de kullanacağı ön işleme kararlarını tanımlıyoruz. 2. bölümde değinilen Türkçeye özgü küçük harf dönüşümünü (Bölüm 2) bu veri üzerinde inceleyecek, ardından tokenizer’ın hangi işaretleri koruyup hangilerini attığını göstereceğiz. Dönüşümün ayrıntıları Türkçe NLP bölümünde (Bölüm 16).
"IYI".lower() # → 'iyi'
"İYİ".lower() # → 'i̇yi̇' (üstünde fazladan birleştirici nokta olan bir i)Türkçede noktalı i/İ ile noktasız ı/I ayrı harflerdir ve farklı kelimeleri ayırır. Doğru yazılmış Türkçe metinde küçük harfe çevirirken I → ı ve İ → i eşlemesi gerekir; bu, Unicode standardının tanımladığı ama varsayılanın uygulamadığı dile özgü uyarlamalardan biridir. Python’ın str.lower() metodu Unicode’un varsayılan — yani dilden bağımsız — eşlemesini uygular ve yerel ayara göre değişmez: I için i, İ için ise i ile bir birleştirici nokta (U+0307) üretir. ASCII klavyeyle yazılmış bir metinde yazarın hangi harfi kastettiğini ise bu eşleme tek başına belirleyemez; o sınıra aşağıda döneceğiz.
TR_LOWER = str.maketrans({"I": "ı", "İ": "i"})
def tr_lower(s):
return s.translate(TR_LOWER).lower()
tr_lower("IYI") # → 'ıyı'
tr_lower("İYİ") # → 'iyi'### the same string, two lowercasing rules
str.lower() tr_lower()
"IYI" iyi ıyı
"İYİ" i̇yi̇ iyi
Varsayılan işlem, doğru yazılmış IYI ile İYİ’yi Türkçedeki küçük harf karşılıklarına çeviremez: IYI’yı iyi yapar, İYİ’de ise üstte birleştirici nokta bırakır. İkisi de hata vermeden çalışır ve tokenleştirmeyi, sözlük eşleşmesini bozabilir. Bu deneyin ana skorunda ise iki küçük harf yordamı arasında fark ölçülmedi, çünkü dağıtılan veri zaten küçük harfli (1. raunt tablosunun altında göreceksiniz); önceden oluşmuş birleştirici nokta hasarı da ayrı bir onarım adımı ister. Büyük-küçük harf dönüşümü dile bağlıdır; dile özgü küçük harf politikası da ön işleme ve tokenizer (tokenlaştırıcı) sözleşmesinin bir parçasıdır. (Buradaki işlem küçük harfe çevirmedir; Unicode’un casefolding’i ise büyük-küçük harften bağımsız eşleştirme için tasarlanmış akraba ama ayrı bir işlemdir ve onun da kendi Türkçe uyarlaması vardır.) Bir sınırı da baştan söyleyelim: tr_lower doğru yazımı varsayar. İngilizce klavyeyle yazılmış bir kullanıcı metninde IYI pekâlâ “İYİ” demek olabilir ve tr_lower onu ıyı yaparak yeni bir hata üretir. ASCII’leştirilmiş metin için gereken şey Türkçe karakter geri kazanımıdır (deasciification; bkz. Bölüm 16.2).
Yerel ayara ve bağlama duyarlı harf eşlemeleri başka dillerde de var: Yunancada kelime sonundaki sigma küçük harfe σ değil ς olarak çevrilir. Almancadaki ß ise başka bir işlemin konusudur: "ß".lower() onu değiştirmez; ß ile ss eşitlemesini casefolding yapar ("ß".casefold() → ss). İngilizce bir eğitim yazısındaki “küçük harfe çevir gitsin” adımı bu yüzden başka dillere olduğu gibi taşınamaz; ama bu örnekleri Türkçedeki I/İ sorununun birebir aynısı da saymayın.
Türkçe küçük harf dönüşümünden sonra kullandığımız basit token deseni, seçilen küçük harflerden oluşan kesintisiz dizileri çıkarır:
import re
TOKEN_RE = re.compile(r"[a-zçğıöşü]+")
def tokenize(s):
return TOKEN_RE.findall(tr_lower(s))Bu desen yalnızca listelenen harfleri tutuyor: noktalama, rakam ve emoji tümüyle düşüyor; şapkalı harfler (â, î, û) ve birleştirici işaretler ise token’ı bölüyor. Örneğin hâlâ ya da kâr tek token olarak korunmuyor. Ürün yorumlarında !!!, 5/5 ya da bir emoji pekâlâ duygu taşıyabilir; bu deney onları modellemiyor. Bu sadeleştirmelerin sınıflandırma skoruna etkisi ölçülmedi; kendi derleminizde alternatif desenleri karşılaştırın.
Bu tokenizer’la eğitim derlemi şöyle görünüyor:
### the training corpus, 40,000 reviews
tokens 903,190
distinct word forms 74,317
hapax (seen exactly once) 43,579 58.6% of all forms
mean review length 22.6 tokens
median 19
95th percentile 56
longest 296
74.317 farklı biçimin 43.579’u yalnızca bir kez geçiyor; kalan 30.738 biçim en az iki kez görülmüş. min_df=2 sonrasında vektörleştiricinin ise 30.195 sütunu var. Aradaki 543 biçimi tek tek saydık: hepsi derlemde iki ya da daha fazla kez geçen ama bütün geçişleri tek bir belgenin içinde kalan biçimler. min_df derlem frekansını değil, belge frekansını sayar.
Sözlüğün %58,6’sı tam olarak bir kez geçiyor. 3. bölümün Türkçe Wikipedia örnekleminde bu oran %50,0’dı (Bölüm 3). İki derlemin konusu, belge uzunluğu ve ön işlemesi farklı olduğu için farkı yalnızca yazım hatalarına bağlayamayız; kullanıcı metnindeki yazım değişkenliği olası etkenlerden biridir.
Kelime biçimlerini ilk beş karakterlerine göre gruplarsanız biçim çeşitliliği gözle görülür hâle geliyor:
### distinct word forms sharing a five-character prefix
kulla 895 forms kullanışlı, kullanıyorum, kullandım, kullanımı, kullanım, ...
bekle 285 forms beklediğimden, beklediğim, beklemiyordum, beklemeyin, ...
çalış 247 forms çalışıyor, çalışma, çalışan, çalışması, çalışırken, ...
çıkar 209 forms çıkarıyor, çıkar, çıkartıyor, çıkarmıyor, çıkardı, ...
düşün 195 forms düşünüyorum, düşünmeden, düşünenlere, düşünen, ...
bag-of-words (kelime torbası) — bir belgenin hangi kelimeleri içerdiğini sayar, geliş sıralarını unutur. “kalite iyi fiyat kötü” ile “kalite kötü fiyat iyi” aynı belge hâline gelir. ↩︎
Beş karakterlik kulla ön eki bu derlemde 895 farklı biçimde görülüyor. Bu grup tek bir kökün 895 çekimi değildir: çekimleri, türetimleri ve yazım varyantlarını birlikte içerir. Bir bag-of-words modelinde eğitim sözlüğüne giren her biçim ayrı bir sütun olur (min_df=2 ile yalnızca tek bir yorumda geçen biçimler hiç sütun olmuyor; doğrudan atılıyorlar). kullanışlı için öğrenilen katsayı kendiliğinden kullanıyorum sütununa aktarılmaz; aynı belgede geçen başka öznitelikler ve düzenlileştirme ise modelin genellemesini yine etkiler.
Beş karakterlik ön ek, Türkçedeki biçim çeşitliliğini görünür kılan kaba bir incelemedir; kök ya da biçimbirim çözümlemesi değildir. kulla grubunda kullanışlı (sıfat), kullanım (isim) ve kullanıcı (isim) yan yana duruyor; aynı ön ek yazım hatalarını da topluyor. Dolayısıyla bu tablo, gerçek bir kök ailesinin kaç sütuna dağıldığını ölçmez. O niceliği saptamak için biçimbilimsel çözümleme ve yazım varyantlarının ayrıca incelenmesi gerekir; çözümleme klasik olarak sonlu durum dönüştürücüleriyle (finite-state transducers) yapılır (Oflazer 1994). Türkçe biçimbilimsel çözümleyiciler ve kullanımları için bkz. Bölüm 16.3 ve Bölüm F.2.
895 biçimlik ön ek grubu, kelime düzeyinde öznitelik sayısının nasıl büyüyebildiğini gösteren bir işarettir. Bu çeşitliliğin kapsamayla ve sınıflandırma skoruyla ilişkisini aşağıda ayrı ayrı inceleyeceğiz.
4.5 1. raunt — 2. bölümün yöntemleri
Değerlendirme metriğini seçtik ve Türkçe küçük harf dönüşümünü açıkça tanımladık. Veride daha önce oluşmuş birleştirici nokta hataları ise hâlâ duruyor; onlara tablonun altında döneceğiz. Şimdi 2. bölümün dört sayım temsilini (Bölüm 2) aynı sınıflandırıcıyla karşılaştıralım.
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
PAT = r"[a-zçğıöşü]+"
# lowercase=False + preprocessor=tr_lower: aksi hâlde scikit-learn Python'ın
# str.lower()'ını çağırır ve yukarıda uyardığımız hatayı biz yaparız
LOC = dict(preprocessor=tr_lower, lowercase=False)
schemes = {
"bag of words": CountVectorizer(min_df=2, token_pattern=PAT, **LOC),
"tf-idf": TfidfVectorizer(min_df=2, sublinear_tf=True, token_pattern=PAT, **LOC),
"tf-idf 1-2 gram": TfidfVectorizer(min_df=2, sublinear_tf=True,
ngram_range=(1, 2), token_pattern=PAT, **LOC),
# ayrı öznitelik çıkarma yolu: token_pattern kullanılmaz, min_df de farklı
"tf-idf char_wb 3-5": TfidfVectorizer(min_df=3, sublinear_tf=True,
analyzer="char_wb", ngram_range=(3, 5), **LOC),
}
clf = LogisticRegression(max_iter=2000, class_weight="balanced", random_state=42)### round 1: counting
accuracy macro-F1 F1(neg) dims fit
majority baseline 93.68 48.37 0.00 — —
bag of words 92.14 73.51 51.30 30,195 0.7 s
tf-idf 90.07 71.95 49.41 30,195 0.5 s
tf-idf 1-2 gram 92.57 76.21 56.47 101,659 1.0 s
tf-idf char_wb 3-5 88.63 70.39 47.14 94,939 3.3 s
Tablodaki satırlar aynı eğitim/test bölmesini ve aynı sınıflandırıcıyı kullanıyor; ama üç noktada birbirlerinden ayrılıyorlar.
Karakter satırı aynı tokenizer’dan geçmiyor. scikit-learn’de token_pattern yalnızca analyzer="word" iken kullanılır; char_wb onu tümüyle yok sayar ve kendi karakter akışını işler. Yani karakter satırı kelime satırlarından yalnızca özniteliklerin ayrıntı düzeyi (karakter mi, kelime mi) bakımından değil, öznitelik çıkarma yolunun kendisi bakımından da ayrılıyor:
### the same string through the two analyzers
input: "5/5 harika!! ürün çok i̇yi 👍"
analyzer="word", token_pattern=[a-zçğıöşü]+
['harika', 'ürün', 'çok', 'i', 'yi']
— 5/5, !!, emoji düştü; birleştirici nokta "i̇yi"yi ikiye böldü
analyzer="char_wb", ngram_range=(3, 5) (3-gram'ların ilk birkaçı)
[' 5/', '5/5', '/5 ', ' ha', 'har', 'ari', 'rik', 'ika', 'ka!', 'a!!', '!! ', ...]
— rakam, eğik çizgi, ünlem ve boşluklar öznitelik olarak duruyor
Dolayısıyla karakter satırının skor farkı, karakter öznitelikleriyle birlikte bu ön işleme seçimini de yansıtıyor olabilir: char_wb kelime token desenini uygulamıyor; rakamı, noktalamayı ve boşluğu farklı işliyor. Bu bölümün ilerisinde karakter n-gram’larından çıkarılan sonuçları okurken bunu aklınızda tutun.
Karakter şeması min_df=3 kullanıyor; üç kelime şeması ise min_df=2. Savunulabilir bir tercih — karakter n-gram sayıları patlar — ama yine de bir tercih; taranmadı ve bu bölüm diğer ayarın ne yapacağını ölçmedi.
Buradaki fit sütunu ile bölümün sonuna doğru gelen maliyet tablosundaki build the representation sütunu aynı adımı ölçmüyor. Süreleri beşer kez yeniden ölçtüğümüzde eğitim metnini vektörleştirmek bigram şemasında 0,82–0,90 sn, karakter şemasında 2,68–2,79 sn; sınıflandırıcıyı eğitmek ise sırasıyla 0,09–0,10 sn ve 0,38–0,39 sn sürdü. İki tablo arasındaki farklar (1,0 sn’ye karşı 0,9 sn; 3,3 sn’ye karşı 2,9 sn) sınıflandırıcının eğitim süresiyle tutarlı: fit vektörleştirme ile sınıflandırıcı eğitimini birlikte, maliyet tablosu yalnızca vektörleştirmeyi kapsıyor. Tablolardaki süreler tek koşudan geliyor ve melez modelin maliyet hesabı ileride ikinci seti kullanıyor; hepsini bu makineye ait yaklaşık değerler olarak okuyun.
Yukarıdaki lowercase=False satırı sonradan eklendi, çünkü ilk sürüm tam da bu bölümün iki kısım önce uyardığı hatayı yapıyordu. Sonra iki sürüm de ölçüldü ve 1. raunt tablosu bayt bayt aynı çıktı.
Sebebi derlemin kendisi: tekilleştirilmiş 233.508 yorumun 37.076.865 karakteri içinde tek bir büyük harf yok (str.isupper() ile sayıldı). Bu gözlem, dağıtılan metnin önceden küçük harfe çevrilmiş olmasıyla tutarlı; hangi araçla ve ne zaman çevrildiğini veri kartı belgelemiyor. Yani iki yol burada aynı sonuca varıyor.
Bu, derlemin temiz olduğu anlamına gelmiyor. U+0307 (COMBINING DOT ABOVE), üzerinde çalıştığımız 50.000 yorumluk altörneklemin 4.194 belgesinde, yani %8,4’ünde duruyor ve her seferinde bir i harfinin ardından geliyor. Varsayılan Unicode küçük harf dönüşümü İ için tam bu diziyi üretir. Verinin önceki işleme adımları belgelenmediği için kaynağını kesinleştiremeyiz; gözlem böyle bir dönüşümle tutarlı. Bizim [a-zçğıöşü]+ desenimiz birleştirici işareti kelime karakteri saymadığı için o belgelerde tavsiye, tavsi + ye diye ikiye bölünüyor. Sözlüğe etkisini ölçtük: işareti silip eğitim metnini yeniden vektörleştirince 30.195 sütunluk sözlük 29.823’e iniyor. 595 sütun yalnızca bu parçalanma yüzünden var (alişveri, alabi gibi); onarımdan sonra da daha önce tek parça hâlinde hiç görülmemiş 223 biçim sözlüğe giriyor. Bölüm 11 aynı hasarı kendi örnekleminde bir kümeleme sonucu olarak yeniden keşfediyor ve satır satır ölçüyor. tr_lower metinde zaten bulunan birleştirici noktayı silmez — onarım, size verilen metinden bu işareti silmektir; küçük harfe farklı biçimde çevirmek değil. Onarımın skorlara etkisini 7. alıştırma ölçmenizi istiyor.
Bunu neden yine de düzelttik? Çünkü kodu kopyalayan okurun derlemi böyle olmayacak. Farkın küçük bir gösterimi:
'İYİ'.lower() -> 'i̇yi̇' -> [a-zçğıöşü]+ ile ['i', 'yi'] ikiye bölünür
'IYI'.lower() -> 'iyi' -> ['iyi'] yanlış birleşir
Aynı uyarı analyzer="char_wb" için de geçerli. Karakter n-gram’ları “dilden bağımsız” diye tanıtılır, ama küçük harfe çevirme adımı hâlâ yerel ayara bağlıdır.
Bu tabloda üç şey dikkat çekiyor.
F1 score / macro-F1 (F1 skoru) — F1, tek bir sınıf için precision ile recall’un harmonik ortalamasıdır. Macro-F1, her sınıfın F1 skorunu eşit ağırlıkla ortalar; böylece nadir bir sınıf, yaygın olanı kadar sayılır. Bu deneyde, çoğunluk kuralının olumsuz sınıfta F1 = 0 almasını görünür kılan metrik budur. ↩︎
Doğruluk ile macro-F1 çoğunluk kuralı konusunda ayrışıyor. Dört sayım yönteminin doğruluğu, çoğunluk kuralının %93,68’inin altında; buna karşılık macro-F1’de onun 22 ila 28 puan üstündeler. (Dört yöntemin kendi arasında iki metrik aynı sırayı veriyor: örneğin bag-of-words’ün doğruluğu da macro-F1’i de TF-IDF’inkinden yüksek.) Burada değerlendirilen modeller, azınlığı görmezden gelmenin getirdiği doğruluğun bir kısmını verip karşılığında olumsuz sınıfta recall kazanıyor. Bu kurulumda bir yöntemi yalnızca doğruluğa göre seçerseniz çoğunluk kuralı güçlü bir aday görünür. Bu bir yasa değil: başka eşikler ve eğitim ayarlarıyla hem doğruluğu hem olumsuz sınıf başarısını yükseltmek mümkündür; o seçenekleri burada sınamadık.
Bu kurulumda ham sayımlar TF-IDF’in önünde. Akla gelen ilk açıklama IDF olur: yorumlar ortalama 22,6 token, çoğu kelime belgede bir kez geçiyor, dolayısıyla IDF sık geçen duygu kelimelerinin — güzel, iyi, tavsiye — ağırlığını düşürüyor olabilir. Bu bir hipotez; sınanabilir de, çünkü CountVectorizer ile TfidfVectorizer arasında aynı anda üç şey değişiyor: IDF ağırlıklandırması, altdoğrusal terim frekansı (sublinear_tf=True; bir \(c\) sayımını \(1 + \log c\) ile değiştirir) ve TfidfVectorizer’ın varsayılan olarak uyguladığı L2 satır normalleştirmesi. Üçünü ayrı ayrı açıp kapatalım — aynı sözlük, aynı sınıflandırıcı, aynı C = 1.0:
### one change at a time, unigram word features, min_df=2
idf log-TF norm accuracy macro-F1 F1(neg)
raw counts (= "bag of words") no no none 92.14 73.51 51.30
counts + L2 no no L2 88.07 69.57 45.85
log-TF + L2 no yes L2 88.37 70.00 46.53
counts + idf + L2 yes no L2 90.20 72.16 49.74
log-TF + idf, no norm yes yes none 92.67 71.83 47.61
log-TF + idf + L2 (= "tf-idf") yes yes L2 90.07 71.95 49.41
Sonuç, ilk açıklamayı desteklemiyor. C = 1.0 sabitken ham sayımlara L2 satır normalleştirmesi eklemek macro-F1’i 73,51’den 69,57’ye düşürüyor (3,94 puan); IDF onun üstüne eklendiğinde skor 72,16’ya çıkıyor. Yani ilk fark yalnızca IDF’ten kaynaklanmıyor; “TF-IDF burada IDF yüzünden geride kaldı” cümlesi deneyin gösterdiği şey değil. Bu, normalleştirmenin kendiliğinden zararlı olduğu anlamına da gelmiyor: etkisi C ile birlikte değerlendirilmeli.
Olası açıklama, C’yi ayarlamamış olmamız. L2 normalleştirilmiş satırların normu 1, ham sayım satırlarınınki ise belge uzunluğuyla büyüyor; sabit bir C = 1.0 bu yüzden iki temsile farklı bir etkin düzenlileştirme uyguluyor — bu bölümün yoğun aile için baştan işaretlediği çekincenin aynısı, şimdi seyrek ailenin içinde. Her iki temsile aynı küçük ayar bütçesini verelim: 40.000 eğitim belgesini modeli eğitmek (fit) için 32.000 ve doğrulama için 8.000 olarak bölüp C’yi doğrulama diliminde seçiyor, sonra seçilen C ile modeli 40.000 belgenin tamamında yeniden eğitip test kümesinde ölçüyoruz:
### C chosen on a validation split carved out of train (32,000 fit / 8,000 val)
best C on validation test macro-F1
raw counts 1.0 73.51
tf-idf 10.0 74.71
Seçim adımını açık yazıyoruz, çünkü sonucu değiştiriyor: tablodaki test skorları, seçilen C ile 40.000 belgenin tamamında yeniden eğitilmiş modellere ait (32.000 belgelik modeller aynı test kümesinde 73,65 ve 73,83 alıyor). Bu test kümesi bölümde daha önce de kullanıldı; dolayısıyla bu satırlar ilk kez açılan, bağımsız bir test sonucu değil.
Sıralama tersine dönüyor: doğrulamada seçilmiş C ile TF-IDF 74,71, ham sayımlar 73,51 macro-F1 alıyor. Bu 1,2 puanlık farkın bu test kümesinde ne kadar sağlam olduğunu, iki modelin aynı 10.000 test yorumundaki tahminlerini eşleştirerek ölçtük. 10.000 eşleştirilmiş yeniden örneklemede (paired bootstrap) macro-F1 farkının %95 aralığı 0,42 ile 1,99 puan arasında kalıyor; yalnızca TF-IDF’in doğru bildiği 151, yalnızca ham sayımların doğru bildiği 80 yorum var (hata oranları için kesin McNemar testi, \(p < 0{,}001\); iki testin farkı 2. rauntta açıklanıyor). Yani fark bu test kümesinin örnekleme gürültüsünden büyük. Aralık tek bir eğitim bölmesine ve tek bir test kümesine ait; başka bir eğitim örnekleminde ne olacağını söylemez. Deneyin gösterdiği şey şu: 1. raunt tablosundaki “ham sayımlar TF-IDF’in önünde” sonucu eşit bir ayar bütçesine dayanamadı; temsilin değişmez bir özelliği değil, paylaşılan ve ayarlanmamış bir C’ye bağlıydı. Tablo yanlış değil — orada gerçekten ölçülen bu — ama ondan çıkarılacak ders “kısa metinde TF-IDF geride kalır” değil: eşit ayar bütçesi verilmeden yapılan bir temsil karşılaştırması, ölçmek istediğiniz şeyi ölçmeyebilir.
bigram (ikili n-gram) — tek bir birim olarak sayılan kelime çifti; böylece iyi değil, iyi’den ayırt edilebilir. ↩︎
Bu kurulumda kelime unigram + bigram TF-IDF’i, yalnız unigram TF-IDF’inden 4,26 macro-F1 puanı, ham sayımlardan 2,70 puan yüksek. (Bölümün en büyük farkları bu değil: iki aile arasındaki fark 14,8 puan, 250 etikette embedding’lerin sayım yöntemlerinin önüne geçtiği fark da 14,6 puan. Bu ise etiket bütçesi sabitken, sayım ailesinin içinde ölçülen en büyük fark.) Bigram’lar iyi değil, güzel değil gibi yerel dizileri ayrı öznitelik olarak tutar; bu, ayrı bir kelimeyle kurulan olumsuzlamayı yakalamaya yardımcı olabilir. Aynı bigram’lar çok kelimeli duygu kalıplarını, ürün adlarını ve birlikte geçen sözcük öbeklerini de yakalıyor. Türkçede olumsuzluğun bir kısmı ise ektedir: beğendim ile beğenmedim unigram düzeyinde de ayrı özniteliklerdir. tavsiye etmem ya da memnun kalmadım gibi çiftlerde de olumsuzluk ekte: aşağıdaki tabloda etmem ve kalmadım tek başlarına güçlü olumsuz unigram’lar; bigram oraya tavsiye ya da memnun bağlamını ekliyor. 4,26 puanın ne kadarının hangi olumsuzlama türünden geldiğini bu bölüm ölçmedi; bunu söylemek için hedefli bir hata çözümlemesi ya da ablasyon gerekir.
4.5.1 Model ne öğrendi, kelimelerle
Bu seyrek doğrusal modelde her sözlük özniteliğine bir katsayı karşılık gelir. Katsayıları öznitelik adlarıyla birlikte sıralamak, modelin bu veride ve bu ön işlemeyle hangi özniteliklerle ilişki kurduğunu incelemeye yardım eder; tek bir kelimenin bütün bağlamlardaki etkisini vermez.
### tf-idf + logistic regression, largest coefficients
olumluya doğru olumsuza doğru
gayet +8.04 etmiyorum -8.16
ederim +6.94 değil -6.95
mükemmel +6.13 kötü -6.63
teşekkürler +6.09 etmem -6.35
harika +5.93 beğenmedim -6.21
memnunum +5.84 iade -5.85
güzel +5.48 fakat -5.52
süper +4.98 kalitesiz -5.47
kaliteli +4.32 kalmadım -5.33
Listedeki iki öznitelik dilden çok alanla ilgili görünüyor: iade ve fakat bu modelde olumsuz sınıfla ilişkilenen öznitelikler arasında. iade gerçekleşmiş bir iadeden söz ediyor olabilir; yalnızca iade olasılığından bahsediyor da olabilir. fakat olumlu bir yargıyı olumsuz bir yargıya bağlıyor olabilir. Katsayılar eğitim etiketleriyle koşullu ilişkiyi gösterir; hangi anlatımın geçerli olduğunu örnek yorumları okuyarak denetlemek gerekir. Bu ilişkileri elle yazmadık; 40.000 etiketli yorumdan öğrenildiler.
Bu listeyi ne olduğundan fazlası olarak okumayın. Katsayılar kelimelerin evrensel duygu puanları değil; bu eğitim dağılımında, diğer bütün özniteliklerle birlikte öğrenilmiş genel (global) ilişkilerdir. Tek bir belgede \(j\) özniteliğinin doğrusal karar skoruna katkısı \(x_j \beta_j\)’dir; sabit terim ve diğer özniteliklerin katkıları da toplam skora eklenir, olasılık ise bu toplam skora sigmoid uygulanarak hesaplanır. Genel katsayı listesi modelin neyi öğrendiğini anlatır; tek bir tahminin eksiksiz açıklaması değildir. İkisi ayrı sorulardır.
Yoğun yöntemler sahneye çıktığında bu sütunu aklınızda tutun, çünkü onlar aynı doğrudan kelime → katsayı tablosunu kendiliğinden vermiyor.
4.6 2. raunt — 3. bölümün yöntemleri
Şimdi aynı görevi 3. bölümün üç modeliyle (Bölüm 3) ele alalım. Word2vec, fastText ve doc2vec modelleri 40.000 eğitim yorumunun metni üzerinde, etiketleri kullanmadan sıfırdan eğitildi; ön eğitimli vektör ve test yorumları bu eğitimde kullanılmadı. İleride öğrenme eğrisinde sınıflandırıcı daha az etiket görürken de 40.000 yorumun metninden öğrenilmiş bu sabit temsil kullanılmaya devam ediyor.
from gensim.models import Word2Vec, FastText
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
w2v = Word2Vec(train_tok, vector_size=100, window=5, min_count=2,
sg=1, negative=5, epochs=10, workers=1, seed=42)
ft = FastText(train_tok, vector_size=100, window=5, min_count=2,
sg=1, negative=5, epochs=10, workers=1, seed=42,
min_n=3, max_n=6, bucket=500_000)
d2v = Doc2Vec([TaggedDocument(d, [i]) for i, d in enumerate(train_tok)],
vector_size=100, min_count=2, epochs=20, dm=0,
negative=5, workers=1, seed=42)Yukarıdaki kod yalnızca üç modelin eğitim ayarlarını gösteriyor; belge matrisine giden adımlar şöyle. word2vec için bir belgenin vektörü, sözlükte bulunan token’larının vektörlerinin ortalamasıdır; sözlükte hiç token’ı olmayan belge sıfır vektörü alır. fastText’te ortalamaya belgenin bütün token’ları girer, çünkü model sözlük dışı biçimlere de alt kelime vektörlerinden bir vektör kurar. doc2vec eğitim belgelerinin vektörünü doğrudan öğrenir; test belgelerinin vektörü infer_vector ile, varsayılan ayarlarla çıkarılır. Üç matris de 1. rauntla aynı lojistik regresyona verilir.
### round 2: coordinates
accuracy macro-F1 F1(neg) dims embed train
averaged word2vec 79.92 61.39 34.64 100 14.7 s
averaged fastText 79.64 61.36 34.79 100 31.6 s
doc2vec (PV-DBOW) 71.96 55.13 27.66 100 8.5 s
Bu satırlar, seyrek satırların aksine son hanesine kadar yeniden üretilemiyor. Aynı kodu ve aynı tohumu (42) bu bölüm gözden geçirilirken yeniden koşturduğumuzda word2vec 61,37, fastText 61,29, doc2vec 55,44 macro-F1 verdi. Bölümün notebook’unun sonraki koşuları her seferinde aynı 61,37 ve 61,29 değerlerini verdi; doc2vec ise yine oynadı (55,57, 55,58, 55,54). Nedeni gensim’in içinde: infer_vector her test belgesini Python’ın string hash’iyle tohumlanan bir vektörden başlatıyor ve bu hash, PYTHONHASHSEED sabitlenmedikçe süreçten sürece değişiyor. Yalnızca embedding tohumunu değiştirdiğimizde (beş tohum) word2vec 61,57 ile 62,06, fastText 60,86 ile 61,68 arasında kaldı. Yoğun satırlardaki ondalık farkları bu yayılımla birlikte okuyun.
1. rauntla yan yana:
### both rounds, sorted by macro-F1
tf-idf 1-2 gram 92.57 76.21 56.47 101,659
bag of words 92.14 73.51 51.30 30,195
tf-idf 90.07 71.95 49.41 30,195
tf-idf char_wb 3-5 88.63 70.39 47.14 94,939
averaged word2vec 79.92 61.39 34.64 100
averaged fastText 79.64 61.36 34.79 100
doc2vec (PV-DBOW) 71.96 55.13 27.66 100
majority baseline 93.68 48.37 0.00 —
Bu sırayı genel bir başarı sıralaması olarak okumayın. Satır adları kısa tutuldu; tam hâlleri şunlar: üç yoğun satır bu derlemin 0,9 milyon token’ı üzerinde sıfırdan eğitilmiş, ortalaması alınmış statik vektörler; ön eğitimli değil. Yoğun vektörlerin ölçeği eşitlenmedi ve C hiçbir satır için ayarlanmadı — bir önceki kısımdaki C deneyinin seyrek tarafta yaptığını hatırlayın.
Her satır tek bir bölmeden ve tek bir koşudan geliyor. Test kümesinin örnekleme belirsizliğini ölçmek için iki modelin aynı 10.000 yorumdaki tahminlerini eşleştirip test satırlarını 10.000 kez yeniden örnekledik (eşleştirilmiş bootstrap; her örneklemde iki modelin macro-F1’i de yeniden hesaplanır):
### paired bootstrap on the 10,000 test reviews: macro-F1 difference, 95% interval
tf-idf 1-2 gram - bag of words +2.69 [ +1.60, +3.82]
bag of words - tf-idf +1.56 [ +0.53, +2.55]
tf-idf - tf-idf char_wb 3-5 +1.57 [ +0.59, +2.54]
tf-idf char_wb 3-5 - averaged word2vec +9.01 [ +7.97, +10.01]
averaged word2vec - averaged fastText +0.08 [ -0.60, +0.77]
averaged fastText - doc2vec (PV-DBOW) +5.85 [ +5.02, +6.69]
tf-idf 1-2 gram - averaged word2vec +14.83 [+13.65, +16.01]
Yoğun satırlar yukarıda sözü edilen yeniden koşudan alındı. Aileler arasındaki fark ve seyrek ailenin içindeki komşu farklar bu test kümesinin örnekleme gürültüsünden büyük; word2vec ile fastText arasındaki fark değil. Bu aralıklar yalnızca test örneklemesini kapsar: eğitim bölmesi değişince ne olacağını söylemez, yoğun satırlarda buna bir de eğitim tohumunun yayılımı eklenir. Öğrenme eğrisinde 250 ile 40.000 etiket arasında görülen dalgalanma ise böyle bir belirsizlik aralığı değildir; o noktalar hem eğitim büyüklüğünde hem örneklenen belgelerde farklılaşır.
Hata oranları için ayrı bir test gerekir. McNemar testi iki yöntemin hata oranlarını karşılaştırır, dolayısıyla doğruluk sütunuyla ilgilidir; sıralamanın dayandığı macro-F1 sütunuyla değil. Bölümün ilerisinde düz kelime TF-IDF’i ile ortalaması alınmış fastText’in aynı test belgelerindeki doğru/yanlış durumlarına uygulanan McNemar testi \(\chi^2 = 684{,}2\) veriyor; bu, o iki kurulumun hata oranı farkını destekler. Macro-F1 farkı eşleştirilmiş bir hata sayımı değildir; onun için yukarıdaki gibi eşleştirilmiş bootstrap ya da rastgeleleştirme testi gerekir. Protokolü Dror vd. (2018) ayrıntısıyla anlatıyor; 8. alıştırma bu aralıkları kendi koşunuzda yeniden üretmenizi ve eğitim bölmesi üzerinden genişletmenizi istiyor.
recall (duyarlılık) — gerçekten olumsuz olan yorumlar içinde modelin bulabildiklerinin oranı. Düşük recall, kaçırmaların çokluğuyla ilişkilidir. ↩︎
precision (kesinlik) — modelin olumsuz dediği yorumlar içinde gerçekten olumsuz çıkanların oranı. Düşük precision, yanlış alarmların çokluğuyla ilişkilidir. ↩︎
Bu kurulumda en iyi seyrek temsil, sıfırdan eğitilmiş ortalama-embedding kurulumunun açık farkla önünde. En iyi seyrek yöntemle en iyi yoğun yöntem arasındaki fark 14,8 macro-F1 puanı; olumsuz sınıfta 21,83 F1 puanı — ve bu farkın biçimi de önemli. (Bir rastlantıyı baştan açıklayalım: birkaç satır aşağıda %21,8’lik bir precision değeri geçiyor. İki sayının ilgisi yok — buradaki bir F1 puan farkı, oradaki bir precision.) Ortalaması alınmış word2vec aslında daha çok olumsuz buluyor (%84,2 recall, bigram TF-IDF’in %76,3’üne karşı); ama olumsuz diye işaretlediği yorumların yalnızca %21,8’i gerçekten olumsuz (precision), bigram TF-IDF’te bu oran %44,8. Bunlar test kümesi üzerindeki toplu oranlardır; tek bir yeni tahminin doğru olma olasılığı gibi okumayın.
3. bölümün 20 Newsgroups görevinde de (Bölüm 3) karşılaştırılan seyrek yöntem ortalama statik embedding’in önündeydi. İki farklı veri kümesinde benzer bir sıralama görmek yararlı bir gözlem; ama dil, sınıf yapısı, eğitim miktarı ve ön işleme farklı olduğu için bu iki sonuçtan genel bir belge sınıflandırma kuralı çıkmaz. Bölümün geri kalanı, bu Türkçe yorum kurulumunda etiket miktarı ve hata türleri değiştiğinde sıralamanın nasıl etkilendiğini inceliyor.
Sınırını da açıkça söyleyelim. 2. rauntun üç modeli yalnızca bu derlemin eğitim yorumlarındaki 903.190 token üzerinde sıfırdan eğitildi; Bojanowski vd. (2017) gibi çalışmalar Wikipedia ölçeğindeki derlemlerle çalışıyor. Dolayısıyla yukarıdaki ölçüm şudur: “0,9 milyon token üzerinde sıfırdan eğitilmiş statik embedding’ler, bu kurulumda aynı 40.000 belgeden çıkarılan sayımların gerisinde kaldı” — “statik embedding’ler sayımların gerisinde kalır” değil. Büyük Türkçe derlemlerde önceden eğitilmiş vektörler farklı sonuç verebilir; farkın yönünü ve büyüklüğünü bu bölüm ölçmedi. 13. alıştırmada kendiniz ölçebilirsiniz.
Derlem boyutuna bağlı olmayan şey ise ortalama alma kusuru. kalite iyi fiyat kötü ile kalite kötü fiyat iyi çiftinin (bölümün sonunda göstereceğimiz) 1,0000 kosinüsünü hiçbir eğitim verisi miktarı düzeltmez, çünkü o arıza vektörlerde değil havuzlama adımındadır. Bu bölümün genellenebilir sonucu budur; yukarıdaki sıralama ise yerel bir sonuç.
Yoğun yöntemlerin belirgin biçimde ayrıldığı yer boyut sayısı: belge başına 100 sayı ile 61,39 macro-F1’e karşılık, 101.659 sütunla 76,21.
Boyut sayısını bellek diye okumayın. Bu deneyde yoğun belge matrisinin 100, kelime TF-IDF matrisinin 30.195 sütunu var; buna rağmen ölçülen eğitim matrisi belleği sırasıyla 16,0 MB ve 9,7 MB. Seyrek matris yalnızca sıfır dışı değerleri ve onların indekslerini saklar: ortalama 19,8 sıfır dışı değer taşıyan bir satır 30.195 değil 19,8 değer tutar. Daha az koordinat, bazı yoğun vektör yapılarında — bir en yakın komşu indeksi, yaklaşık en yakın komşu (ANN) araması, bir ağın ilk katmanı — avantaj sağlayabilir; gerçek arama belleğini ve gecikmesini ise seçilen indeks, belge sayısı ve seyreklikle birlikte ölçmek gerekir.
Oranı, hangi seyrek modelle karşılaştırdığınız belirler. Bigram TF-IDF’in 101.659 sütununa göre 100 boyutlu yoğun belge vektörü yaklaşık 1.017 kat, düz kelime TF-IDF’in 30.195 sütununa göre yaklaşık 302 kat daha az koordinat taşır (bölümün ilerisindeki özet tablosunda geçen rakam 302’dir). Bu oranlar tek başına bellek, gecikme ya da ürün mimarisi oranları değildir. Hedef kullanımınızda seyrek erişim, yoğun erişim ve sınıflandırma maliyetlerini ayrı ayrı ölçün.
Yoğun modellerin hatalarının yönüne dikkat edin: bu koşuda ortalaması alınmış word2vec olumsuz yorumların %84,2’sini buluyor — herhangi bir seyrek modelden fazla — ama olumsuz tahminlerinin precision’ı %21,8. Bu yanlış alarm örüntüsü, temsilin ayırt ediciliği kadar class_weight="balanced", karar eşiği ve C seçimiyle de ilişkili olabilir. Sebebi ayırmak için eşik ve ağırlık ablasyonları gerekir.
4.8 Skor farkını anlamak için hata örnekleri
Tablo, bu kurulumda sayım yöntemlerinin daha yüksek skor aldığını gösteriyor; nedenini göstermiyor. Nedenlerin payını ölçmek ayrı deneyler ister. Burada iki yöntemin uyuşmadığı tahminlere, olumsuzlama örneklerine ve temsillerin sınırlarına bakacağız.
İki temsili ele alalım: düz kelime TF-IDF’i (doğruluğu 90,07 olan satır) ve ortalaması alınmış fastText (79,64). Test belgelerinin %84,1’inde aynı etiketi veriyorlar. Ayrıştıkları 1.587 belgede TF-IDF 1.315, fastText 272 kez doğru. (İki sınıf olduğu için iki model ne zaman ayrışsa ikisinden tam olarak biri haklıdır; bu yüzden aradaki 1.315 − 272 = 1.043 belge, ikisinin doğruluk farkının ta kendisidir: 10,43 puan.)
Bu iki sayı bir anlamlılık testi için yeterli. Sezgisi şu: iki yöntem eşit derecede doğru olsaydı, anlaşmazlıklar kabaca yarı yarıya bölünürdü; eşleştirilmiş tahminler üzerindeki McNemar testi (McNemar 1947) bölünmenin yarı yarıdan ne kadar uzak olduğunu sorar ve tam olarak köşegen dışındaki bu sayıları kullanır: \(\chi^2 = (|1315 - 272| - 1)^2 / (1315 + 272) = 684{,}2\), tek serbestlik derecesiyle; yaygın anlamlılık eşiklerinin çok ötesinde. Bu, aynı test kümesinde iki kurulumun hata oranlarının farklı olduğuna güçlü kanıttır; yani doğruluk hakkında bir ifade. Macro-F1 farkının belirsizliği bu testten çıkmaz; onu test satırları üzerinde eşleştirilmiş bootstrap ile ölçtük: fark 10,66 puan, %95 aralığı 9,52 ile 11,77 (fastText tarafı 2. rauntta sözü edilen yeniden koşudan). İki sonuç da yalnızca incelenen iki kurulum ve bu test verisi için geçerli.
Asıl ilginç soru, o 272 örneğin neye benzediği.
### averaged fastText right, tf-idf wrong (gold: positive)
"en guvenli alısveriş sitesi" Türkçe karakterler kısmen düşmüş
"çok hizli ve temi̇z tesli̇mat" kelime ortasında bozuk karakter
"çok sessiz çalışıyor makina ." "makina" — "makine"nin konuşma dilindeki biçimi
### tf-idf right, averaged fastText wrong
"sıkıcı edebi yonu cok zayif" gerçek: olumsuz — fastText olumlu diyor
"koku ne çok kötü ne çok iyi" gerçek: olumsuz — "ne… ne…" yapısı
"cok guzel! kedi bayildi buna" gerçek: olumlu — fastText olumsuz diyor
Bu altı seçilmiş örnek, iki modelin hangi metinlerde ayrışabildiğini gösteriyor: eksik Türkçe karakterler, konuşma dili yazımı ve ne … ne … gibi kapsam ilişkileri. Hangi özniteliğin kararı belirlediği bu listeden çıkmaz; onun için karar katkılarına bakmak, metinde kontrollü değişiklikler yapmak ya da bütün uyuşmazlıkları etiketleyerek çözümlemek gerekir. Eksik karakterli metinler her iki yönde de görünüyor; tek bir açıklama yetmiyor.
İki özelliği bütün uyuşmazlıklarda saydık (yeniden koşudaki fastText modeliyle; orada sayılar 1.323 ve 272). TF-IDF sözlüğünün dışında kalan token’ların payı, yalnızca fastText’in doğru bildiği yorumlarda %9,49, yalnızca TF-IDF’in doğru bildiği yorumlarda %9,48; iki modelin de doğru bildiği yorumlarda ise %6,51. Yani sözlük dışı biçimler uyuşmazlıklarda daha sık, ama hangi modelin haklı çıkacağını ayırmıyor. Ayrışan şey sınıf: yalnızca fastText’in doğru bildiği yorumların %31’i olumsuz (test kümesinin tamamında %6,3), yalnızca TF-IDF’in doğru bildiklerinin %98’i olumlu. Bu, ortalama-embedding kurulumunun daha yüksek recall ve daha düşük precision’la çalışmasıyla tutarlı.
Olumsuzlama örnekleriyle temsilleri doğrudan da sınayabiliriz.
### cosine between a review and its negation
averaged tf-idf
fastText
ürünü çok beğendim / ürünü hiç beğenmedim 0.776 0.193
kesinlikle tavsiye ederim / … tavsiye etmem 0.919 0.474
kargo çok hızlı geldi / kargo çok yavaş geldi 0.943 0.572
fiyatına göre gayet kaliteli / … hiç kaliteli değil 0.892 0.690
bu üründen memnun kaldım / … memnun kalmadım 0.962 0.582
Bu beş karşıt yorum çiftinde ortalaması alınmış fastText’in kosinüsü 0,78–0,96, kelime TF-IDF’inki 0,19–0,69 aralığında. (Aynı çiftlerde word2vec ortalaması da 0,72–0,96 veriyor; yüksek değerler fastText’in alt kelimelerine özgü değil.) Ortalama alma, iki cümlenin paylaştığı kelimelerin katkısıyla, değişen tek kelimenin etkisini azaltabilir. Ama iki temsil farklı ağırlıklar ve farklı vektörler kullanıyor; tablodaki farkın tamamını yalnızca ortalama işlemine bağlayamayız. Yüksek kosinüs, sınıflandırıcının iki yoruma aynı etiketi vereceği anlamına da gelmez; buna aşağıda döneceğiz.
O açıklama nitelikseldi. Hesabını da yapalım, çünkü sonuç bir formül. Bu formül size sabit bir uzunluk eşiği vermiyor — eşik vektörlerin normlarına ve yönlerine bağlı — ama seyrelmenin ortak içerik büyüdükçe nasıl ölçeklendiğini gösteriyor.
Beş kelimelik bir yorumu ve onun yalnızca tek bir kelimede farklılaşan olumsuz hâlini ele alın:
\[ \mathbf{d}_+ = \frac{1}{5}\left(\mathbf{v}_1 + \mathbf{v}_2 + \mathbf{v}_3 + \mathbf{v}_4 + \mathbf{v}_{\text{liked}}\right), \qquad \mathbf{d}_- = \frac{1}{5}\left(\mathbf{v}_1 + \mathbf{v}_2 + \mathbf{v}_3 + \mathbf{v}_4 + \mathbf{v}_{\text{disliked}}\right) \]
Fark şu:
\[ \mathbf{d}_+ - \mathbf{d}_- = \frac{1}{5}\left(\mathbf{v}_{\text{liked}} - \mathbf{v}_{\text{disliked}}\right), \]
Bu \(1/5\)’i okurken dikkatli olun: aynı çarpan ortak kelimeleri de ölçekliyor ve kosinüs ortak bir çarpana duyarsız, dolayısıyla asıl sorun çarpanın kendisi değil. Önemli olan oran — farklılaşan tek vektöre karşı ortak dört vektör. Yorumu yirmi kelimeye uzatın: farklılaşan vektör yine tek, ama ortak vektörlerin sayısı dörtten on dokuza çıkar ve fark vektörü \(1/20\) ile ölçeklenir. İki ortalamanın kosinüsünün 1’e yaklaşması ise garanti değildir: ortak kelimelerin vektör toplamının farklılaşan kelimelere göre baskın olmasına bağlıdır. Ortak katkılar birbirini götürür ya da karşıt yönlere dağılırsa, yorum uzasa da bu sonuç zorunlu olmaz. Yukarıdaki beş örnek, yüksek kosinüsün gerçekleşebildiğini gösteriyor.
Bir alt kelime modelinde buna bir etken daha eklenir: beğendim ile beğenmedim, beğ, eğe, ğen gibi karakter n-gram’larını paylaşır ve bu, vektörlerine ortak katkılar verir. İki kelimenin ayrı tam kelime bileşenleri ve ayrışan n-gram’ları da vardır; dolayısıyla paylaşılan yazım tek başına aradaki uzaklığı belirlemez. Bu bölümün modellerinde ölçtüğümüzde beğendim ile beğenmedim arasındaki kosinüs fastText’te 0,74, word2vec’te 0,53; kaldım ile kalmadım için 0,69 ve 0,56. Kökü paylaşmayan ederim / etmem çiftinde ise iki model aynı yerde: 0,56 ve 0,57.
Kelime unigram TF-IDF’inde beğendim ile beğenmedim iki ayrı sütundur; birini içeren belge, ötekinin sütununda sıfır taşır. Bu, iki biçimin karıştırılmamasına yardım eder. TF-IDF seyrelmeye bağışık da değil: L2 normalleştirmesiyle, yalnızca tek bir terimde farklılaşan \(n\) terimli iki belge (her terim bir kez geçiyor ve bütün ağırlıklar eşitse) \((n-1)/n\) kosinüsünde oturur ve bu da \(n\) büyüdükçe 1’e gider. Gerçek yorumlardaki 0,19–0,69 değerleri ise terimlerin IDF ağırlıklarına ve token dizilerine bağlıdır; bu sayıları yalnızca ayrı sütunlara bağlayamayız.
Benzetme. Kelime vektörlerinin ortalamasını almak, bir tablonun ortalama rengini almaya benzer. Yalnızca biri gün doğumu, öteki gün batımı olmakla ayrışan iki tablonun ortalama rengi neredeyse aynıdır ve sınıflandırıcınızın görebildiği tek şey o ortalama renktir. Bag-of-words ise bunun yerine hangi boyaların bulunduğunun listesidir — ilişkiler konusunda daha kaba, ama değişen boyayı ayrı bir kalem olarak tutar.
Yüksek kosinüs, karar yönünde ayrım olmadığı anlamına gelmiyor. Ortalaması alınmış fastText üzerindeki sınıflandırıcı, “ürünü çok beğendim” cümlesine olumlu olma olasılığı 0,82, olumsuz hâline 0,02 veriyor — kosinüs 0,776 iken. Yeniden koşuda beş çiftin beşinde de olumsuz hâlin olasılığı 0,5’in altında kalıyor (0,02 ile 0,33 arasında). Lojistik regresyon, iki ortalama arasındaki küçük farkın ayırt edici olduğu bir yön bulabiliyor. Ortalama alma bazı sinyalleri zayıflatabilir; 14,82 puanlık toplam farktaki payını ise bu örnekler ölçmez.
4.9 Kesişim noktası: embedding’ler ne zaman kazanır
Buraya kadar her şey yöntemleri 40.000 etiketli yorumla karşılaştırdı. Pratikte çoğu zaman bu kadar etiket olmaz; bu yüzden etiket sayısı değiştikçe sıralamanın nasıl değiştiğine bakacağız.
Bu öğrenme eğrisinde iki temsil ailesi de 40.000 eğitim yorumunun metninden yararlanıyor: TF-IDF sözlüğünü ve IDF değerlerini, embedding modelleri eş-oluşum (hangi kelimelerin birlikte geçtiği) ve alt kelime parametrelerini bu metinden, etiketlere bakmadan öğreniyor. Değişen, sınıflandırıcıya verilen etiket sayısı: 100’den 40.000’e. Yani soru şu: etiketsiz metne erişim sabitken, ek etiketler karar sınırını nasıl değiştiriyor? TF-IDF’in etiketsiz metinden aldığı şey belge frekanslarıyla sınırlı; embedding’ler kelimeler arasındaki eş-oluşum ilişkilerini de alıyor.
Her n için eğitim kümesinden tabakalı bir altörneklem çekiliyor (train_test_split(train_size=n, stratify=…, random_state=42)) ve sınıflandırıcı yalnızca o satırların etiketleriyle eğitiliyor.
### macro-F1 by labelled training size (same test set of 10,000)
n negatives tf-idf tf-idf char word2vec fastText
100 6 48.37 48.37 53.51 53.87
250 16 48.53 48.84 61.59 63.10
500 32 49.28 50.60 61.02 61.16
1,000 63 55.40 58.55 59.52 59.93
2,500 158 66.61 68.36 60.91 61.19
5,000 316 71.16 70.47 61.52 60.80
10,000 632 72.55 71.29 61.80 61.56
20,000 1,264 72.42 71.26 60.94 60.96
40,000 2,529 71.95 70.39 61.39 61.36
Tablonun her satırı tek bir altörneklemden geliyor. word2vec sütunu 250 ile 40.000 etiket arasında 59,52 ile 61,80 arasında değişiyor. Bu dalgalanmanın ne kadarının etiket sayısından, ne kadarının hangi belgelerin seçildiğinden ya da vektör eğitiminden geldiğini bu tablo söylemez; model çiftleri için bir anlamlılık eşiği olarak da kullanılamaz. Yoğun sütunlar ayrıca küçük n’de vektör eğitimine duyarlı: aynı kodla yeniden eğitilen vektörlerle (2. raunttaki yeniden koşu) word2vec 100 etikette 58,23, 250 etikette 65,21 veriyor — tablodaki 53,51 ve 61,59’un yerine. Seyrek sütunlar yeniden koşuda birebir aynı çıkıyor.
Belirsizliği ölçmek için her eğitim büyüklüğünde on ayrı tabakalı etiket örneklemi çektik (temsiller sabit; yoğun sütunlar yeniden koşunun vektörleriyle):
### ten label samples per size: mean macro-F1 [min, max]; representations fixed
n tf-idf tf-idf 1-2 gram word2vec fastText tf-idf > fastText
100 48.49 [48.35, 48.85] 48.45 [48.37, 48.69] 59.68 [54.63, 61.68] 58.66 [53.80, 61.44] 0 / 10
250 48.98 [48.35, 49.63] 48.70 [48.37, 49.17] 61.69 [58.58, 65.07] 60.96 [56.55, 64.83] 0 / 10
500 50.65 [49.46, 51.94] 49.17 [48.51, 49.95] 61.85 [59.63, 64.18] 61.96 [60.47, 63.84] 0 / 10
1,000 56.57 [55.14, 59.80] 51.68 [50.39, 53.36] 62.15 [61.61, 63.32] 61.96 [61.01, 63.15] 0 / 10
1,250 59.59 [57.39, 62.41] 53.43 [51.60, 56.44] 62.01 [60.81, 62.91] 62.00 [60.83, 63.29] 2 / 10
1,500 61.87 [60.50, 65.01] 55.63 [53.54, 58.41] 62.06 [60.69, 63.43] 61.90 [60.36, 63.52] 4 / 10
1,750 63.95 [62.34, 65.35] 57.81 [56.37, 60.89] 61.89 [60.30, 63.11] 61.64 [60.22, 62.92] 10 / 10
2,000 65.54 [63.74, 67.20] 59.69 [57.89, 61.64] 61.70 [60.38, 62.67] 61.44 [60.35, 62.82] 10 / 10
2,500 67.52 [66.29, 69.69] 63.42 [62.18, 64.71] 61.68 [60.65, 62.70] 61.55 [60.61, 62.53] 10 / 10
5,000 70.97 [69.72, 72.27] 71.49 [70.06, 72.88] 61.48 [60.00, 62.64] 61.18 [59.98, 62.40] 10 / 10
Aynı büyüklükte, yalnızca hangi belgelerin etiketlendiği değişince skorlar birkaç puan oynuyor: 1.000 etikette TF-IDF 55,14 ile 59,80, fastText 61,01 ile 63,15 arasında. Tek bir altörnekleme dayanan bir sıralamayı bu yayılımla birlikte okuyun.
Bu grafikte kelime TF-IDF’i, ortalaması alınmış fastText ve (etiketsiz kesikli çizgi olarak) ortalaması alınmış word2vec gösteriliyor; karakter TF-IDF’i okunabilirlik için çizilmedi, bigram TF-IDF’inin sonuçları yukarıdaki on örneklemli tabloda. Dokuz eğitim büyüklüğü, baştan sona aynı test kümesi, her büyüklükte tek bir altörneklem. 250 etikette fastText kelime TF-IDF’inden 14,57 puan yüksek (word2vec 13,06), 40.000 etikette 10,59 puan düşük. Bu kurulumda etiket sayısı sıralamayla ilişkili; farklı yöntem ve ayarlar için aynı kesişim beklenmemeli.
Kesişim aralığını taşınabilir bir sayı olarak okumayın. İlk tablodaki tek altörneklem dizisinde kelime TF-IDF’i 1.000 etikette embedding yöntemlerinin altında, 2.500 etikette üstünde; çizgilerin kesiştiği yer (yaklaşık 1.500) iki ölçüm arasından okunan bir değerdi, ölçülmüş bir nokta değil. On etiket örnekleminde ölçtüğümüzde TF-IDF fastText’i 1.000 etikette hiç, 1.250’de on örneklemin ikisinde, 1.500’de dördünde, 1.750’de onunda da geçiyor: bu kurulumda sıra 1.250 ile 1.750 etiket arasında değişiyor. Bu bölümün en yüksek skorlu modeli olan kelime bigram TF-IDF’i için aralık daha sağda: az etikette unigram TF-IDF’in altında kalıyor (3,4 kat fazla sütunu bir avuç olumsuz örnekten kestirmek zorunda) ve fastText’i 2.000 etikette on örneklemin ikisinde, 2.500’de dokuzunda geçiyor. Bütün bu sayılar aynı test kümesinden okundu. Yöntem seçimi için train’i bir kez daha bölüp doğrulama diliminde karar verin; testte yalnızca önceden seçilmiş yöntemi değerlendirin.
Taşınabilir olan şey eşik değil, biçim: az etiket rejiminde etiketsiz metinden öğrenilmiş bir temsilin önceliği olabilir; etiket arttıkça seyrek doğrusal model bu önceliği kapatır. Kendi göreviniz için kendi eğrinizi çıkarın.
Grafiğin sol kenarını dikkatle okuyun. 250 etiketli yorumla — ki bunların 16’sı olumsuz — kelime TF-IDF’i 48,53, çoğunluk kuralı 48,37 macro-F1 alıyor. Bu modelin tahminlerine baktık: 10.000 test yorumunun yalnızca birine olumsuz diyor (o yorum gerçekten olumsuz). Yani bu koşuda fiilen çoğunluk kuralı gibi davranıyor; 0,16 puanlık farkın eşleştirilmiş bootstrap aralığı 0,00 ile 0,51. Ortalaması alınmış fastText aynı 250 etiketle 63,10 alıyor. On etiket örnekleminde fastText ile TF-IDF arasındaki fark 250 etikette ortalama 12,0 puan (8,2 ile 16,1 arasında).
Bu örüntüyle uyumlu bir açıklama şu: az etiketle, kelime temelli doğrusal modelin nadir özniteliklerine ait katsayılar güvenilir kestirilemeyebilir — 16 olumsuz örnek, 30.195 sütunlu bir uzaydan çekilmiş 16 seyrek satırdır. Embedding modeli ise 40.000 yorumun etiketsiz metninden önceden öğrenilmiş ortak bir yapı sunar: örneğin word2vec kalitesiz, dandik ve dayanıksız kelimelerini birbirine yakın yerleştiriyor (yukarıdaki komşu listeleri) ve sınıflandırıcının 100 boyutta kestirmesi gereken katsayı sayısı çok daha az. Bu açıklamayı sınamak için az etiketli koşuldaki katsayılara, hatalara ve daha güçlü düzenlileştirme seçeneklerine bakmak gerekir; bu bölüm bunu yapmadı.
Kendi kendine denetimli (self-supervised) eğitim — etiketi verinin kendisinden türeten eğitim — etiketlere bakmadan kelimelerin birlikte görülme örüntülerinden bilgi çıkarır. Bu örüntüler az etiketli bir sınıflandırıcıya yararlı olabilir; modelin Türkçenin bütün dilbilgisini ya da duygu kutbunu öğrendiği anlamına gelmez. Öğrenilen bilginin bu görevde hangi örnekleri düzelttiği ayrıca incelenmelidir. Bu kitaptaki ön eğitimli modellerin arkasındaki genel ilkenin küçük ölçekli hâli budur.
Sonra eğri düzleşiyor. Ortalaması alınmış fastText 500 etiketle 61,16, 40.000 etiketle 61,36 macro-F1 alıyor; on örneklemli ölçümde de 500 ile 5.000 etiket arasındaki ortalamalar 61,2–62,0 bandında kalıyor. Bu yakınlık, mevcut havuzlama ve ayarlarla daha fazla etiketin sınırlı kazanç verdiğini düşündürür. Bunun temsilin değişmez üst sınırı olduğunu söylemek için normalleştirmeyi, C’yi, karar eşiğini, farklı tohumları ve kelime sırasını koruyan alternatifleri karşılaştırmak gerekir. Kelime TF-IDF’i ise aynı tabloda yaklaşık 10.000 etikete kadar yükseliyor, sonra tek koşuda hafifçe düşüyor.
İki eğrinin biçimi farklı: bu kurulumda ortalamaya dayalı statik yoğun temsil birkaç yüz etiketten sonra neredeyse hiç kazanmıyor, seyrek doğrusal model ise etiket geldikçe kazanmayı sürdürüyor. Cümleyi bu kadar dar tutmak önemli — ölçülen şey “yoğun temsiller” değil, bu kurulum: sıfırdan eğitilmiş 100 boyutlu statik vektörlerin ortalaması. Genelleşen kısım, sorunun kendisi: bu görevde beni sınırlayan etiket mi, temsil mi, yoksa ayarlar mı?
4.10 Bunun bedeli ne
Yöntem seçerken skorla birlikte eğitim ve çıkarım maliyetini de değerlendirmek gerekir. Bu deney üç şeyi ölçtü: temsili kurma süresini, 10.000 test belgesini vektörleştirme süresini ve eğitim matrisinin belleğini. Model dosyasının boyutu, sözlük ve embedding tablosunun bellekte kapladığı yer, sınıflandırıcının kendi boyutu, eğitimdeki tepe RAM kullanımı, 95. yüzdelik (p95) gecikme ve bir indeksi yayına almanın bedeli burada yok.
### cost, on one CPU core, 40,000 training documents (single run, not repeated)
build the vectorise training
representation 10,000 test matrix
tf-idf 0.5 s 0.11 s 9.7 MB
tf-idf 1-2 gram 0.9 s 0.17 s 15.4 MB
tf-idf char_wb 3-5 2.9 s 0.72 s 144.8 MB
word2vec + averaging 14.7 s 0.11 s 16.0 MB
fastText + averaging 31.6 s 0.27 s 16.0 MB
doc2vec 8.5 s 1.73 s 16.0 MB
training matrix sütunu yalnızca eğitim matrisinin belleğidir; modeli, sözlüğü ya da embedding tablosunu ve tepe RAM kullanımını kapsamaz. Süreler tek koşudan geliyor. 1. rauntta vektörleştirme sürelerini beşer kez yeniden ölçtüğümüzde koşudan koşuya fark yüzde on dolayında kaldı (örneğin bigram şemasında 0,82–0,90 sn); küçük süre farklarını bu yüzden karşılaştırmayın.
Tablodaki iki satır ayrıca yorumlanmayı hak ediyor.
Karakter n-gram’larında bellek ile skor dengesi koşula bağlı. Tam eğitim koşulunda karakter TF-IDF’i 144,8 MB’lık bir matrisle (belge başına 301 sıfırdan farklı değer) 70,39 macro-F1 aldı; kelime TF-IDF’i 9,7 MB ile 71,95. (Bag-of-words matrisinin seyreklik deseni de aynı olduğu için o da aynı boyutta; tabloda yalnızca tf-idf satırı var.) 1.000 etiketli noktada ise karakter öznitelikleri kelime TF-IDF’inin 3,2 puan önündeydi. Bu yüzden bellek–skor dengesini etiket miktarına ve metindeki yazım gürültüsüne göre yeniden değerlendirin.
doc2vec, yeni bir belgeyi vektörleştirmek için gradyan inişi koşturmak zorunda. 10.000 yorum için 1,73 saniye; ortalama alma ise 0,11 — 16 kat fark ve eğitimin aksine bu maliyet her yeni belgede yeniden oluşuyor. Mutlak sayıya da bakın: belge başına 0,17 milisaniye, çoğu servis için hâlâ küçük; karar, sizin gecikme bütçenize göre verilir. Bu kurulumda doc2vec’in macro-F1’i 55,13 ile incelenen yoğun satırların en düşüğü. Bu kısa ve gürültülü yorum görevinde doc2vec’in varsayılan tercih olmasını destekleyen bir ölçüm yok. 3. bölümün 20 Newsgroups karşılaştırmasında (Bölüm 3) doc2vec ortalama almanın önündeydi; burada 6,3 puan geride. İki sonuç arasındaki farkın belge uzunluğundan mı, dilden mi, veri miktarından mı kaynaklandığını bu bölüm sınamadı.
4.10.1 Melez yaklaşım ve bir olumsuz sonuç
Önce ölçek. Melezdeki iki blok farklı ölçeklerde geliyor: char_wb TF-IDF satırları L2 ile normalleştirilmiş (norm 1; belge başına ~301 sıfır dışı değer, ortalamaları 0,05); ortalaması alınmış fastText satırları ise normalleştirilmemiş ve normları ortalama 2,5 (bileşenlerin ortalama mutlak değeri 0,2). İki bloğu tek bir L2-cezalı C = 1.0’a vermek, aralarındaki göreli ağırlığı bizim değil varsayılanın seçmesi demek. Bu yüzden iki sürümü de ölçtük: önce düz birleştirmeyi, sonra blokları ayrı ayrı normalleştirip karışım ağırlığını doğrulama diliminde seçen sürümü.
Akla gelen ilk hamle birleştirmek: yazım dayanıklılığı için karakter TF-IDF’i, anlam için ortalaması alınmış fastText, ikisinin üstünde tek bir sınıflandırıcı.
### tf-idf char_wb 3-5 ⊕ averaged fastText (95,039 dimensions)
accuracy 89.36 macro-F1 71.65 F1(neg) 49.24
Düz birleştirme bu testte 71,65 macro-F1 alıyor; tek başına karakter TF-IDF’i 70,39, tek başına fastText 61,36, kelime bigram TF-IDF’i 76,21 almıştı. Yeniden koşudaki eşleştirilmiş bootstrap aralıklarıyla: melez − karakter TF-IDF +1,28 puan (0,65 ile 1,92 arası), bigram − melez +4,54 puan (3,42 ile 5,63 arası). Yani düz melez kendi parçalarının önünde, bigram’ların gerisinde.
Blok ölçeklerini ayarlayan sürümde yoğun bloğu satır bazında L2 ile normalleştirip bir \(\alpha\) katsayısıyla çarptık; \(\alpha\)’yı (0,25; 0,5; 1; 2; 4) ve C’yi (1; 3; 10; 30) 32.000/8.000’lik doğrulama bölmesinde seçip modeli 40.000 belgede yeniden eğittik. Seçilen ayar (\(\alpha = 2\), C = 10) testte 74,69 macro-F1 veriyor: düz birleştirmenin 3,02 puan üstünde (2,00 ile 4,06 arası). Aynı ayar bütçesi tek başına karakter TF-IDF’ine verildiğinde o da 73,46’ya çıkıyor (C = 30); melezin ona göre kazancı 1,23 puan (0,33 ile 2,15 arası). Ayarlanmamış bigram TF-IDF’i (76,21) ise ayarlanmış melezin hâlâ 1,52 puan önünde (0,20 ile 2,80 arası). Yani ölçek ayarı melezin skorunu belirgin biçimde değiştiriyor — düz birleştirmeye bakıp “melez işe yaramıyor” demek yanlış olurdu — ama bu kurulumda bigram TF-IDF’ini geçmesine yetmiyor.
Maliyet tarafında, temsil kurma sürelerinin kaba toplamı 2,9 + 31,6 = 34,5 saniye (ikisi de yukarıdaki maliyet tablosundan), bigram modelinin 0,9 saniyesine karşılık; uçtan uca eğitim ve servis maliyetini ölçmedik. Birleştirme gerçek bir tekniktir ve burada bileşenlerine göre ölçülebilir bir kazanç veriyor. Ama melezi yalnızca kendi parçalarıyla karşılaştırıp başarı diye bildirmek, tam da bu bölümün karşı çıktığı şey olurdu: işinize gelen baseline’ı seçmek.
4.11 Bilerek seçmek
Yedi temsilin ölçülen skorları, bellek ve kapsama özellikleri farklı. Aşağıdaki tablo bunları bu deneyin koşullarıyla birlikte özetliyor; yöntem seçimi göreve ve veri bütçesine göre yapılmalı.
| Güçlü yanları | Zayıf yanları | Ne zaman seçilir | |
|---|---|---|---|
| Bag of words | Bu deneyde en hızlı kurulan temsillerden biri; kelime öznitelikleri katsayılarla eşleştirilebilir. Sabit C = 1.0 ile kelime TF-IDF’inden yüksek skor aldı (73,51’e karşı 71,95). |
Belge uzunluğunu kendiliğinden normalleştirmez; temsil aşamasında bir bilgilendiricilik ağırlığı uygulamaz. Nadir biçimler ayrı özniteliklerdir. Katsayılar tek başına neden göstermez. | Kısa belge sınıflandırması için ilk baseline’lardan biri; ayarları doğrulama kümesinde seçin. |
| TF-IDF (kelime) | Belge frekanslarını eğitim metninden öğrenir; kelime öznitelikleri incelenebilir. C doğrulamada ayarlanınca 74,71 macro-F1 aldı ve ham sayımların önüne geçti (fark 1,20; eşleştirilmiş bootstrap aralığı 0,42–1,99). |
Paylaşılan ve ayarlanmamış C ile ham sayımların gerisinde kaldı; kısa metinde ikisini de ölçün. Görülmemiş bir kelime biçiminin sütunu yoktur; model aynı belgedeki tanıdık kelimelere dayanır. Türkçe çekimler ayrı sütunlara dağılır. |
Genel amaçlı ilk seyrek baseline; vektörleştirici ve C seçimini eğitim/doğrulama sınırı içinde yapın. |
| TF-IDF (kelime unigram + bigram) | Bu bölümdeki en yüksek macro-F1: 76,21. İki kelimelik yerel dizileri ayrı öznitelik olarak tutar. Hâlâ katsayıları incelenebilen bir doğrusal model. | 101.659 sütun (unigram’ın 3,4 katı). Az etikette unigram TF-IDF’in altında kaldı (1.000 etikette ortalama 51,7’ye karşı 56,6). Hangi dizilerin skora ne kadar katkı verdiği ayrıca çözümlenmeli; eğitimde görülmemiş bigram’lar temsil edilmez. | Birkaç bin etiketiniz varsa ve yerel kalıpların önemli olabileceği kısa metin görevlerinde — duygu, niyet, triyaj — denenmesi gereken güçlü seyrek aday. |
| TF-IDF (karakter n-gram’ları) | Kısmi yazım örtüşmesinden yararlanabilir: yanlış yazılmış bir kelime, doğrusuyla n-gram’larının çoğunu paylaşır. Tek altörneklemli öğrenme eğrisinde 1.000 etikette kelime TF-IDF’inin 3,2 puan önündeydi. Kelime tokenizer’ına daha az bağımlı — ama küçük harfe çevirme, Unicode normalleştirmesi ve bozuk karakterler hâlâ dile bağlı kararlar. | 144,8 MB eğitim matrisi ve belge başına ortalama 301 sıfır dışı değer. Tam veride kelime TF-IDF’inden düşük macro-F1 (70,39). Görülmemiş n-gram’lar atılır. N-gram katsayıları incelenebilir, ama kelime katsayılarından daha güç yorumlanır. | Yazım değişkense ve ölçtüğünüz bellek ile skor uygunsa. |
| Ortalaması alınmış word2vec | 100 boyutlu belge vektörüyle 61,39 macro-F1 — kelime TF-IDF’inden 302 kat az koordinat. Etiketsiz metinden eğitilir. Bu kurulumda 1.000 etikete kadar on etiket örnekleminin hepsinde kelime TF-IDF’inin önünde; sıra 1.250–1.750 etiket arasında değişiyor ve bu aralık taşınabilir değil. | Farklı test biçimlerinin %46,4’ü sözlükte yok; ortalama bunları atlar. Az görülmüş sözlük içi biçimlerin vektörü zayıf kestirilmiş olabilir. Ortalama alma kelime sırasını ve bazı yerel ayrımları kaybeder. Yoğun matris seyrek matristen küçük olmak zorunda değil (16,0 MB’a karşı 9,7 MB). | Etiket kıtsa ya da yoğun vektör araması gerekiyorsa; hedef veride sınanacak bir aday olarak. |
| Ortalaması alınmış fastText | Bu deneyde tokenizer’ın ürettiği bütün test biçimleri için vektör kurdu. Tek altörneklemli eğride 250 etikette en yüksek skor (63,10). | Benzer yazılış, zıt duygulu biçimleri de yakınlaştırabilir: kalitesiz → kalitesi; ilk 5 komşunun %60,7’si sorguyla aynı beş harfle başlıyor (word2vec’te %6,5). Macro-F1’i word2vec’inkinden ayırt edilemedi (61,36’ya karşı 61,39). Eğitimi word2vec’in yaklaşık 2 katı sürdü; alt kelime tablosunun belleği ölçülmedi. |
Yazım ve biçim çeşitliliği yüksekse; görev başarısını ve belleği ölçerek. |
| doc2vec (PV-DBOW) | Eğitim belgelerinin her biri için ayrı bir vektör öğrenir; ortalama alma adımı yoktur. | Bu koşudaki en düşük skor: 55,13. Yeni belge için vektör çıkarımı ek optimizasyon gerektirir (10.000 yorumda 1,73 sn; ortalamanın 16 katı). Bu varyantın kelime sırasını temsil ettiği gösterilmedi. Fazladan hiperparametreler. | Belge vektörünü doğrudan öğrenmenin kendi verinizde ortalama almayı geçtiğini ayrı bir deneyle gösterebildiğinizde. |
Karar prosedürünün, tek satır kod yazmadan önce uygulayabileceğiniz biçimde sıkıştırılmış hâli. Dikkat edin: bu bir eşik listesi değil, bir soru listesi.
### temsil seçme sırası
1. Görevi, yanlış alarm ve kaçırma maliyetlerini, ana metriği yazın.
2. Veri sürümünü, eğitim/doğrulama/test bölmelerini ve erişebildiğiniz
etiketsiz metni sabitleyin.
3. Ön işlemeyi, sözlüğü ve IDF'i test etiketlerinden uzak tutun; hangi metnin
nerede kullanıldığını belgeleyin.
4. Ucuz baseline'ları kurun:
kelime sayımları / tf-idf
kelime n-gram'ları
karakter n-gram'ları (özellikle yazım gürültülüyse)
5. Yeterli etiketsiz metniniz ya da uygun ön eğitimli vektörünüz varsa bir
embedding adayı ekleyin.
6. Her adayın ayarlarını aynı doğrulama bütçesiyle seçin; OOV oranına ve hata
örneklerine bakın (sıra/olumsuzlama mı, yazım/OOV mi?).
7. Kararı doğrulama kümesinde verin:
skor + aralık · gecikme · bellek · açıklanabilirlik ihtiyacı
8. Kilitli test kümesini, seçilmiş çözüm için bir kez kullanın.
Bu bölümün gözlediği sayılar — 1.250–1.750 etiket arasındaki sıra değişimi, kısa belgelerdeki sayım–TF-IDF sıralaması, süreler — 5. adımda birer başlangıç beklentisi olarak işe yarar, 1. adımda birer kural olarak değil. “Açıklama gerekiyorsa seyrek”, “milyonlarca vektörde arama gerekiyorsa yoğun” da böyle: ikisi de güçlü ilk adaylar, mutlak kurallar değil. Seyrek sözlüksel erişim (lexical retrieval) milyonlarca belgede pekâlâ standart olabilir ve yoğun modeller de açıklanabilir hâle getirilebilir.
4.12 Unigram torbasının ve ortalamanın ortak sınırı: kelime sırası
Bölümü “sayım yöntemleri daha yüksek skor aldı” özetiyle kapatmak eksik olurdu; çünkü en yüksek skorlu modelin de hâlâ kaçırdığı bir şey var. Unigram kelime torbası ve kelime vektörlerinin basit ortalaması, bazı sıra değişimlerini aynı belge temsiline indirger. Bigram TF-IDF aşağıdaki kısa örneği ayırabiliyor; ama sabit bir n-gram penceresi uzun erimli ilişkilerde sınırlı kalıyor. Hangi temsilin hangi sıra bilgisini koruduğunu ayıralım; Kısım II bu sınırdan başlıyor.
### two reviews, same words, opposite meaning
a = "kalite iyi fiyat kötü"
b = "kalite kötü fiyat iyi"
cosine, averaged fastText 1.0000
cosine, tf-idf 1.0000
Bu iki yorum aynı token’ları aynı sayıda içeriyor. Aynı tokenleştirme, aynı sözlük ve aynı ağırlıklar altında unigram TF-IDF de kelime vektörlerinin basit ortalaması da iki yorum için aynı vektörü üretir: toplama, terimlerin sırasına duyarsızdır. Kosinüs bu yüzden yaklaşık değil, tam olarak 1’dir (pratikte kayan nokta yuvarlamasına kadar; dördüncü ondalığın çok altında). Yalnızca bu vektörü girdi alan bir sınıflandırıcı iki yorumu ayıramaz — daha çok etiketle de, daha güçlü bir sınıflandırıcıyla da. Sırayı, bigram’ları ya da özgün metni ayrıca gören bir model ayırabilir.
Belge düzeyindeki duygu analizi bu kaybı, yön (aspect) düzeyindeki görevlere göre daha iyi tolere edebilir; çoğu yorumun baştan sona tek kutuplu olduğu makul bir beklenti, ama bu bölüm onu ölçmedi. “Müşteri hangi bileşenden şikâyet ediyor” sorusu içinse aynı kayıp, görevin çözümünü doğrudan engelliyor.
O 1,0000’in neye ait olduğunu açıkça belirtin: yukarıdaki iki satır unigram TF-IDF’e ve ortalaması alınmış embedding’lere ait. Kelime bigram’larında durum farklı: kalite iyi, iyi fiyat, fiyat kötü ile kalite kötü, kötü fiyat, fiyat iyi tek bir bigram bile paylaşmıyor. Eğitim sözlüğünde bu bigram’lar bulunuyorsa unigram + bigram TF-IDF temsilleri ayrılır. Bu deneyde altı bigram’ın dördü sözlükte (fiyat kötü ile kötü fiyat, min_df=2 eşiğini geçemedi) ve iki yorumun kosinüsü 1,0000’den 0,3247’ye iniyor. Temsillerin ayrılması, sınıflandırıcının farklı ya da doğru etiket vereceği anlamına gelmez: bu model iki yoruma da olumsuz diyor (olumlu olma olasılıkları 0,26 ve 0,15). Eşik bir çiftin bütün bigram’larını elerse, o çiftte sıra bilgisi de kaybolur.
Bigram torbası yerel sırayı tutar; daha uzaktaki bağımlılıkları doğrudan kodlamaz. Pompa, mühendisin geçen hafta değiştirmesine rağmen yine arızalandı cümlesinde özne pompa ile yüklem arızalandı arasında altı kelime var — Türkçenin özne–nesne–yüklem dizilimi özneyi başa, yüklemi sona itiyor. Bu bağı tek bir ardışık n-gram ile kapsamak için sekiz token’lık bir dizi gerekir; bu kadar uzun kalıplar küçük veri kümelerinde çok seyrek tekrar eder. Olası n-gram çeşitlerinin sayısı n ile çok hızlı artar; fiilen saklanan sözlük ise görülen kalıplarla ve eşiklerle sınırlıdır. Daha uzun ilişkiler için temsilin kelime dizisinin bir fonksiyonu olması gerekir: kalite, ardından iyi okuduğunda, kalite, ardından kötü okuduğundakinden farklı bir durum üreten bir şey. Bu bizi kelime sırasını hesaba katan encoder’lara (kodlayıcılara) götürüyor. Dil modelleri, bu tür encoder’ları büyük miktarda etiketsiz metinden öğrenmenin önemli yollarından biridir ve Bölüm 6 oradan başlıyor — ama sırayı hesaba katan bir encoder’ın illa bir dil modeli olması gerekmez. O durumu diğer bütün kelimelere aynı anda bağlayan mekanizma ise attention’dır (dikkat mekanizması); konusu ondan sonraki bölümde (Bölüm 7).
Bu deney, sonraki modellerde aranacak iki yararlı özelliğe işaret ediyor: seyrek temsillerin belirleyici yerel biçimlere duyarlılığı ve embedding’lerin kelime biçimleri arasında ortak yapı kurabilmesi. Sıraya duyarlı modeller, bu iki özelliğin yanında belge içi ilişkileri de temsil etmeyi hedefler. Hangi kazancın gerçekleştiğini yine hedef görevde ölçmek gerekir.
4.13 Sezgi kontrolleri
Açmadan önce cevaplayın.
Tek bir model adı değil, bir karşılaştırma planı.
Önce talebin etiketini, iş metriğini ve test düzenini belirleyin. İki milyon etiketsiz talep iki aile için de kaynaktır: word2vec ya da fastText’i o metinde eğitebilir, ön eğitimli vektörleri alana uyarlayabilirsiniz; kelime ve karakter TF-IDF’i de sözlüğünü ve IDF ağırlıklarını aynı metinden öğrenebilir. Aradaki fark ne öğrenilebildiği: TF-IDF sözlük ve belge frekansıyla sınırlı kalır, embedding modeli aynı metinden eş-oluşum yapısını da çıkarır. Bu metin “bedava” da değil: eğitim süresi ve veri erişimi birer maliyettir.
Bu bölümün ürün yorumu deneyinde 500 etikette embedding ortalamaları kelime TF-IDF’inin yaklaşık 11 puan önündeydi (on etiket örnekleminin ortalaması: 62,0’a karşı 50,7); 400 etiketle bir embedding adayının güçlü çıkmasını beklemek makul. Ama bu bir beklenti: destek talepleri başka bir alan, etiket de başka bir etiket. Kelime n-gram, karakter n-gram ve embedding adaylarını aynı doğrulama bütçesiyle karşılaştırın. Talepler kullanıcıların yazdığı Türkçe metinler olduğu için fastText’i özellikle deneyin: burada farklı test biçimlerinin %46,4’ü word2vec sözlüğünün dışındaydı; kendi verinizdeki oranı ölçün.
Sonra cevabın ikinci yarısını söyleyin: ek etiketleme kararını kendi öğrenme eğrinizle verin. Ürün yorumu deneyindeki 1.250–1.750 etiketlik sıra değişimini bu alanda eşik saymayın.
Önce aynı test kümesindeki çoğunluk kuralının doğruluğunu ve karışıklık matrisini.
%93, bu test kümesinde her girdiye çoğunluk sınıfını vererek elde edilen %93,68’in altında. Bu, modelin işe yaramadığını göstermez: doğruluğu daha düşük bir model olumsuzların çoğunu buluyor olabilir (bu bölümün bigram TF-IDF’i %92,57 doğrulukla olumsuzların %76,3’ünü buluyor). Bu yüzden olumsuz sınıfın recall ve precision’ını, seçilen karar eşiğinde yanlış alarmların yarattığı iş yükünü isteyin. Yayına alma kararı için kaçırılan şikâyetin ve yanlış alarmın maliyeti ile hedef trafikteki sınıf dağılımı da gerekir.
Sorunun genel hâli şudur: en basit baseline’ın skoru kaç? Bunu, bildirilen herhangi bir skora bakmadan önce sorun.
Bu koşuda word2vec 61,39, fastText 61,36 macro-F1 aldı; fark ayırt edilemiyor (eşleştirilmiş bootstrap aralığı −0,60 ile +0,77; eğitim tohumu tek başına 0,5–0,8 puan oynatıyor). Kapsama, farklı test biçimlerinin %53,6’sından %100’üne çıktı. Karşılaştırmayı olduğu gibi okuyun: farklı yöntemlerle eğitilmiş iki model var, yani bu kurgu kapsamayı yalıtmıyor; skor farkından kapsamanın nedensel etkisini ayıramayız.
Olası açıklamalar var. fastText’in komşuları yazılışça yakın biçimlere kayıyor (ilk 5 komşunun %60,7’si sorguyla aynı beş harfle başlıyor; word2vec’te %6,5) ve kalitesiz (“düşük kaliteli”), olumsuzluk eki taşımayan kalitesi’ni (“onun kalitesi”) getiriyor. Ortalaması alınmış vektörlerde bir cümle ile olumsuz hâli arasındaki kosinüs iki modelde de yüksek: fastText’te 0,78–0,96, word2vec’te 0,72–0,96. Bunlar açıklama adayları; doğrulamak için aynı model üzerinde OOV token’larını çıkarıp ekleyen bir ablasyon, eşit ayar bütçesi ve eşleştirilmiş hata analizi gerekir.
Aktarılabilir ders: bir temsil özelliğindeki iyileşme, ancak görevi sınırlayan şey o özellikse görev skorunda görünür. Bir şeyi düzeltmeye girişmeden önce neyin sınırladığını ölçün.
Bilmiyoruz; bu koşullar ölçülmedi.
Daha büyük ya da ön eğitimli Türkçe vektörler (Grave vd. 2018) komşulukları, olumsuzlama çiftlerinin kosinüsünü ve görev skorunu değiştirebilir; yönünü ve büyüklüğünü bu bölümden çıkaramayız. Değişmeyen tek şey matematiksel olan: aynı kelimeleri aynı sayıda içeren iki cümlenin basit ortalaması, hangi sabit kelime vektörleri kullanılırsa kullanılsın aynıdır; kelime sırası örneğindeki 1,0000 bu yüzden değişmez. 0,78–0,96’lık olumsuzlama kosinüsleri ise böyle değil: o cümleler hangi kelimenin geçtiğinde farklılaşıyor ve başka vektörler beğendim ile beğenmedim’i birbirinden daha uzağa koyabilir.
Bunu karara bağlamanın yolu 13. alıştırma: bu bölümün deneyini 300 boyutlu, ön eğitimli vektörlerle yeniden koşturun; sıralamayı ve sıranın değiştiği etiket aralığını yeni deneyle belirleyin.
4.14 Mülakat soruları
Bu sorular, temsil seçerken hangi ölçümleri ve hangi sınırları gerekçenize katacağınızı çalıştırır. Her yanıtı görev, veri miktarı, karşılaştırma sonucu ve sonucu değiştirebilecek koşullarla kurun. Aşağıdaki cevapların neredeyse hepsi bu bölümün ölçtüğü bir şeye dayanıyor.
Yanıtınızda önce görevde belirleyici olan ekseni adlandırın: etiket miktarı, biçim çeşitliliği, sıra gereksinimi ya da maliyet. Ardından varsa ilgili ölçümü verin ve sonucu hangi yeni verinin ya da deneyin değiştireceğini söyleyin.
Metin sınıflandırma için embedding mi, TF-IDF mi? Cevabı üç adımda kurun.
İlk soru. Etiketli örnek sayısını, erişilebilir etiketsiz derlemi ve görevin türünü sorun (belge düzeyi mi, yön düzeyi mi; belge uzunluğu; yazım/OOV gürültüsü). Kelime TF-IDF’i de sözlüğünü ve IDF ağırlıklarını etiketsiz eğitim metninden öğrenir; embedding modeli aynı metinden ayrıca eş-oluşum ve alt kelime parametreleri öğrenir. Hangisinin görev etiketine yaradığı hedef veride ölçülür.
Sayı. Bu deneyde 250 etikette ortalaması alınmış fastText 63,10 macro-F1 alırken kelime TF-IDF’i 48,53 aldı — çoğunluk kuralının skoruna çok yakın; 40.000 etikette aynı TF-IDF 71,95, fastText 61,36 aldı. On etiket örnekleminde sıra 1.250 ile 1.750 etiket arasında değişiyor.
Sınır. Aralık, eğriye hangi seyrek modeli koyduğunuza bağlı: 40.000 etikette 76,21 alan bigram TF-IDF az etikette unigram’ın altında kalıyor ve fastText’i ancak 2.000–2.500 etiket arasında geçiyor. Sıfırdan eğitilmiş ortalama-embedding eğrisi birkaç yüz etiketten sonra düzleşiyor; kelime TF-IDF’i kabaca 10.000 etikete kadar yükseliyor (tek koşuda 10.000’de 72,55, 40.000’de 71,95). Daha fazla etiketin mi, ayar değişikliğinin mi, başka bir modelin mi yarar sağlayacağını kendi verinizde, tekrarlı bir öğrenme eğrisi ve bir doğrulama kümesiyle belirleyin.
Kelime vektörlerinin ortalaması neden sayımların gerisinde kalabilir? Ortak içerik, ayırt edici tek bir kelimenin yön katkısını zayıflatabilir. Beş karşıt yorum çiftinde ölçüldü: bir yorum ile onun olumsuz hâli, ortalaması alınmış fastText’te 0,78 ile 0,96, TF-IDF’te 0,19 ile 0,69 kosinüsünde duruyor. Yüksek kosinüs doğru sınıflandırmayı dışlamaz: sınıflandırıcı beş çiftin beşinde de olumsuz hâle 0,5’in altında olasılık verdi. Birinci temel bileşeni çıkarılmış ağırlıklı ortalama (Arora vd. 2017) denenebilecek ucuz bir seçenektir; o da kelime sırasını geri getirmez ve olumsuzlamadaki etkisini ayrıca ölçmek gerekir.
Türkçenin biçim çeşitliliği hangi adayları gündeme getirir? Bu deneyde test token’larının %7,27’si, farklı test biçimlerinin ise %46,4’ü word2vec sözlüğünün dışındaydı; oran derleme ve alana göre değişir. Bu kadar yüksek bir biçim OOV oranı, alt kelime kullanan fastText’i ve karakter n-gram TF-IDF’ini aday yapar: fastText bu testteki bütün biçimler için vektör kurabildi. Sonra ölçtüğünüzü söyleyin: kapsamayı %100’e çıkarmak macro-F1’i ayırt edilebilir biçimde değiştirmedi (61,39’a karşı 61,36). Kendi metninizde kapsamayı ve görev skorunu ayrı ayrı ölçün.
İki temsili manşet skorlarının ötesinde nasıl karşılaştırırsınız? Eşleştirilmiş tahminlerin çapraz tablosunu çıkarın. Düz kelime TF-IDF’i ile ortalaması alınmış fastText test kümesinin %84,1’inde uyuşuyor; uyuşmadıkları yerlerde TF-IDF 1.315, fastText 272 kez tek başına doğru — bir McNemar testinin ihtiyaç duyduğu da tam bu iki sayı. Sonra örnekleri okuyun, ama altı seçilmiş yorumdan 272’nin tamamı hakkında sonuç çıkarmayın: sözlük dışı token payı iki uyuşmazlık grubunda aynı (%9,5); ayrışan şey sınıf dağılımı. Skorları birbirine yakın iki modelde eşleştirilmiş bootstrap aralığını ve sistematik bir hata etiketlemesini ekleyin.
Maliyet farkı ne zaman önemlidir? Sayıları kapsamlarıyla birlikte söyleyin. Bu makinede bigram TF-IDF için temsili kurmak 0,9 s, eğitim matrisi 15,4 MB; fastText için kelime vektörü eğitimi 31,6 s, belge matrisi 16,0 MB. Bunlar toplam model belleği ya da servis gecikmesi değil. Bu ölçekte iki seçenek de ucuz görünüyor; maliyetin belirleyici olup olmadığını yeniden eğitim sıklığınız ve gecikme hedefinizle birlikte ölçün. Başka bir ölçekte tablo değişir: 12. bölümün kendi ölçümünde (Bölüm 12.9) prompt verilen bir model, fine-tuning (ince ayar) uygulanmış bir encoder’a göre belge başına 142 kat pahalı. Böyle bir sayıyı aktarırken görevini, donanımını ve ölçüm sınırını da söyleyin.
Daha büyük bir encoder’ı da deneyeceksek bu karşılaştırma neden yararlı? İki sebep. Birincisi, basit modeller göreve uygun güçlü başlangıç ölçütleri sağlar: 12. bölümün kendi ölçümünde (Bölüm 12.3) fine-tune edilmiş encoder kabaca 500 etiketin altında bu bölümdeki yöntemlerin gerisinde kalıyor; sıra 500 ile 1.000 etiket arasında değişiyor. O sonucu kendi verinizle, etiket bütçenizle ve ayar koşullarınızla karşılaştırın; bu bölümde ölçülmemiş bir üstünlük ya da eşik varsaymayın. İkincisi, tanılama alışkanlıkları buradan geliyor: olumsuzlama kosinüsü testi, uyuşmazlık çapraz tablosu, kapsama ile skor arasındaki ayrım ve maliyet denetimi. Bunlar daha karmaşık modellere de aynen uygulanır.
4.15 Daha derine inmek için
| kaynak | ne olduğu |
|---|---|
| Let’s build GPT: from scratch, in code — Andrej Karpathy | bir dil modelinin kodla, sıfırdan nasıl kurulduğunu yaklaşık iki saatte gösterir; bu bölümdeki temel yöntemlerden sonra sıraya duyarlı modellere geçmek isteyen okur için tamamlayıcı bir kaynak |
| Hugging Face LLM Course | eski adıyla NLP Course; ücretsiz ve koşturulabilir; kitabın Kısım II’de ulaştığı transformer modelleriyle başlıyor, dolayısıyla bu bölümün klasik baseline’larından sonraki adım olarak okuyun |
fastText kaynak deposu |
denetimsiz alt kelime vektörleri ve denetimli metin sınıflandırması için uygulama. Depo 19 Mart 2024’te arşivlendi; üretimde kullanmadan önce bakım ve sürüm durumunu ayrıca değerlendirin |
| scikit-learn text feature guide ve model selection | ilki bu bölümdeki kelime ve karakter vektörleştiricilerini, ikincisi doğrulama ve çapraz doğrulama düzenini anlatır |
| Chip Huyen’s blog | baseline seçmek ve bir modelin kullanıma sunulacak kadar iyi olduğuna ne zaman karar verileceği üzerine |
“fastText” adının iki ayrı şeyi gösterdiğine dikkat edin: denetimsiz alt kelimeli kelime vektörleri (bu bölümün 2. rauntunda kullanılan) ve denetimli fastText sınıflandırıcısı (aşağıdaki ilk makale). İkisi aynı kütüphaneden çıkar ama farklı şeylerdir.
- fastText for classification (Joulin vd. 2017). Denetimli fastText sınıflandırıcısı, kelime ve isteğe bağlı kelime n-gram temsillerini görev etiketleriyle birlikte öğrenir; makale CPU’da dakikalar içinde eğitildiğini bildiriyor. Bu bölümün düzeniyle — denetimsiz alt kelime vektörlerinin ortalamasını alıp üzerine lojistik regresyon eğitmek — aynı model değildir. CPU maliyetini ve görev başarısını hedef veride ölçerek karşılaştırmaya eklenebilecek bir adaydır.
- Enriching word vectors with subword information (Bojanowski vd. 2017). Yukarıdaki kapsama sonucunun arkasındaki makale; deneyleri, alt kelimelerin en çok yardım ettiği biçimbilimsel olarak zengin diller (aralarında Çekçe, Almanca ve Rusça) üzerinde yoğunlaşıyor.
- Distributed representations of sentences and documents (Le ve Mikolov 2014). doc2vec’in orijinal iddiaları; bu bölümün ölçümüyle karşılaştırarak okumaya değer.
- A simple but tough-to-beat baseline for sentence embeddings (Arora vd. 2017). SIF, kelime sıklığına göre ağırlıklı ortalama alır ve ortak bir bileşeni çıkarır. Bu bölümün yoğun satırları için sınanabilecek bir alternatiftir; skora etkisi ve hesap maliyeti burada ölçülmedi.
- The Hitchhiker’s Guide to Testing Statistical Significance in NLP (Dror vd. 2018). Bu bölümdeki eşleştirilmiş bootstrap ve McNemar hesaplarının dayandığı protokol; 8. alıştırma onu eğitim bölmesi üzerinden genişletmenizi istiyor.
- scikit-learn (Pedregosa vd. 2011) ve gensim (Řehůřek ve Sojka 2010). Bu bölümün üzerine kurulduğu iki kütüphane; ikisinin de kullanıcı kılavuzları alışılmadık derecede iyi.
4.16 Alıştırmalar
Her alıştırmanın başındaki etiket zorluk düzeyini gösteriyor: Temel kavramı pekiştirir, Uygulama kendi verinizde ölçüm yaptırır, İleri bölümün ötesine geçer, Araştırma ise açık uçludur.
- Kesişimi farklı sözlük eşikleriyle inceleyin. (Uygulama) Kelime TF-IDF’inin öğrenme eğrisini
min_df=1,2ve5için yeniden kurun. Her koşulda sözlüğün ve IDF’in hangi eğitim metninden öğrenildiğini sabit tutun (bu bölümde 40.000 yorumun tamamı) ve test etiketlerini seçimde kullanmayın. Az etiketli uçta skorun hangi yöne kayacağını önceden yazın; sonra sonucunuzla karşılaştırıp öznitelik sayısını ve doğrulama skorunu birlikte bildirin. - Bunun yerine dengesizlik düzeltmesini kaldırın. (Temel)
class_weight="balanced"ayarını kaldırıp her modeli yeniden koşturun. Her biri için doğruluğu ve macro-F1’i bildirin. Hangi yöntemler çoğunluk sınıfına çöküyor? Doğruluğa göre sıralama macro-F1’e göre sıralamadan daha çok değişiyor mu — değişiyorsa neden? - SIF ile ağırlıklı ortalama. (İleri) Arora vd. (2017) yöntemini uygulayın:
p(w)değerlerini eğitim metninden kestirin ve kelime vektörlerinin \(a = 10^{-3}\) için \(a/(a + p(w))\) ağırlığıyla ortalamasını alın. Çıkarılacak ortak bileşeni yalnızca eğitim belge vektörlerinden öğrenin; doğrulama ve test belgelerine aynı dönüşümü uygulayın. Düz ortalama, kelime TF-IDF’i ve bigram TF-IDF’iyle aynı değerlendirme düzeninde karşılaştırın; kazancı ya da kaybı önceden belirlediğiniz tek bir metrikle ve eşleştirilmiş bootstrap aralığıyla bildirin. - Olumsuzlama çiftlerini inceleyin. (Uygulama) Kendi alanınızdan yirmi karşıt çift kurun; her model için kosinüsü, sınıflandırıcının verdiği etiketi ve karar skorunu kaydedin. Kosinüsü yüksek olduğu hâlde doğru ayrılan bir çift bulun ve iki vektörün farkını sınıflandırıcının katsayı yönüne izdüşürerek bunu açıklayın. Seçtiğiniz yirmi örnekten genel bir hata oranı çıkarmayın.
- Karakter n-gram koşullarını sınayın. (Uygulama) Tek altörneklemli eğride karakter TF-IDF’i 1.000 etikette kelime TF-IDF’inin önündeydi, 40.000 etikette gerisinde. Bu fark için öznitelik sayısına ve öznitelik başına düşen gözlem sayısına dayalı bir hipotez kurun. Sonra
min_dfveCseçeneklerini doğrulama verisinde tarayın ve farkın yalnızca sütun sayısıyla açıklanıp açıklanmadığını sınayın. - Yön düzeyinde yeni bir görev kurun. (Araştırma) Bir yorumun hangi ürün özelliği (kargo, fiyat, kalite) hakkında olumlu ya da olumsuz yargı verdiğini açık bir etiket tanımıyla belirleyin. Belgeleri eğitim/doğrulama/test olarak ayırın ve her temsili aynı bölmelerde değerlendirin. Kelime sırasına duyarlılığın hangi örneklerde gerekeceğini önceden yazın; sonra skorlarla ve hata örnekleriyle denetleyin.
- Birleştirici nokta hasarını inceleyin. (Uygulama) 1. rauntu bu derlemde
str.lower()ile koşturmak hiçbir şeyi değiştirmez; yanlış işlenebilecek büyük harf kalmamış. Hasar daha önce oluşmuş: 4.194 belge U+0307 taşıyor ve bu altörneklemde işaret her seferinde biri’nin ardından geliyor. Örnekleri gözden geçirin ve yalnızca bu bozukidizisini hedefleyen bir normalleştirme kuralı yazın (başka bir derlemde U+0307 gerçek bir birleştirici işaret olabilir). Kuralı eğitim ve test metinlerine aynı biçimde uygulayıp 1. raunt tablosunu yeniden koşturun; sözlük büyüklüğündeki değişimi (bu bölüm 30.195 → 29.823 buldu), örnek token’ları ve macro-F1 farkını bildirin. Hangisinin daha çok oynamasını beklediğinizi ve nedenini önceden yazın. - Belirsizliği ölçün ve genişletin. (İleri — yapılacak tek alıştırma buysa bunu yapın.) Önce bu bölümün 2. raunttaki eşleştirilmiş bootstrap tablosunu yeniden üretin: önceden belirlediğiniz model çiftleri için aynı 10.000 test belgesini eşleştirilmiş biçimde yeniden örnekleyip macro-F1 farkının %95 aralığını hesaplayın. Doğruluk farkı için doğru/yanlış eşleştirmesinden McNemar testini kullanın; tek tek modellerin aralıklarını fark aralığıyla karıştırmayın. Aynı tabloda çok sayıda çifti sınarken çoklu karşılaştırmayı ve test kümesinin bölümde daha önce de incelenmiş olduğunu belirtin. Sonra bölümün ölçmediği kaynağı ekleyin: deneyi beş farklı eğitim/test bölmesiyle tekrarlayıp sonucun ne kadarının bölmeden kaynaklandığını bildirin. Protokol için bkz. Dror vd. (2018).
- Bir karar eşiği seçin. (Uygulama) Önceden seçtiğiniz modeli doğrulama verisinde üç farklı karar eşiğinde değerlendirin. Yanlış alarmların yarattığı iş yükünü ve kaçırılan olumsuz yorumun maliyetini karşılaştırıp eşiği orada belirleyin. Kilitli test kümesinde, seçtiğiniz eşiğin karışıklık matrisini bir kez bildirin ve kararı, yanlış alarmlarla uğraşacak kişiye gerekçelendiren cümleyi yazın. Asıl teslim edilecek şey macro-F1 değil, o cümledir.
- Suçlu gerçekten IDF mi? (Uygulama) Bölümdeki ablasyon merdivenini kendiniz yeniden koşturun — ham sayım, sayım + L2, log-TF + L2, TF-IDF — sonra bir basamak ekleyin: her satırı
C’yi doğrulama kümesinde ayarlayarak tekrarlayın. Normalleştirmenin etkisinden geriye ne kalıyor? - Analyzer denetimi. (Temel) İçinde noktalama, rakam, emoji ve bir U+0307 bulunan on cümle yazın.
analyzer="word"ilechar_wb’nin ürettiği öznitelikleri yan yana koyun. Karakter kolunun fazladan neyi gördüğünü ve bunun 1. raunt karşılaştırmasını nasıl etkilediğini yazın. - Tekrarlı öğrenme eğrilerini genişletin. (Araştırma) Bu bölüm her etiket bütçesinde on tabakalı altörneklem kullandı ve temsilleri 40.000 yorumun metninde sabit tuttu. Sayıyı 20’ye çıkarın, karakter TF-IDF’ini ekleyin ve her tekrarda, aynı altörneklemdeki model farkını bildirin. Sıra değişimi her tekrarda görülüyorsa yerinin dağılımını verin; bazı tekrarlarda hiç görülmüyorsa bunu da açıkça gösterin. Son olarak temsili de yalnızca etiketli altkümenin metninden öğrenin ve eğrinin nasıl değiştiğini bildirin.
- Ön eğitimli vektörleri sınayın. (İleri) 2. rauntun sıfırdan eğitilmiş vektörlerini, fastText’in Türkçe için yayımladığı 300 boyutlu ön eğitimli vektörlerle (Grave vd. 2018) değiştirin; vektörlerin ön işleme politikasının (küçük harf, tokenleştirme) sizinkiyle uyuştuğunu kontrol edin. Doğrulama bütçesini ve test protokolünü sabit tutup öğrenme eğrisini yeniden çıkarın; iyileşme, kötüleşme ya da değişmeme olasılıklarından hangisinin gerçekleştiğini bildirin.
kalite iyi fiyat kötüilekalite kötü fiyat iyiaynı token’ları içerdiği için basit ortalamaları, hangi sabit vektör tablosunu kullanırsanız kullanın eşittir; kosinüsü sayısal bir toleransla denetleyin.