kmRows = [
{rep: "lsa", k: 2, silh: 0.0174, ch: 728, db: 6.381, ari: -0.0471, nmi: 0.0118, big: 81.1},
{rep: "lsa", k: 3, silh: 0.0236, ch: 629, db: 6.533, ari: -0.0507, nmi: 0.0185, big: 67.6},
{rep: "lsa", k: 4, silh: 0.0246, ch: 566, db: 7.174, ari: -0.0243, nmi: 0.0153, big: 46.6},
{rep: "lsa", k: 5, silh: 0.0288, ch: 534, db: 6.410, ari: -0.0229, nmi: 0.0117, big: 50.1},
{rep: "lsa", k: 6, silh: 0.0262, ch: 491, db: 6.523, ari: -0.0171, nmi: 0.0117, big: 39.0},
{rep: "lsa", k: 8, silh: 0.0344, ch: 454, db: 5.873, ari: -0.0160, nmi: 0.0102, big: 35.8},
{rep: "lsa", k: 10, silh: 0.0391, ch: 423, db: 5.747, ari: -0.0094, nmi: 0.0100, big: 26.6},
{rep: "lsa", k: 12, silh: 0.0420, ch: 396, db: 5.565, ari: -0.0096, nmi: 0.0102, big: 22.9},
{rep: "lsa", k: 15, silh: 0.0440, ch: 360, db: 5.229, ari: -0.0083, nmi: 0.0099, big: 23.8},
{rep: "lsa", k: 20, silh: 0.0528, ch: 325, db: 4.921, ari: -0.0057, nmi: 0.0091, big: 16.4},
{rep: "lsa", k: 25, silh: 0.0560, ch: 288, db: 4.731, ari: -0.0052, nmi: 0.0101, big: 17.2},
{rep: "lsa", k: 30, silh: 0.0605, ch: 269, db: 4.554, ari: -0.0033, nmi: 0.0099, big: 12.7},
{rep: "lsa", k: 40, silh: 0.0647, ch: 241, db: 4.276, ari: -0.0014, nmi: 0.0081, big: 9.5},
{rep: "lsa", k: 50, silh: 0.0696, ch: 215, db: 4.105, ari: -0.0005, nmi: 0.0121, big: 8.7},
{rep: "minilm", k: 2, silh: 0.0977, ch: 2724, db: 4.240, ari: 0.0042, nmi: 0.0392, big: 51.2},
{rep: "minilm", k: 3, silh: 0.1018, ch: 2428, db: 3.741, ari: 0.0083, nmi: 0.0223, big: 42.7},
{rep: "minilm", k: 4, silh: 0.1042, ch: 2217, db: 3.583, ari: 0.0058, nmi: 0.0275, big: 34.9},
{rep: "minilm", k: 5, silh: 0.0770, ch: 1949, db: 3.603, ari: 0.0007, nmi: 0.0236, big: 25.7},
{rep: "minilm", k: 6, silh: 0.0808, ch: 1745, db: 3.563, ari: 0.0036, nmi: 0.0220, big: 24.4},
{rep: "minilm", k: 8, silh: 0.0621, ch: 1475, db: 3.553, ari: 0.0029, nmi: 0.0251, big: 17.3},
{rep: "minilm", k: 10, silh: 0.0736, ch: 1327, db: 3.331, ari: -0.0007, nmi: 0.0197, big: 16.0},
{rep: "minilm", k: 12, silh: 0.0744, ch: 1196, db: 3.427, ari: 0.0013, nmi: 0.0171, big: 12.7},
{rep: "minilm", k: 15, silh: 0.0720, ch: 1036, db: 3.401, ari: 0.0014, nmi: 0.0155, big: 9.7},
{rep: "minilm", k: 20, silh: 0.0704, ch: 867, db: 3.276, ari: 0.0013, nmi: 0.0159, big: 8.6},
{rep: "minilm", k: 25, silh: 0.0714, ch: 751, db: 3.242, ari: 0.0009, nmi: 0.0148, big: 5.8},
{rep: "minilm", k: 30, silh: 0.0718, ch: 667, db: 3.254, ari: 0.0010, nmi: 0.0152, big: 5.6},
{rep: "minilm", k: 40, silh: 0.0678, ch: 547, db: 3.233, ari: 0.0007, nmi: 0.0142, big: 4.9},
{rep: "minilm", k: 50, silh: 0.0605, ch: 468, db: 3.260, ari: 0.0007, nmi: 0.0142, big: 3.9},
{rep: "e5", k: 2, silh: 0.0936, ch: 2041, db: 4.757, ari: -0.0079, nmi: 0.0014, big: 63.8},
{rep: "e5", k: 3, silh: 0.0445, ch: 1679, db: 4.642, ari: -0.0000, nmi: 0.0327, big: 44.3},
{rep: "e5", k: 4, silh: 0.0438, ch: 1415, db: 4.439, ari: -0.0019, nmi: 0.0265, big: 40.1},
{rep: "e5", k: 5, silh: 0.0415, ch: 1220, db: 4.698, ari: 0.0007, nmi: 0.0183, big: 33.3},
{rep: "e5", k: 6, silh: 0.0223, ch: 1094, db: 4.765, ari: 0.0049, nmi: 0.0416, big: 29.6},
{rep: "e5", k: 8, silh: 0.0320, ch: 926, db: 4.479, ari: 0.0047, nmi: 0.0341, big: 24.2},
{rep: "e5", k: 10, silh: 0.0261, ch: 794, db: 4.566, ari: 0.0075, nmi: 0.0396, big: 19.4},
{rep: "e5", k: 12, silh: 0.0256, ch: 706, db: 4.598, ari: 0.0057, nmi: 0.0363, big: 16.0},
{rep: "e5", k: 15, silh: 0.0263, ch: 607, db: 4.670, ari: 0.0031, nmi: 0.0293, big: 12.5},
{rep: "e5", k: 20, silh: 0.0255, ch: 494, db: 4.651, ari: 0.0027, nmi: 0.0326, big: 9.4},
{rep: "e5", k: 25, silh: 0.0207, ch: 419, db: 4.703, ari: 0.0013, nmi: 0.0269, big: 8.2},
{rep: "e5", k: 30, silh: 0.0189, ch: 366, db: 4.663, ari: 0.0015, nmi: 0.0278, big: 5.5},
{rep: "e5", k: 40, silh: 0.0141, ch: 296, db: 4.584, ari: 0.0014, nmi: 0.0274, big: 4.4},
{rep: "e5", k: 50, silh: 0.0130, ch: 250, db: 4.572, ari: 0.0014, nmi: 0.0287, big: 4.6}
]11 Benzerlik, Kümeleme ve Konu Keşfi
Öğrenme hedefleri. Bu bölümden sonra şunları yapabilirsiniz:
- vektörlerinizin gerçekte neyi kodladığına uyan bir uzaklık seçmek ve ondan bir anlam çıkarmadan önce onu rastgele iki belgenin benzerliğine karşı kalibre etmek;
- okunamayacak kadar büyük bir derlemde yakın kopyaları bulmak ve sayının, seçtiğiniz eşiğe nasıl bağlı olduğunu söylemek;
- k-means (k-ortalamalar) çalıştırmak ve onun sizin adınıza yaptığı dört varsayımı adlandırmak;
- silhouette (siluet), Calinski-Harabasz ve Davies-Bouldin’i okumak ve üçünün birden işe yaramadığı durumları tanımak;
- “bu belge hiçbir kümeye ait değil” cevabını vermesine izin verilen, yoğunluk tabanlı (density-based) bir yöntem kullanmak;
- LDA, NMF ve “önce kümele, sonra betimle” yaklaşımlarını konu tutarlılığı (topic coherence) üzerinden ve tutarlılığın ölçemediği şey üzerinden karşılaştırmak;
- kümeleme, umduğunuz yapıyı geri getirmediğinde net bir hüküm bildirmek — daha iyisini bulduğu durum da dâhil;
- bir kümelemeyi, hiç görmediği bir etiket listesine göre değil, desteklemesi gereken kararın kendisine göre ölçmek.
11.1 Okuyamadığınız derlem
Bölüm 4, 40.000 etiketli Türkçe yorum üzerinde yedi temsili yarıştırıp bir lider tablosu üretti. Bölüm 5 ardından o etiketlerin nereden geldiğini sordu ve test etiketlerindeki %2’lik bir oynamanın, kazananın skorunu temiz etiketlerle ölçülmüş bir rakibin altına indirmeye yettiğini buldu. İki bölümün de etiketi vardı. Bu bölüm ise ikisinden de önce gelen soruyu soruyor: belgeler elinizde, hiç etiket yok ve birinin neyin etiketlenmeye değer olduğuna karar vermesi gerekiyor.
Olağan durum budur. Bir destek gelen kutusu, bir yıl boyunca toplanmış serbest metinli anket cevapları, kazınarak toplanmış ürün yorumları — belgeler bir sentiment sütunu olmadan gelir ve Bölüm 5’teki bütçe konuşması (“1.000 temiz etiket, %10 gürültülü 40.000 etiketle başa baş”) biri belgelerde ne olduğunu bilmeden başlayamaz bile.
Bu yüzden kurulumda derlem ve seed bilinçli olarak aynı; etiketler ise bir çekmecede kilitli. Aşağıdaki çıktı sırasıyla indirilen satır sayısını, birebir tekilleştirmeden sonra kalanları (ve silinen birebir kopyaları), etiket dağılımını, tabakalı altörneklemi, kelime ve karakter cinsinden uzunluğu (medyan, ortalama, 95. yüzdelik, en büyük) ve farklı kelime biçimi sayısını veriyor:
rows as downloaded 235,165
after deduplication 233,508 (1,657 exact duplicates)
label 1 (positive) 218,747 93.7%
label 0 (negative) 14,761 6.3%
stratified subsample 50,000 46,839 positive 3,161 negative
length, words median 19 mean 22.1 p95 55 max 305
length, characters median 132 mean 157.3 p95 393
distinct word forms 86,245
Aynı kaynak, aynı seed, Bölüm 4 ile aynı tekilleştirme — ama Bölüm 12 hazırlanırken fark edildiği üzere, aynı 50.000 satır değil. Bölüm 4 altörneklemini tek bir tabakalı (stratified) train_test_split ile çekmişti; bu bölüm grup grup çekti. İkisi de tabakalı, ikisi de 42 seed’ini kullanıyor, ikisi de 46.839 olumlu ve 3.161 olumsuz veriyor — ve 23.819 belgeyi, yani %47,6’sını paylaşıyorlar. “Aynı seed” ile “aynı örneklem” aynı şey değil ve bunu öğrenmenin tek yolu ikisini kesiştirip saymak.
Tokenizer da farklı, bu kez bilerek. Bölüm 4 Türkçeye duyarlı bir tr_lower ve [a-zçğıöşü]+ örüntüsünü kullanıyordu; bu bölüm bilinçli olarak standart str.lower() ve çıplak bir \w+ kullanıyor — yani hiç düşünmezseniz elinize geçecek olan şeyi. Küçük harfe çevirme farkı bu derlemde hiçbir şeyi değiştirmiyor, çünkü derlem zaten küçük harfle geliyor; örüntü farkı ise değiştiriyor, çünkü \w+ rakamları, _ işaretini ve Türk alfabesi dışındaki harfleri de tutuyor. Buradaki (86.245) ve oradaki (74.317) biçim sayılarının karşılaştırılabilir olmamasının sebeplerinden biri bu fark; öteki, satırların %52,4’ünün farklı belgeler olması. Birbirine karışmış iki neden var ve ikisini de ancak örneklemleri kesiştirdiğimiz için adlandırabiliyoruz. İki örüntü de birleştirici (combining) bir işareti harf saymıyor; bu ortak kör nokta, bu bölümün ilerisindeki bir kısmın (Bölüm 11.9) asıl konusu.
Etiketler mevcut ve bu sayfadaki hiçbir model onlara göre eğitilmiyor: ne temsiller, ne \(k\), ne algoritmalar. Ama “yalnızca puanlama için kullanıldılar” demek fazla basitleştirilmiş bir özet olurdu; o yüzden kesin konuşalım. Etiketler iki yerde karşımıza çıkıyor ve ikincisinde bir şey seçiyorlar. Birincisi, aşağıdaki \(k\) taramasının tamamında bildirilen düzeltilmiş Rand indeksinin (adjusted Rand index, ARI) cevap anahtarı onlar. İkincisi, Bölüm 11.10’un triyaj (öncelik sıralaması) eğrisini puanlarken esas aldığı şey de onlar; üstelik orada kümelerin okunma sırasını da onlar belirliyor. O sonucu bir oracle sonucu (bütün referans etiketleri bilen ideal bir sıralamanın sonucu) yapan da bu: gerçek bir kullanıcının elinde olmayacak bir bilgiyi kullanıyor. Bölüm 11.10 sayıyı bildirdiği yerde bunu söylüyor. Bütün deney bu disipline dayanıyor: “denetimsiz” bir hattı, gizlice baktığınız bir etiketi yeniden üretene kadar ayarlamak çok kolaydır ve ortaya çıkan sayı, etiketi olmayan bir derlemle karşılaşınca geçerliliğini koruyamaz.
Bölümün sonunda neyi bildireceği aşağıda; böylece ortasını, nereye gittiğini bilerek okuyabilirsiniz:
| ne sorduk | ne geldi |
|---|---|
| Birebir tekilleştirmeden sonra kaç yakın kopya kalıyor? | Belgelerin %0,30’u; ama eşiği 0,1 oynatırsanız %1,06 |
| Kümeleme duygu etiketlerini geri getiriyor mu? | Hayır. Herhangi bir yerdeki en iyi ARI: 0,0083 |
| İçsel geçerlilik indeksleri kaç küme olduğunda anlaşıyor mu? | Hayır. Üç temsil 50, 4 ve 2 dedi |
| Yoğunluk tabanlı bir yöntem küme buluyor mu? | Hayır. Hiçbir zaman 3’ten fazla değil, %53–100 gürültüyle |
| En iyi konu tutarlılığı puanı en iyi konuyu işaretliyor mu? | Hayır. En yüksek puanlı konu tokenizer enkazıydı |
| Demek ki kümeleme değersizdi? | Hayır — ve asıl ilginç kısım da bu |
| Peki gerçekte ne buldu? | Yayına alınmış bir Unicode hatası ve okumanın %13’ü karşılığında şikâyetlerin %56’sı |
Son iki satır retorik bir numara değil. Yukarıdaki yedi ana cevaptan dördü düpedüz olumsuz ve bölüm yine de gerçek iş gören bir kümeleme hattıyla bitiyor. Birinden diğerine geçmek soruyu değiştirmeyi gerektiriyor; sorunun ne zaman yanlış olduğunu fark etmeyi öğrenmek ise aşağıdaki algoritmaların hepsinden daha çok işinize yarar.
Neye bakacağız. Önce, atlarsanız her kümeleme yönteminin kötü cevapladığı soru: belgeleriniz için “benzer”in ne anlama geldiği. Sonra bölümün en ucuz kazancı — herhangi bir kümeleme çalıştırmadan önce yakın kopyaları temizlemek. Sonra k-means ve dört varsayımı, öğreticilerin (tutorial) önerdiği yöne gitmeyen bir tarama ve kümelerin biçimi varsayıma uymadığında ne yapılacağı. Sonra konu modelleri ve nihayet bu bölümün asıl konusu: başarısız bir kümelemenin hâlâ neye değdiği.
11.2 Kümeleyebilmeniz için “benzer”in ne anlama gelmesi gerekir
Bu bölümdeki her algoritma, birbirine yakın olan noktaları gruplamanın bir yolu. Hiçbiri “yakın”ı tanımlamıyor. Onu siz tanımlıyorsunuz — bir temsil ve bir uzaklık seçtiğinizde; ve bu seçim, cevabı kümeleme algoritması seçiminden çok daha fazla belirliyor.
11.2.1 Üç uzaklık ve her birinin varsayımı
Vektör olarak temsil edilen belgeler için üç ölçüt neredeyse bütün pratiği kapsıyor.
\[ \operatorname{cos}(a, b) = \frac{a \cdot b}{\lVert a \rVert \, \lVert b \rVert} \qquad d_{\text{euc}}(a, b) = \lVert a - b \rVert_2 \qquad J(A, B) = \frac{|A \cap B|}{|A \cup B|} \]
Kosinüs açıyı ölçer, uzunluğu görmezden gelir. Metin için genellikle istediğiniz de budur: aynı şey hakkındaki 300 kelimelik bir yorumla 30 kelimelik bir yorumun benzer olması gerekir, oysa ham sayım vektörlerinin büyüklükleri on kat farklıdır. Öklit uzaklığı ise uzunluğu ciddiye alır; büyüklüğün anlam taşıdığı yerde doğru seçim odur — ve şuna dikkat edin: birim uzunluktaki vektörlerde bu iki ölçüt çiftleri aynı biçimde sıralar, yani sıralama açısından aradaki fark ortadan kalkar.1 Jaccard ise vektörler yerine kümeler üzerinde çalışır; onu yakın kopya düzeneğinin (Bölüm 11.3) temeli yapan şey de budur.
cosine similarity (kosinüs benzerliği) — iki vektör arasındaki açının kosinüsü; 1 aynı yön, 0 dik demektir. Vektörlerin ne kadar uzun olduğunu görmezden gelir; bu, metin için çoğu zaman işe yarar, arada bir de sorun çıkarır. ↩︎
11.2.2 0,98’lik bir kosinüs sandığınız anlama gelmiyor
Pratikte en çok zamana mal olan tuzak burada. Ham bir kosinüs benzerliği değeri tek başına yorumlanamaz. Yalnızca aynı modelin ilgisiz belgeler için ürettiği benzerlik dağılımına göre yorumlanabilir.
3.000 rastgele yorum aldık ve aralarındaki 4.498.500 çiftin hepsini dört ayrı uzayda puanladık:
| uzay | boyut | ortalama kosinüs | std. sapma | 1.–99. yüzdelik |
|---|---|---|---|---|
| tf-idf (seyrek) | 23.971 | 0,0182 | 0,0287 | 0,000 – 0,130 |
| LSA (SVD ile 256’ya) | 256 | 0,0654 | 0,0794 | −0,026 – 0,330 |
| MiniLM | 384 | 0,3051 | 0,1503 | −0,009 – 0,669 |
| multilingual-E5 | 768 | 0,8547 | 0,0278 | 0,783 – 0,916 |
Aynı kosinüs dört farklı anlama geliyor
Kesikli çizgiye bakın. 0,8’in üstündeki belge çiftlerini “benzer” diye işaretleyen bir pano, tf-idf, LSA ya da MiniLM altında neredeyse hiçbir şeyi işaretlemez; E5 altında ise neredeyse bütün derlemi işaretler, çünkü orada ilgisiz iki yorum bile 0,855 alıyor. Eşik değişmedi. Geometri değişti.
Ortak hiçbir yanı olmayan iki yorum E5 altında ortalamada 0,855 alıyor ve bütün rastgele çiftlerin %98’i 0,78 ile 0,92 arasına düşüyor. 0,8’in üstünü “benzer belgeler” diye işaretleyen bir pano, neredeyse bütün derlemi işaretlerdi. Mutlak sayı belgelerinizin hiçbir özelliğini yansıtmıyor; encoder’ın (kodlayıcı) nasıl eğitildiğinin bir özelliği: anizotropisi. Bu, bütün vektörlerin kabaca aynı yöne bakma eğilimi demek; birbiriyle ilgisiz metinler bile büyük bir ortak bileşeni paylaşıyor. Bölüm 3’ün kelime vektörlerinde ölçtüğü ve bağlamsal modellerde daha da güçlü olduğunu not ettiği geometrinin aynısı bu.
Ayrıca kullanılabilir aralığın, nominal aralıkla aynı olmadığına dikkat edin. Hem E5 hem tf-idf, rastgele çiftlerinin %98’ini yaklaşık 0,13 genişliğinde bir pencerenin içine koyuyor — ama E5’in penceresi nominal olarak 2 uzunluğunda bir aralığın içinde ve bunun %6,6’sını kullanıyor, üstelik en sağda sıkışmış hâlde. tf-idf’in penceresi ise sıfırdan başlıyor; yani 0,13’lük bir puan gerçekten de o uzayın ürettiğinin tepesine yakın. Aynı genişlik, bambaşka anlam — ve ikisinden yalnızca biri, göründüğü gibi 0 ile 1 arasında bir oran gibi davranıyor.
Eşik koymadan önce kalibre edin. Herhangi bir benzerlik kesme noktası seçmeden önce kendi derleminizden birkaç bin rastgele çifti kendi encoder’ınızla puanlayın ve dağılıma bakın. Bunu atlarsanız, ölçmediğiniz bir ölçeğe karşı eşik seçmiş olursunuz. Steck vd. (2024) bu argümanın daha güçlü sürümünü kuruyor: bazı modellerde kosinüs benzerliği, anlamlı hiçbir benzerlik kavramına karşılık gelmiyor; \([-1, 1]\) aralığıyla sınırlı olması ise ona sahte bir yüzde havası veriyor.
11.2.3 Üç bölümdür peşimizi bırakmayan çift
Bu çift Bölüm 4’te ortaya çıktı; Bölüm 6 ve Bölüm 7’de yeniden karşımıza çıktı. Bölüm 4 bir başarısızlıkla bitmişti. Anlamları zıt, dörder kelimelik iki Türkçe yorum vardı ve hem unigram tf-idf hem de ortalaması alınmış kelime vektörleri ikisine de birebir aynı puanı vermişti (o bölümün not ettiği gibi kelime bigram’ları ikisini ayırıyor — ama yalnızca sıra bilgisi iki kelimelik bir pencereye sığdığı için):
a = "kalite iyi fiyat kötü"
b = "kalite kötü fiyat iyi"
Bölüm 6 bunu düzeltti, çünkü bir n-gram modeli sırayı okur, kelime torbası (bag of words) okumaz. Cümle embedding’leri ise anlam üzerinde, onlarca, hatta yüze yakın dilde ve cümlenin tamamına attention (dikkat mekanizması) uygulanarak eğitiliyor. Bariz beklenti, bu sorunu onların da düzeltmesi.
Düzeltmiyorlar. Bir kümeleme hattının ayırmaya ihtiyaç duyduğu şeyleri ayırmak üzere tasarlanmış, elle yazılmış beş çift ölçtük. Her puan iki kez bildiriliyor: ham kosinüs olarak ve modelin yukarıdaki tabloda yer alan kendi rastgele çift dağılımına göre hesaplanmış bir \(z\)-skoru olarak. Ölçekleri bu kadar farklı modelleri karşılaştırmanın tek yolu bu.
Bir \(z\)-skoru, ham bir sayıyı “bu, ortalamanın kaç standart sapma üstünde?” diye yeniden ifade eder: \(z = (x - \mu)/\sigma\). Burada \(\mu\) ve \(\sigma\), yukarıdaki tablodaki rastgele çift kosinüslerinin ortalaması ve yayılımı. Yani \(z = 4\), modelin ham ölçeği ne olursa olsun, çiftin rastgele seçilmiş iki belgeden çok daha benzer olduğu anlamına gelir. E5’in 0,9894’ü ile tf-idf’in 1,0000’i kosinüs olarak birbirine benziyor, \(z\)-skoru olarak ise aralarında dağlar kadar fark var.
| çift | tf-idf | MiniLM | E5 | ||||
|---|---|---|---|---|---|---|---|
| kos | \(z\) | kos | \(z\) | kos | \(z\) | ||
| çelişki | aynı kelimeler, zıt iddialar | 1,0000 | 34,2 | 0,9649 | 4,4 | 0,9894 | 4,8 |
| anlamdaş (paraphrase) | aynı iddia, farklı kelimeler | 0,5349 | 18,0 | 0,9479 | 4,3 | 0,9827 | 4,6 |
| kutup değişimi | tek kelime hükmü değiştiriyor | 0,5687 | 19,2 | 0,6518 | 2,3 | 0,9525 | 3,5 |
| olumsuzlama | tek ek hükmü değiştiriyor | 0,4999 | 16,8 | 0,7201 | 2,8 | 0,9528 | 3,5 |
| ilgisiz | farklı konu, aynı duygu | 0,1626 | 5,0 | 0,1871 | −0,8 | 0,8785 | 0,9 |
Birinci satırı ikinciyle karşılaştırarak okuyun. Üç temsilde de çelişki çifti, gerçek anlamdaş çiftten daha yüksek puan alıyor. Zıt şeyler öne süren iki cümle, aynı şeyi farklı kelimelerle söyleyen iki cümleden daha benzer kabul ediliyor — tf-idf’e göre de, MiniLM’e göre de, E5’e göre de.
Üç gözlem, en önemlisinden başlayarak:
- Cümle embedding’leri Bölüm 4’teki başarısızlığı onarmadı. E5 çelişki çiftine 0,9894 veriyor. Sorun hiçbir zaman seyreklik değildi, hiçbir zaman söz dağarcığı da değildi. Anlamı hâlâ kelime sırası taşıyor ve havuzlanmış cümle vektörü (pooling: token vektörlerinin ortalaması alınarak tek bir vektöre indirgenmiş hâli) hâlâ çoğunlukla taşımıyor.
- Bu beş çiftte MiniLM, kutupluluğu E5’ten daha keskin ayırıyor. MiniLM anlamdaş puanından kutup değişimine 2,0 \(z\), olumsuzlamaya 1,5 \(z\) düşüyor; E5 ikisine de 1,1 \(z\) düşüyor. Bariz sonuca atlamayın. Beş çift iki modeli sıralayamaz ve Bölüm 11.10 derlem ölçeğinde tam tersini ölçüyor: E5 olumsuz yorumları 4,23× yoğunlaştırırken MiniLM 2,79× yoğunlaştırıyor. Bu, bölümün kendi kuralının bu deneye de uygulanması — bir probe ile bir ölçüm uyuşmadığında ölçüme inanın. Ayakta kalan şey daha zayıf ama daha yararlı iddia: bir model genel olarak daha iyi, sizin önemsediğiniz tek eksende ise daha kötü olabilir; dolayısıyla o ekseni ayrıca ölçmeye değer.
- tf-idf, kutup değişimini anlamdaş çiftin üstüne koyuyor (0,5687; anlamdaş çift 0,5349) ve bu çifti ters sıralayan tek temsil de odur; kelime anlamı diye bir kavramı olmayan bir yöntemin yapması gereken de bu: kargo çok hızlı geldi ile kargo çok yavaş geldi dört kelimenin üçünü paylaşıyor.
1. maddeyi aklınızda tutun. Daha tek bir kümeleme algoritması çalıştırmadan şunu öngörüyor: bu geometrilerin hiçbirinin ilk ayrılacağı yön duygu olmayacak — ve o öngörünün sınandığı yer Bölüm 11.5.
Bu tablonun sınırları üzerine. Bir görüşü desteklemek için tek bir kişinin yazdığı beş çift, bu kitaptaki en zayıf kanıt türü. Burada olmasının sebebi, derlem ölçeğindeki bir sonucun yerini almak değil, onu açıklamak. Yukarıdaki üç gözlemden yalnızca birincisi derlem ölçeğindeki sayılar karşısında ayakta kalıyor: Bölüm 11.5 üç geometriden hiçbirinin duyguya göre ayrılmadığını doğruluyor; Bölüm 11.10 ise 2. gözlemdeki model sıralamasıyla doğrudan çelişiyor. Bir probe için doğru sonuç budur. Probe hipotezler üretir, onları karara bağlamaz. Bir probe ile bir ölçüm uyuşmadığında ölçüme inanın — probe’u siz yazmış ve seviyor olsanız bile.
11.3 Yakın kopyalar: elde edilebilecek en ucuz kazanç
Herhangi bir şeyi kümelemeden önce, zaten birbirinin kopyası olan belgeleri çıkarın. Bölüm 11.1, karakter dizilerini karşılaştırarak 1.657 birebir tekrarı çıkardı. Birebir eşleşme zayıf bir testtir — tek bir karakter değişince işe yaramaz — ve tekrarlanan kalıp metin üzerine kurulmuş bir küme, kalıp metni ölçüyordur.
11.3.1 Shingling, MinHash ve neden her çifti karşılaştırmadığınız
50.000 belgenin bütün çiftlerini karşılaştırmak \(1{,}25 \times 10^9\) karşılaştırma demek. Bundan kurtulmanın standart yolu üç adımdan oluşur (Broder 1997):
- Shingle’lara bölme. Her belgeyi, örtüşen \(k\)-gram’lardan oluşan bir kümeye çevirin. Kelime shingle’ları yerine bilerek karakter 5-gram’ları kullandık: Türkçenin eklemeli yapısı yüzünden neredeyse birebir aynı iki yorum birkaç kelime biçiminde farklılaşırken hemen hemen bütün karakter dizilerini paylaşabiliyor.
- MinHash. Kümeyi 128 kez hashleyin ve her hash fonksiyonunun verdiği en küçük değeri saklayın. İki belgenin belirli bir minimumu paylaşma olasılığı, Jaccard benzerliklerine eşittir; yani 128 sayı, kümeleri saklamadan \(J\)’yi kestirir.
- Bantlara bölün ve kovalara atın (LSH) (Indyk ve Motwani 1998). LSH, locality-sensitive hashing, yani benzer girdileri büyük olasılıkla aynı kovaya düşüren yerelliğe duyarlı hashleme demek. 128 değeri bantlara bölün ve her bandı hashleyin; aynı hash değerine düşen belgeler aynı kovaya girer. Yalnızca en az bir bantta çakışan belgeleri karşılaştırın. Eşiğin altındaki çiftler neredeyse hiç çakışmaz; dolayısıyla \(10^9\) karşılaştırmanın neredeyse tamamı hiç yapılmaz.
MinHash — bir kümenin sabit uzunluktaki taslağı (sketch); iki taslağın bir konumda uyuşma şansı, özgün kümelerin Jaccard benzerliğine eşit olacak şekilde kuruluyor. Kümeleri saklamadan örtüşmeyi kestirmenizi sağlar. ↩︎
1,25 milyar karşılaştırma neden hiç yapılmıyor
2. ve 3. aşamalar, büyüklüğü bilinmeyen bir kümeyi sabit 128 sayıya çeviriyor; 4. aşamayı mümkün kılan şey de bu. 5. aşama, sağ kalanlar üzerinde tam Jaccard’ı hesaplıyor; yani LSH size verdiği bir çift hakkında vardığınız sonucu asla değiştirmiyor — değiştirdiği şey, size hangi çiftleri verdiği.
Yaklaşıklığın gerçekte nerede devreye girdiği — ve orası tahmin edeceğiniz yer değil. 4. aşama, 5. aşamayı geçecek hiçbir yanlış pozitif üretmiyor; ama yanlış negatif üretiyor: gerçekten benzer bir çift hiçbir bantta çakışmayabilir ve o zaman hiç puanlanmaz. Ne sıklıkta? datasketch, iki hata türünü istediğiniz eşikte dengelemek için 128 hash’imizi \(r\) satırlık \(b\) banda bölüyor; bunu \(b \cdot r \le 128\) kısıtıyla yapıyor. Jaccard benzerliği \(J\) olan bir çift \(1 - (1 - J^{r})^{b}\) olasılıkla çakışıyor. threshold=0.8’de \(b=9\), \(r=13\) seçiyor; bu da 128 permütasyonun 117’sini kullanıp kalan on birini atıyor; hash bütçenizi sayıyorsanız bunu bilmeniz gerekir. Aşağıda sol sütun Jaccard benzerliği, sağ sütun o çiftin en az bir bantta çakışıp incelemeye alınma olasılığı:
J P(pair is even looked at)
0.9 0.93
0.8 0.40
0.7 0.08
Bu olasılığı \(J\)’ye karşı çizerseniz S biçimli bir eğri elde edersiniz: eşiğin epey altında sıfıra, epey üstünde bire yapışık, arada dik bir geçiş. datasketch \(b\) ile \(r\)’yi yanlış pozitif ve yanlış negatif olasılıklarını dengeleyecek biçimde seçtiği için eşik bu dik geçişin içine düşüyor (bu \(b\) ve \(r\) için en dik nokta \(J \approx 0{,}84\)). Eşikte oturan bir çiftin bulunma şansı %40. Bu bir hata değil, tasarımın sonucu; yöntemin, kendisini mümkün kılan hız uğruna recall’dan (duyarlılık: bulunması gereken çiftlerden gerçekten bulunanların payı) feragat ettiği yer. Ama bu, sonraki tablodaki sayıların alt sınır olduğu ve tam da sizin işaret ettiğiniz sınırda en gevşek oldukları anlamına geliyor. Yakın kopya sayılarını her zaman “en az” diye bildirin, asla “tam olarak” diye değil.
Ardından sağ kalan aday çiftler üzerinde union-find çalıştırdık; böylece yakın kopyalardan oluşan bir zincir birkaç çift yerine tek bir grup olarak sayılıyor. Union-find, “bunların hepsi birbirine bağlı” bilgisini tutmanın standart yolu: her belge kendi grubunda başlar, sağ kalan her çift iki grubu birleştirir ve \(a \sim b \sim c\) zinciri, \(a\) ile \(c\) hiç karşılaştırılmamış olsa bile üç üyeli tek bir grup olarak biter.
11.3.2 Sayı eşiğe bağlı, hem de keskin biçimde
Ne kadar sileceğinize tek bir sayı karar veriyor ve bu, kimsenin size hazır veremeyeceği bir sayı: iki yorum hangi Jaccard benzerliğinde “aynı yorum” sayılır? Onu oynatın ve cevabın onunla birlikte oynadığını izleyin.
| Jaccard eşiği | grup | fazlalık belge | derlemdeki pay | en büyük grup | süre |
|---|---|---|---|---|---|
| ≥ 0,9 | 57 | 60 | %0,12 | 3 | 28,0sn |
| ≥ 0,8 | 131 | 151 | %0,30 | 6 | 27,4sn |
| ≥ 0,7 | 265 | 529 | %1,06 | 61 | 28,4sn |
Eşiği 0,8’den 0,7’ye çekmek, fazlalık belge sayısını 3,5 katına, en büyük grubu ise on katına çıkarıyor. Bu, yöntemin bir hatası değil; derlemin görünüşü bu. \(J \ge 0{,}8\)’de üç grup:
group 1 "teşekkürler hepsiburada.com ;)"
"teşekkürler hepsiburada!"
"teşekkürler hepsiburada....."
group 2 "güzel tavsiye ederim"
"ürün çok güzel tavsiye ederim."
"isıtması çok güzel tavsiye ederim"
group 3 "herkese tavsiye ederim"
"herkese tavsiye ederim,fiy"
"herkese tavsiye ederim :)"
1. grup kalıp metin ve gitmesi gerekiyor. 2. grup ise üç farklı ürün hakkında genel geçer bir şey söyleyen üç farklı insan; ikisini silmek gerçek veriyi çöpe atmak demek. Yeterince düşük bir eşikte “yakın kopya” ile “kısa ve genel geçer” aynı kategori hâline geliyor; en büyük grubun \(J \ge 0{,}7\)’de 61’e sıçramasının sebebi de bu.
Savunulabilir bir varsayılan. \(J \ge 0{,}8\)’de tekilleştirin, sonra sonucu kabul etmeden önce en büyük beş grubu okuyun. En büyük grup kalıp metin değil de kısa ve genel geçer metinse eşiği yükseltin. Bu bölüm \(J \ge 0{,}8\)’de kaldı ve geriye 49.849 belge bıraktı; bu noktadan sonraki her sayı bu belgeler üzerinde hesaplandı.
Bölüm 8.2, tekilleştirmeyi ön eğitim derlemleri için etkisi ölçülmüş bir kalite ayarı olarak ele alıyor. Orada risk çok daha yüksek; Lee vd. (2022) gerçek kazanımlar buldu, Penedo vd. (2024) ise en agresif tekilleştirmenin veriyi kötüleştirdiğini gördü. Aynı gerilim burada, beş büyüklük mertebesi daha küçük bir derlemde, minyatür hâlinde karşımıza çıkıyor.
SimHash (Charikar 2002) aynı problemi farklı bir taslakla çözüyor: belge başına tek bir bit vektörü üretiyor ve Hamming uzaklığını ölçüyor. Bu yüzden saklaması daha ucuz; yeni bir belgeyi mevcut büyük bir indeksle karşılaştırmanız gerektiğinde de doğal bir seçim. SimHash’i web ölçeğinde çalıştırmanın hikâyesini Manku vd. (2007) anlatıyor. Tek seferlik bir derlem denetimi için ise LSH’li MinHash’in davranışını anlamak daha kolay ve datasketch onu bir düzine satırda gerçekleştiriyor.
11.4 Üç temsil ve maliyetleri
Bundan sonraki her şey aynı 49.849 belge üzerinde, üç geometride çalışıyor. Bu geometriler, bir uygulayıcının 2026’da gerçekten aralarından seçim yaptığı yelpazeyi kapsayacak biçimde seçildi.
| temsil | boyut | kurma süresi | notlar |
|---|---|---|---|
| tf-idf → LSA | 256 | 2,6sn | kelime tf-idf, SVD ile 256’ya; GPU yok, tamamen deterministik |
| MiniLM | 384 | 40sn | paraphrase-multilingual-MiniLM-L12-v2, 117,7M parametre, 1.246 belge/sn |
| multilingual-E5 | 768 | 104sn | intfloat/multilingual-e5-base, 278,0M parametre, 478 belge/sn |
İki ayrıntıyı özellikle belirtelim, çünkü ikisi de sonuçları değiştiriyor ve ikisi de kolayca atlanıyor.
SVD isteğe bağlı değil. Buradaki ham tf-idf, belge başına 19,3 sıfır olmayan girdiyle 23.971 boyutlu. Önemli olan teşhis ölçütü göreli kontrast: belirli bir belge için, en uzak komşusunun en yakın komşusundan ne kadar daha uzakta olduğu, \((d_{\max} - d_{\min}) / d_{\min}\). Bu sayı sıfıra yakınsa “en yakın”, “en uzak”tan anlamlı biçimde farklı değildir ve uzaklık tabanlı her yöntem gürültü üzerinde çalışıyordur. 300 sorgu belgesi üzerinde ölçülen medyan göreli kontrast (çıktıdaki median relative contrast):
median relative contrast
tf-idf 0.539
LSA (256) 2.116
MiniLM 4.911
E5 3.009
Elli bir belge orijinde duruyor. min_df=3, max_df=0.5, 49.849 belgeden 51’inin içerdiği bütün token’ları sildi; bu yüzden onların LSA satırları tam olarak sıfır ve \(\ell_2\)-normalleştirilemiyorlar. Orijinde — bileşenlerinin tamamı sıfır olan noktada — duruyorlar; oraya en yakın küme hangisiyse ona atanıyorlar ve bu bölümdeki her LSA tablosunda sayılıyorlar. Elli bin içinden elli bir tane hiçbir sayıyı oynatmaz, ama “bütün vektörlerim birim uzunlukta” cümlesi yine de yanlıştı ve bunu yalnızca kontrol ettiğimiz için biliyoruz.
tf-idf sorgularının %0,6’sında başka bir belge tam olarak 0 kosinüs uzaklığında oturuyor; bu da \(d_{\min} = 0\) demek ve oranı sonsuz yapıyor. Sıfır uzaklık, kosinüs benzerliğinin bir olması demektir; yani tf-idf vektörleri birbiriyle orantılı iki yorum. 19 kelimelik yorumlarda bu, iki kişi aynı kısa cümleyi yazdığında hep oluyor. (Ters durum, yani hiç ortak terim bulunmaması — ki burada olağan — kosinüs benzerliği 0, uzaklık 1 verir ve zararsızdır: \(d_{\max}\) tarafına düşer.) Oranı sonsuz çıkan bu sorgular bir epsilon ile yamanmak yerine medyandan çıkarıldı, çünkü uzayın gerçek bir özelliğini yansıtıyorlar. Kesilmiş SVD ile 256 boyuta indirmek varyansın %29,9’unu koruyor ve kontrastı dört katına çıkarıyor. (Kesilmiş SVD, ortalamayı çıkarma adımı atlanmış bir PCA’dır, yani temel bileşenler analizidir: varyansı en çok açıklayan yönleri tutar; ortalamayı çıkarmamak da seyrek matrisin seyrek kalmasını sağlar.) Bu indirgeme kendi başına bir konu modeli ve bir adı da var — latent semantic analysis (örtük anlamsal analiz) (Deerwester vd. 1990) — bu yüzden Bölüm 11.8 onu ek bir maliyet olmadan yeniden kullanabiliyor.
E5’in böyle bir onarıma ihtiyaç duymadığına dikkat edin; oysa 1.–99. yüzdelik bandı 0,133 genişliğinde, yani tf-idf’in 0,130’uyla kabaca aynı. Problemi tek başına bant genişliği teşhis etmiyor; kontrast ediyor. Kontrast uzaklıklar (\(1 - \cos\)) üzerinden hesaplanıyor ve orada iki bant yer değiştiriyor: E5’in rastgele çift uzaklıkları sıfıra yakın (0,08–0,22), dolayısıyla 0,13’lük bir yayılım onlara göre büyük; tf-idf’inkiler ise bire yakın (0,87–1,00) ve aynı yayılım orada küçük kalıyor.
E5’in ön ekine ihtiyacı var. multilingual-E5 modelleri query: ve passage: işaretleyicileriyle eğitiliyor ve bunlar olmadan ölçülebilir biçimde farklı davranıyorlar (Wang vd. 2024). Kümeleme gibi simetrik bir görev için model kartı iki tarafa da query: konmasını öngörüyor; biz de öyle yaptık. Bunu unutmak, embedding hatlarındaki en yaygın sessiz hatalardan biri: hiçbir şey çökmez, sayılar sadece daha kötü olur.
E5 için yapılması gereken ama yapmadığımız ablasyon. Ablasyon, bir adımı çıkarıp (ya da ekleyip) sonucun nasıl değiştiğini ölçen kontrol deneyi. 0,8547’lik bir rastgele çift ortalaması, bu embedding’lerin tek bir baskın yön paylaştığını söyler. Onu kaldırmak tek satır — Bölüm 3’te gördüğümüz ortalama çıkarma: derlem ortalamasını çıkarın, sonra yeniden normalleştirin: X -= X.mean(0); X /= np.linalg.norm(X, axis=1, keepdims=True) — ve aşağıdaki her olumsuz sonuç için bariz kontrol budur. Bölüm 11.6’daki düz silhouette eğrisi ve Bölüm 11.7’deki %99,5’lik HDBSCAN gürültü oranı merkezlemeden sonra da ayakta kalıyorsa, bunlar derlemin özellikleridir. Kalmıyorsa, bunlar encoder’ın anizotropisinden kaynaklanıyordu ve biz ölçüm aracının ürettiği yapay bir örüntüyü veri hakkında bir bulgu diye raporlamış olurduk. Aynı kontrolün daha güçlü biçimleri de var: ilk birkaç temel bileşeni de kaldırmak (“all-but-the-top”, Mu vd. (2018)) ya da beyazlatma (whitening: vektörleri kovaryans birim matris olacak biçimde döndürüp yeniden ölçeklemek). Hiçbirini çalıştırmadık; aşağıdaki her olumsuz sonucu bu eksikliği akılda tutarak okuyun. Herhangi birini alıntılamadan önce çalıştırılacak ilk şey budur.
11.5 k-means ve sizin adınıza yaptığı dört varsayım
k-means boşuna varsayılan değil: basit, hızlı ve Lloyd’un algoritması (Lloyd 1982) birkaç geçişte yakınsıyor. \(k\) tane merkez seçin, her noktayı en yakın merkeze atayın, her merkezi kendisine atanan noktaların ortalamasına taşıyın, tekrarlayın.
Amaç fonksiyonunu yazmak varsayımları görünür kılıyor. k-means şunu en aza indiriyor:
\[ \sum_{i=1}^{k} \sum_{x \in C_i} \lVert x - \mu_i \rVert^2 \]
ve bunu yaparken sizi, hiçbirini kimsenin seçmediği dört şeye bağlıyor:
- Kümeler küreseldir. Amaç fonksiyonu yalnızca bir merkeze olan uzaklığı ölçüyor, dolayısıyla uzamış ya da eğri bir grubu temsil edemiyor.
- Kümelerin yayılımı benzerdir. Sıkı bir küme ile dağınık bir küme aynı ölçekte puanlanıyor; sonuçta dağınık olan parçalanıyor ve parçaları komşularına dağıtılıyor.
- Her nokta bir kümeye aittir. Aykırı değer sınıfı yok. Hiçbir şeye benzemeyen bir belge bile en az yanlış olan merkeze atanıyor.
- \(k\)’yi zaten biliyorsunuz. O bir girdi, çıktı değil.
k-means (k-ortalamalar) — her noktayı en yakın grup merkezine atayıp merkezleri yeniden hesaplamayı tekrarlayarak noktaları \(k\) gruba bölüyor. Hızlı; karşılığında sizi küresel, benzer büyüklükte ve herkesi kapsayan gruplara mecbur bırakıyor. ↩︎
Dört varsayım, çizilmiş hâliyle
Bunların hiçbiri hata değil; amaç fonksiyonu olması gerektiği gibi çalışıyor. Bir merkeze olan karesel uzaklığı en aza indirmek, grupların yuvarlak, eşit yayılımlı ve kapsayıcı olduğu varsayımının ta kendisi. Verileriniz bu varsayıma uymuyorsa algoritma size bunu söylemez; sadece bir bölümleme döndürür.
Amaç fonksiyonunun değil, algoritmanın kendisinin bir özelliği de önemli. Lloyd’un algoritması başladığı yerden yalnızca yokuş aşağı yürür; bu yüzden amaç fonksiyonunun yerel bir minimumunda durur ve farklı başlangıç merkezleri farklı bölümlemeler verebilir. Uygulamaların algoritmayı birkaç kez çalıştırıp (n_init) amaç değeri en düşük olan sonucu tutması bundandır. k-means++ başlatmasını kullanın (Arthur ve Vassilvitskii 2007): her yeni başlangıç merkezini, o ana kadar seçilmiş merkezlere olan karesel uzaklığıyla orantılı bir olasılıkla seçer, yani başlangıçları birbirinden uzağa yayar. scikit-learn’ün varsayılanıdır ve rastgele yeniden başlatma piyangosunun, yani sonucun şanslı başlangıç noktalarına bağlı olmasının en kötü kısmını ortadan kaldırır — ama dört varsayımın hiçbirine çare olmadığını da unutmayın.
11.5.1 Tarama
k-means’i üç temsilin hepsinde, \(k\)’nin 2 ile 50 arasına yayılan on dört değeriyle çalıştırdık ve her bölümlemeyi dört ayrı şekilde puanladık. Puanların üçü içsel: yalnızca vektörleri kullanıyorlar, yani etiketi olmayan bir derlemde de hesaplanabiliyorlar — bu bölümün konusu da o durum. Dördüncüsü dışsal: bölümlemeyi gizli duygu etiketleriyle karşılaştırıyor ve cevap anahtarı o.
On dört \(k\) değeri, üç temsil, dört puan ve küme büyüklüğü
Dikkat edilecek biçim, bir biçimin yokluğu. Hiçbir eğride belirgin bir dirsek noktası yok, hiçbir silhouette 0,11’e ulaşmıyor ve ARI ayarında her çizgi sıfır hizasında dümdüz uzanıyor. Düğmeyi değiştirin ve dört puanı tek tek değil, birbiriyle karşılaştırarak okuyun.
Düğmeyi ARI’ye getirin ve sıfırdaki kesikli çizgiye bakın: rastgele bir bölümlemenin aldığı puan. Üç eğri de tam onun üstünde oturuyor.
11.5.2 Taramayı okumak
Üç temsil ve on dört \(k\) değeri içeren bir tablo birkaç şekilde okunabilir ve bu okumaların çoğu birilerini olduğundan iyi gösterir. İşte hiçbir temsili kayırmayan okuma.
Önce dışsal karar, çünkü tartışmaya kapalı. Taramanın tamamındaki en iyi ARI 0,0083; MiniLM’de \(k=3\) noktasında. ARI şansa göre düzeltilmiş, yani 0,0 rastgele atamanın aldığı puan, 1,0 ise kusursuz eşleşme. Birkaç girdi negatif. Normalleştirilmiş karşılıklı bilgi (normalized mutual information, NMI; aşağıda Bölüm 11.6’da tanımlanıyor) en fazla 0,0416’ya çıkıyor. Üç temsil üzerindeki 42 kümelemenin hiçbiri duygu etiketini ortaya çıkaramadı.
Bölüm 11.2 bunu zaten öngörmüştü. Bir temsil çelişki çiftine anlamdaş çiftten daha yüksek puan veriyorsa, o geometride kutupluluk baskın değişim ekseni değildir — ve k-means baskın eksenler boyunca bölüyor, dolayısıyla başka bir şeye göre bölecek. İddianın gücüne dikkat edin: kutupluluk geometriden yok olmuş değil. Bölüm 11.10 aynı E5 vektörlerinden 4,23× sinyal çıkarıyor, Bölüm 4 da bir kelime torbası temsilinden 76,21 macro-F1 almıştı. Denetimli bir yöntem ikincil bir yönü arayabilir, çünkü etiketler ona hangisini bulacağını söylüyor. Denetimsiz bir yöntem bunu yapamaz, o yüzden bunun yerine baskın yönü raporlar. Kümeleme başarısız olmadı; kendisine verilen yapıyı sadakatle raporladı.
İçsel indeksler ne birbirleriyle ne de kendileriyle uyuşuyor. Asıl rahatsız edici sonuç bu, çünkü gerçekten etiketsiz bir derlemde elinizdeki tek şey içsel indeksler:
| temsil | silhouette’e göre \(k\) = | Calinski-Harabasz’a göre | Davies-Bouldin’e göre |
|---|---|---|---|
| LSA | 50, ve hâlâ yükseliyor | 2 | 50 |
| MiniLM | 4 | 2 | 40 |
| E5 | 2 | 2 | 4 |
Calinski-Harabasz her seferinde \(k=2\) seçiyor. Bu bir varyans oranı ve güçlü bir küme yapısı olmayan veride \(k\) büyüdükçe düşme eğiliminde — bu üç taramanın gösterdiği bir eğilim, bir teorem değil. Monotonluğu garanti değildir; belirli bir \(k\)’de gerçek yapı taşıyan bir derlemde eğri orada tepe yapabilir; indeksin varlık sebebi de budur. Davies-Bouldin ise bunun tersi olan bir nedenle öbür yöne, büyük \(k\)’ye doğru kayıyor — ama yalnızca kıpırdadığı yerde.
Asıl önemli olan bu son ifade; bu yüzden argmin’ine değil, gerçek değerlerine bakın: E5’te \(k=2\)’den \(k=50\)’ye kadar bütün tarama 4,44 ile 4,77 arasında kalıyor, yani \(k=4\)’teki “optimum” düz bir çizgi üzerindeki %7’lik bir salınım. MiniLM başta kıpırdıyor — \(k=2\)’deki 4,24’ten \(k=10\)’daki 3,33’e iniyor — sonra düzleşiyor: \(k=20\)’den yukarısı 3,23 ile 3,28 arasına sıkışıyor, yani \(k=40\)’taki “optimum” bir plato üzerindeki %1’lik bir salınım.
Bu üçünden ikisinde seçilen \(k\)’nin çevresindeki farklar o seçimi destekleyemeyecek kadar küçük — argmin gerçek, ama bir karar değil.
Sonuna kadar düşmeyi sürdüren yalnızca LSA; o bile bir yöne yerleşmeden önce bir süre gezinip duruyor: \(k=2\)’de 6,38; \(k=4\)’te yukarı, 7,17’ye çıkıyor; sonra 6,41’e iniyor, \(k=6\)’da yeniden 6,52’ye çıkıyor ve ancak ondan sonra kesintisiz düşerek \(k=50\)’de 4,105’e varıyor.
Bu, tepe noktasından %43’lük bir düşüş; karşısında E5’te %7’lik, MiniLM’in platosunda ise %1’lik bir salınım var — argmin’i almak yerine grafiği çizdiğinizde bir eğilimle bir gürültü arasındaki fark böyle görünüyor.
Tablonun asıl dersi bu ve mesele salt uyuşmazlıktan daha kötü: üç indeks farklı \(k\) seçmekle kalmıyor; Davies-Bouldin’in üç temsilden ikisinde seçtiği \(k\), komşu değerlerden ayırt bile edilemiyor. Argmin raporlayan bir indeks her zaman bir argmin raporlayacaktır. Onun en aza indirdiği yüzeyin herhangi bir şekli olup olmadığını kontrol etmek size düşüyor.
Bu tablodaki her silhouette küçük. Ölçek 1,0’a kadar gidiyor; taramanın tamamındaki en iyi değer 0,1042. Sıfıra yakın bir silhouette, ortalama bir noktanın, komşu kümeye kendi kümesine olduğu kadar yakın olması demek. Bu vasat bir kümeleme değil, bu geometride iyi ayrılmış kümeleri olmayan bir derlem — ve sayı size bunu söylüyor.
En büyük küme sütununu izleyin. LSA’da \(k=2\)’de tek bir küme derlemin %81,1’ini tutuyor. Bu, klasik dejenere sonuç: aykırı değer ilan etmesi yasaklanmış k-means, kocaman bir torba ve ondan çok daha küçük bir küme üretiyor. Bölümleme teknik olarak geçerli ve tamamen işe yaramaz.
11.6 Kaç küme?
Yukarıdaki tablo göz önündeyken, bu derlem için “doğru \(k\) nedir” sorusunun cevabı öyle bir şey yok — bu kısmın geri kalanı da bunu “yeterince aramadım”dan nasıl ayırt edeceğinizle ilgili.
11.6.1 İndeksler aslında neyi ölçüyor
Üç indeks de bir kümelemenin ne kadar “iyi” olduğunu tek bir sayıyla söylediğini iddia ediyor (silhouette ve CH’de yüksek, DB’de düşük değer iyidir). Bu iddiayı açıp bakalım: her biri gerçekte neyi ödüllendiriyor?
\[ s(i) = \frac{b(i) - a(i)}{\max\{a(i),\, b(i)\}} \]
\(i\) noktasının silhouette değeri, \(a(i)\) ile \(b(i)\)’yi karşılaştırıyor: \(a(i)\) noktanın kendi kümesindeki noktalara ortalama uzaklığı, \(b(i)\) ise en yakın diğer kümedeki noktalara ortalama uzaklığı (Rousseeuw 1987). \(-1\) ile \(1\) arasında değişiyor ve bir kümelemenin puanı, tüm noktalar üzerindeki ortalama. Sayıyı değiştiren ama neredeyse hiç raporlanmayan iki uygulama ayrıntısı var. Birincisi, hesap \(O(n^2)\); bu yüzden 49.849 belgelik derlemde silhouette’i sabit, rastgele bir 10.000’lik örneklem üzerinde hesapladık (seed 42). Bu da buradaki her silhouette’i kendi hata payı olan bir kestirime dönüştürüyor. İkincisi, “uzaklık” baştan sona metric="cosine"; yani kümelemenin fiilen yapıldığı geometriyle aynı. Metriği ve örneklem büyüklüğü belirtilmemiş bir silhouette, yeniden üretilebilir bir sayı değil.
silhouette — her nokta için, kendi kümesine bir sonraki en yakın kümeye kıyasla ne kadar daha yakın olduğu; \([-1, 1]\) aralığına ölçeklenmiş hâli. 0’a yakın olması noktanın bir sınırda oturduğu anlamına geliyor; derlemin tamamının 0’a yakın olması ise ortada sınır olmadığı anlamına geliyor. ↩︎
Calinski-Harabasz, \(k\) için açık bir düzeltme taşıyan bir varyans oranı:
\[ \mathrm{CH} = \frac{\operatorname{tr}(B_k)}{\operatorname{tr}(W_k)} \times \frac{n-k}{k-1} \]
Burada \(B_k\) ve \(W_k\) kümeler arası ve küme içi dağılım matrisleri. Gerçek yapısı olmayan veride \(k\) büyüdükçe düşmesinin başlıca sebebi o \((n-k)/(k-1)\) çarpanı: dağılım oranı yavaş iyileşirken düzeltme hızla küçülüyor. Davies-Bouldin ise her küme için eşleşmelerinin en kötüsünü seçip sonra bunların ortalamasını alıyor:
\[ \mathrm{DB} = \frac{1}{k}\sum_{i=1}^{k} \max_{j \neq i} \frac{s_i + s_j}{d(\mu_i, \mu_j)} \]
Burada \(s_i\), \(i\) kümesinin içindeki ortalama yayılım; DB’de düşük değer daha iyi. Çiftler üzerinde bir maksimum olduğu için \(k\) büyüyüp kümeler tek tek sıkılaştıkça iyileşme eğiliminde. Bu, CH’nin yanlılığının tam ayna görüntüsü; taramamızda ikisinin uyuşmamasının sebebi de bu. İkisi de ucuz, ikisi de nokta sayısında \(O(n)\) ve — taramanın gösterdiği gibi — gerçek küme yapısı olmayan veride ikisi de \(k\)’ye göre neredeyse monoton. Bu da onların “optimum”unu, tesadüfen taradığınız aralığın bir yan ürünü hâline getiriyor.
Tarama tablosunun sakladığı bir çekince var ve bu kez esnettiğimiz kural kendi kuralımız. silhouette_score bir metric argümanı alıyor ve bizimki "cosine"’dı; calinski_harabasz_score ile davies_bouldin_score ise almıyor. İkisi de ham merkezler etrafındaki karesel Öklit dağılımı üzerinde tanımlı ve scikit-learn ikisinin de kosinüs varyantını sunmuyor. \(\ell_2\)-normalleştirilmiş vektörlerde bu, noktalar için kulağa geldiği kadar zararlı değil — \(d^2 = 2 - 2\cos\) ikisini birbirinin afin yeniden parametrelendirmesi yapıyor. Ama merkezler için zararsız değil: merkezler birim vektörlerin ortalaması ve kendileri birim vektör değil. Yani CH ile DB sütunlarını, kosinüsle yapılmış bir kümelemenin Öklit ölçümleri diye okuyun. Bu, Bölüm 11.13’ün sizi uyardığı uyuşmazlığın ta kendisi; tolere etmemizin gerçek sebebi de alternatifin iki indeksi kendimiz yazmak olması. “İndeksler uyuşmuyor” sonucunun bir kısmı, indekslerin değil metriklerin uyuşmaması olabilir.
“Silhouette 0,11’in altında” ifadesini başka bir yere taşımadan önce bir çekince. E5’in düşük değerlerini minicik uzaklıklarına bağlamak cazip — rastgele çiftlerin kosinüs uzaklıklarının hepsi kabaca 0,08 ile 0,22 arasında — ama bu bir açıklama değil. Silhouette bir oran, \(b - a\) bölü \(\max\{a, b\}\); bütün uzaklıkları aynı sabitle çarpmak onu hiç değiştirmez. Silhouette’in bağlı olduğu şey uzaklıkların düzeni: bir noktanın kendi kümesinin, bir sonraki kümeye göre — uzaklıkların kendi büyüklüğüne oranla — ne kadar yakın olduğu. Temsil değişince bu düzen de değişebilir; E5’in 0,855’lik ortalamasının arkasındaki ortak yönü kaldırmak bazı belgeleri ötekilerden daha çok kaydırır. Bu yüzden silhouette’i ortalama-merkezlemeden sonra yeniden hesaplamak yine de yapılması gereken kontrol ve biz yapmadık. Bölüm 11.4’teki göreli kontrast başka bir soru soruyor ve başka bir cevap veriyor: E5 orada 3,009 alıyor, yani komşu sıralaması, \(k\) gruba bölmenin yakalayamadığı bir yapı taşıyor. Silhouette’i tek bir temsil içinde \(k\)’ler arası bir karşılaştırma olarak okuyun. Temsiller arası her karşılaştırmaya şüpheyle yaklaşın ve ona asla mutlak bir anlam yüklemeyin.
Silhouette’lerin hata payını da vermemiz gerekirdi. Hesaplamadık: buradaki her silhouette tek bir 10.000 belgelik örneklemden gelen tek bir kestirim; yani üçüncü ondalık, kimsenin ona göre hareket etmesi gereken bir nicelik değil ve MiniLM’in \(k=4\)’teki “optimum”u (0,1042) ile komşusu \(k=3\) (0,1018) arasındaki fark savunabileceğimiz bir fark değil. Beş ayrık örneklem bir öğleden sonrada bir standart sapma verirdi. Verene kadar ayakta kalan tek şey, tablodaki her değerin 0,2’nin epey altında olduğu — ki argümanın ihtiyaç duyduğu tek kısım da o.
11.6.2 Dirsek yöntemi kötü ününü hak ediyor
En eski tarif, atalet (inertia) değerini \(k\)’ye karşı çizip bükülmeyi aramak. Atalet, k-means amaç fonksiyonunun (Bölüm 11.5) çözümde hesaplanmış hâlinden başka bir şey değil — \(\sum_i \sum_{x \in C_i} \lVert x - \mu_i \rVert^2\), yani her noktanın kendi merkezine toplam karesel uzaklığı.
Popüler, çünkü her zaman bir cevap üretiyor. Sorun da bu.
Atalet optimumda monoton düşüyor — daha çok merkez her noktayı en yakınına ancak daha da yaklaştırabilir. Bu bir bükülme vaadi değildir: düz inen bir doğru da monotondur ve hiç dirseği yoktur; bir bükülme gördüğünüzü sandığınız yer ise eksen sınırlarınıza bağlıdır. (Her \(k\)’de k-means’i bağımsız çalıştırırsanız ölçülen eğri yer yer yukarı da çıkabilir, çünkü her koşu kendi yerel çözümüne düşer; bu, dirseğin işe yaramazlığına karşı bir örnek değil, yeniden başlatma piyangosunun bir belirtisidir.) Schubert (2023) bu savı uzun uzun kuruyor ve özeti sert: dirsek ölçütü kullanılmamalı, ayakta kalmasının sebebi de bilgilendirici olması değil, çizmesinin kolay olması.
Her indeksten daha iyi bir varsayılan. Üç ya da dört \(k\) değerinde kümeleyin, her kümeden 20 belge örnekleyin ve onları okuyun. Bir küme için, bir meslektaşın sonra yeni belgeleri ayıklamakta kullanabileceği tek satırlık bir tarif yazamıyorsanız, silhouette ne derse desin o küme gerçek değildir. “Bir insanın karar verirken kullanabileceği grup sayısı” ölçütü bir kaçamak değil — zaten neden kümelediğinizle bağlantısı olan tek ölçüt o.
11.6.3 Etiketleriniz varsa, onları kullanın
Etiketli bir alt küme varsa, dışsal doğrulama her içsel indeksten çok daha bilgilendirici. En basitinden başlayarak üç standart ölçü:
- Saflık (purity), her kümeye çoğunluğunun etiketini verir ve bu şekilde doğru etiketlenmiş belgelerin payını sayar. Anlatması kolay, kandırması da kolay. Her kümede tek belge olursa kusursuz 1,0 alır; %93,7’si olumlu olan bir derlemde ise herhangi bir bölümleme en az 0,937 alır, çünkü her kümenin çoğunluğu pekâlâ “olumlu” olabilir. Bizim verimizde saflık, iyi bir kümelemeyi rastgele olandan ayıramaz.
- Düzeltilmiş Rand indeksi (ARI) (Hubert ve Arabie 1985), iki bölümlemenin üzerinde anlaştığı belge çiftlerini sayıyor — ikisinde de aynı grupta ya da ikisinde de farklı gruplarda olan çiftler — ve bu sayıyı şansa göre düzeltiyor: \(\mathrm{ARI} = (\mathrm{RI} - \mathbb{E}[\mathrm{RI}]) / (\max \mathrm{RI} - \mathbb{E}[\mathrm{RI}])\); burada RI, uyuşan çiftlerin ham payı. Böylece rastgele uyuşma 0, tam eşleşme 1 alır; negatif bir ARI ise bölümlemelerin şanstan daha az uyuştuğu anlamına gelir.
- Normalleştirilmiş karşılıklı bilgi (NMI), kümeyi bilmenin etiket hakkında ne kadar bilgi verdiğini soruyor: kümeler \(C\) ile etiketler \(L\) arasındaki karşılıklı bilgi \(I(C; L)\), 0 ile 1 arasında kalsın diye \(H(C)\) ve \(H(L)\) entropilerinin bir ortalamasına bölünüyor. V-measure (Rosenberg ve Hirschberg 2007) ise belirli bir normalleştirme altında aynı nicelik —
v_measure_score,average_method="arithmetic"ile çağrılmışnormalized_mutual_info_score’dur, ayrı bir ölçü değil. İkisi de şansa göre düzeltilmemiş, dolayısıyla ikisi de bir bölümlemeyi salt daha çok kümesi olduğu için ödüllendirebilir. Düzeltmenin bir adı var ve aynı modülde geliyor: düzeltilmiş karşılıklı bilgi (adjusted mutual information, AMI) (Vinh vd. 2010), aynı biçimdeki rastgele bir bölümlemenin alacağı değeri çıkarıyor — ARI’nın çift sayıları için yaptığının aynısı. Karşılaştırdığınız koşular arasında \(k\) değişiyorsa NMI değil AMI raporlayın. Bu yanlılığın bizim taramamızda görünmediğine dikkat edin — MiniLM’in NMI’sı \(k=2\)’de 0,0392 iken \(k=50\)’de 0,0142’ye düşüyor, E5’inki ise \(k=6\)’da tepe yapıyor. Yanlılığın bu sefer ortaya çıkıp çıkmadığını tartışmak yerine düzeltilmiş kestiriciyi kullanmanın doğru gerekçesi de bu.
Hepsi şu soruyu cevaplıyor: bu bölümleme, etiket bölümlemesi mi? Bu ifadeyi aklınızda tutun, çünkü Bölüm 11.10 bunun yanlış soru olduğunu gösterecek.
11.7 Şekil yanlış olduğunda: yoğunluk tabanlı kümeleme
Yukarıdaki her k-means sonucu 3. varsayıma tabi: her nokta bir kümeye aittir. Bir ürün yorumu derleminde bu açıkça yanlış. Yorumların önemli bir kısmı kısa ve genel bir övgü ve belirli hiçbir şeye ait değil. Gürültü demesine izin verilen bir yöntemin bu yüzden daha iyi iş çıkarması gerekir. Onu çalıştırmaya değer kılan da şu: başarısız olma biçimi, k-means’inkinden daha bilgilendirici.
HDBSCAN bir yoğunluk seviyeleri hiyerarşisi kuruyor, sonra bu hiyerarşi boyunca en uzun süre ayakta kalan kümeleri çıkarıyor (Campello vd. 2013; McInnes ve Healy 2017). \(k\)’si yok. Ana ayarı min_cluster_size: küme demeye razı olduğunuz en küçük grup. Yeterince yoğun olmayan her şey \(-1\) etiketini alıp dışarıda bırakılıyor. HDBSCAN, DBSCAN’in (Ester vd., 1996) hiyerarşik ardılı. DBSCAN sizden tek bir eps yarıçapı ister ve böylece bütün derlem için tek bir yoğunluk düzeyi varsayar; HDBSCAN bu ayarı kaldırır ve her bölgenin kendi yoğunluğuna sahip olmasına izin verir.
HDBSCAN — kümeleri, çevresinden daha yoğun bölgeler olarak buluyor; her bölge kendi yoğunluğuyla değerlendiriliyor. Geri kalanını gürültü sayıyor. \(k\) istemiyor ve her noktayı atama zorunluluğu yok. ↩︎
Her temsilde min_cluster_size’ı üç değerde taradık, min_samples’ı ise varsayılanında bıraktık. Bu varsayılanın ne olduğunu açıkça söyleyelim, çünkü aşağıdaki tablo hakkındaki en belirleyici bilgi bu: hem sklearn.cluster.HDBSCAN’de hem de hdbscan paketinde min_samples=None, min_samples = min_cluster_size demek. Yani bunlar tek bir eksen üzerindeki üç nokta değil. Her satır yoğunluk tahminini ve asgari küme büyüklüğünü birlikte değiştiriyor; gürültü oranı da çoğunlukla birincisine tepki veriyor. Sonuç her hücrede aynı ve hiç de ince bir sonuç değil.
| temsil | min_cluster_size |
küme | gürültü | en büyük küme | süre |
|---|---|---|---|---|---|
| LSA | 25 | 2 | %52,9 | %47,0 | 674sn |
| LSA | 100 | 2 | %97,1 | %2,4 | 219sn |
| LSA | 500 | 0 | %100,0 | — | 198sn |
| MiniLM | 25 | 2 | %55,1 | %44,8 | 285sn |
| MiniLM | 100 | 3 | %90,0 | %9,2 | 248sn |
| MiniLM | 500 | 0 | %100,0 | — | 1495sn |
| E5 | 25 | 2 | %99,5 | %0,3 | 612sn |
| E5 | 100 | 0 | %100,0 | — | 1530sn |
| E5 | 500 | 0 | %100,0 | — | 2631sn |
Her temsilin üç satırını birlikte okuyun. LSA ve MiniLM’de min_cluster_size = 25 iki küme buluyor; biri her şeyin kabaca yarısını tutuyor, diğeri yuvarlama hatası düzeyinde; kalan yarı gürültü. Bu bir yapı keşfi değil, tek bir büyük yığının tarifi. Eşiği 100’e çıkarın, yığın yoğun sayılmayı bırakıyor ve derlemin %90–100’ü gürültü oluyor. 500’e çıkarın: hangi yoğunluk seviyesine bakarsanız bakın, 49.849 belgenin hiçbir yerinde küme kalmıyor.
E5 uç durum ve en öğretici olanı. Denediğimiz en gevşek ayar olan min_cluster_size = 25’te bile derlemin %99,5’ini gürültü ilan ediyor ve en büyük kümesi %0,3. Eşiği azıcık yükseltin, hiçbir şey bulamıyor — sıfır küme, %100 gürültü, üstelik min_cluster_size = 500’de 44 dakikalık bir çalışmanın ardından.
Neden bütün uzaylar içinde E5? Bölüm 11.4 zaten bant genişliğinin hiçbir şey teşhis etmediğini söylemişti ve onun tercih ettiği kontrast ölçüsüne göre E5 (3,009), LSA’dan (2,116) daha iyi bir uzay. Akla gelen ikinci cevap E5’in sıkışmış ölçeği: rastgele çiftlerin kosinüsünün standart sapması 0,0278, MiniLM’de ise 0,1503 — beşte bir yayılım. Bu cevap ikinci bakışta çöküyor. Varsayılan cluster_selection_epsilon=0 ile HDBSCAN, bütün uzaklıklar aynı sabitle çarpılsa da birebir aynı kümeleri döndürür; çünkü çekirdek uzaklıkları, karşılıklı erişilebilirlik (mutual reachability) uzaklıkları ve küme kararlılıkları hep birlikte ölçeklenir. Yani küçük bir mutlak ölçek tek başına hiçbir şeyi açıklamaz. Kendi ortalama uzaklığına göre ölçüldüğünde (\(1 - 0,8547 \approx 0,145\)) E5’in yayılımı yaklaşık 0,19 — MiniLM’in 0,22’sine yakın ve LSA’nın 0,085’inin iki katından fazla. HDBSCAN’in asıl ihtiyaç duyduğu şey yerel yoğunluğun değişmesi: her noktanın min_samples’ıncı en yakın komşusunun başka yerlere göre çok daha yakın olduğu bölgeler. E5’te bu değişim belli ki fazla zayıf ve nedenini ölçmedik. Akla gelen iki şüpheli var: ortak yön (Bölüm 11.4’teki merkezleme ablasyonu bunu sınardı) ve yüksek boyutlu uzaylarda uzaklıkların genel olarak birbirine yaklaşma eğilimi. Bir noktanın en yakın ve en uzak komşusu arasındaki büyük fark, yoğunluğun bölgeden bölgeye değiştiğini garanti etmez; yoğunluk tabanlı yöntemlerin ihtiyacı ise ikincisidir. Bir ironi var: E5, en iyi başarımı gösteren (Bölüm 11.10) temsil; yoğunluk tabanlı kümelemenin en ağır biçimde çuvalladığı temsil de o. Bunlar çelişki değil — farklı şeyleri ölçüyorlar — ama yalnızca HDBSCAN deneyen bir uygulayıcı, kazanan modeli çöpe atmış olurdu.
%90–100’lük gürültü oranları bir ölçüm, bir başarısızlık değil. HDBSCAN size doğru ve belirli bir şey söylüyor: yüzlerce belge ölçeğinde bu derlemin, çevresinden anlamlı biçimde daha yoğun bölgeleri yok. Derlem bir takımada değil, yoğunluğu kademeli olarak değişen tek bir bulut. k-means size bunu söyleyemezdi, çünkü k-means ortada küme olsun ya da olmasın \(k\) küme döndürmek zorunda.
Doğru okuma bu ve k-means taramasını da açıklıyor. Silhouette’in 0,1042’nin üstüne hiç çıkmaması yanlış \(k\)’yi aradığımız için değil, bulunacak sınır olmadığı için. Varsayımları tamamen farklı iki yöntem aynı şeyi söylüyor; bu, sonuçların herhangi birinden tek başına daha değerli.
Bu iddia nereye kadar geçerli. HDBSCAN’in sonucu belirleyen üç ayarı var ve biz bunlardan birini değiştirdik. min_samples yoğunluk tahmininin sıkılığını belirliyor ve gürültü oranının asıl tepki verdiği parametre o; cluster_selection_epsilon aşırı parçalanmayı önleyen sabit bir alt uzaklık sınırı; cluster_selection_method ise "eom" ile "leaf" küme seçimi arasında seçim yapıyor. Bu tablo için hâlâ yapmamız gereken iki takip çalışması var. Birincisi, min_samples’ı min_cluster_size’dan ayıran bir tarama: min_samples 5 ya da 10’da sabit kalırken min_cluster_size değişir. İkincisi, sıfırdan farklı bir epsilon. Bunlar çalıştırılana kadar “bu derlemde yoğunluk yapısı yok” ifadesi, üç boyutlu bir parametre uzayının tek ekseni üzerindeki üç nokta hakkında bir iddiadır. Bu iddiayı tek başına tarama değil, yukarıdaki k-means uyuşması destekliyor.
Maliyete de dikkat edin. MiniLM üzerindeki min_cluster_size = 500 koşusu, ortada bir şey olmadığı sonucuna varmak için 1.495 saniye — 25 dakika — sürdü. Yüksek boyutlu veride yoğunluk tabanlı kümeleme ucuz değil. Çalışma süresi de min_cluster_size’a göre monoton değil ve bu da yukarıdaki bağlantının bir belirtisi: min_cluster_size’ı yükseltmek min_samples’ı da yükseltiyor. min_samples ise çekirdek uzaklığını bulan en yakın komşu sorgusunun \(k\)’si; maliyeti belirleyen de bu sorgu.
Standart geçici çözüm ve bedeli. Alışılmış tavsiye, önce UMAP (McInnes vd. 2018) ile 5–15 boyuta inmek, sonra izdüşüm üzerinde HDBSCAN çalıştırmak. BERTopic varsayılan olarak bunu yapıyor (Grootendorst 2022) ve gerçekten de küme üretiyor. Nedeni konusunda net olun: UMAP, komşuları birbirine çekip geri kalan her şeyi iterek yerel yoğunluğu imal eden doğrusal olmayan bir yöntem. Bir UMAP izdüşümünde bulunan kümeler kısmen UMAP’in bir özelliği. Yine de faydalı olabilirler — ama “UMAP’ten sonra HDBSCAN küme buldu”, özgün uzayın küme içerdiğinin kanıtı değildir. Özgün uzayın gerçekte neye benzediğini yukarıdaki sayılar gösteriyor.
Aynı uyarı, insanların UMAP ya da t-SNE ile çizdiği iki boyutlu resimler için de geçerli. Bu yöntemler kimin kimin yanında olduğunu oldukça iyi korur; ama grafikteki bir öbeğin büyüklüğünü ve iki öbek arasındaki boşluğu büyük ölçüde veri değil, yöntemin kendisi ve ayarları belirler (Wattenberg vd., 2016). Böyle bir grafiği hangi belgeleri okuyacağınıza karar vermek için kullanın, asla ölçüm olarak değil. Doğrusal alternatif PCA’dır: en büyük varyans yönlerine bir izdüşüm; uzaklıkları kısaltır ama bir bölgeyi ötekinden fazla germez. Daha az çarpıcıdır ve metinde çoğu zaman tek bir bulut gösterir; öteki kanıtlar da ortada ada olmadığını söylüyorsa, daha sadık resim odur.
11.7.1 Çalıştırmadığımız iki aile ve onları neden çalıştırmak isteyebilirsiniz
Aglomeratif kümeleme, en yakın grup çiftini tekrar tekrar birleştirir ve size bir \(k\) yerine bir dendrogram verir. Bu, Bölüm 11.6’ya doğrudan bir cevap: bir indeksin argmin’ini almak yerine birleştirme uzaklıklarının nerede sıçradığına bakarsınız. linkage ayarı “en yakın grup çifti”nin ne demek olduğunu belirler: en yakın üyeleri (single), en uzak üyeleri (complete), gruplar arası bütün çiftlerin ortalaması (average) ya da grup içi varyansta en küçük artış (Ward; yalnızca Öklit). Single linkage her şeyi tek, uzun bir zincire bağlama eğilimindedir; average ve Ward daha yuvarlak gruplar verir. scikit-learn’ün AgglomerativeClustering sınıfı ayrıca metric="cosine", linkage="average" parametrelerini doğrudan kabul ediyor; yani Calinski-Harabasz ile Davies-Bouldin’in aksine, kümelemenin fiilen yapıldığı geometride puanlanabiliyor. Bedeli \(O(n^2)\) bellek; 49.849 belgede bu, bir örneklem üzerinde kümelemek demek.
\(k\) en yakın komşu çizgesi artı Leiden (Traag vd. 2019), NLP dışında, özellikle tek hücre genomiğinde (Seurat, Scanpy) embedding kümelemesinin fiilî standardı hâline gelmiş tarif. Denemediğimiz yöntemler içinde bu derlemde en çok şansı olan da bu. Esas olarak kimin kimin komşusu olduğuna dayanıyor, uzaklıkların mutlak ölçeğine değil (bazı uygulamalar kenarları uzaklığa göre ağırlıklandırsa da). E5’in göreli kontrastı (3,009) en yakın komşuların en uzaklardan belirgin biçimde ayrıştığını söylüyor; komşuluk bilgisinin işe yarar olabileceğinin işareti bu, bir garantisi değil. Üstelik HDBSCAN’in ihtiyaç duyup bulamadığı şeye, yoğunluğun bölgeden bölgeye değişmesine de ihtiyacı yok. Bu kısımdan kendi işinize tek bir deney götürecekseniz, bu olsun. Doğal üçüncü varsayım takımı bu. Üçüncü yöntem de “belirgin yapı yok” derse kanıt güçlenir; yapı bulursa, ilk iki yöntemin uyuşmasının neden yanıltıcı olduğunu öğrenirsiniz. İki sonuç da bilgi verir.
11.8 Klasik ve embedding çağı konu modelleri
Kümeleme size belge başına bir etiket veriyor. Bir konu modeli ise grup başına bir kelime listesi veriyor — paydaşa asıl gösterdiğiniz şey de bu. İkisi rakip olmaktan çok aynı teslimatın iki yarısı. 2026’da bilinmesi gereken üç aile var; aşağıda, işin ne kadarını dışarıdan hazır bir bileşene (ön eğitimli bir embedding’e, hazır bir kümelemeye) bıraktıklarına göre artan sırayla geliyorlar.
11.8.1 LDA: üretici hikâye
Latent Dirichlet allocation (Blei vd. 2003) iki varsayımla başlıyor: her belge \(K\) konu üzerinde bir karışım, her konu da sözlük üzerinde bir dağılım. İkisi de Dirichlet önsellerinden çekiliyor (Dirichlet, toplamı 1 olan olasılık vektörleri üreten bir dağılım; parametresi küçük tutulursa her belge az sayıda konuya yoğunlaşır). Model sonra, gözlediğiniz kelimeleri en iyi hangi konuların açıkladığını soruyor. Gerçekten olasılıksal: bir belge tek bir gruba atanmıyor; %60 oranında konu 3, %30 oranında konu 7 oluyor. On beş yıl boyunca konu modellemenin baskın yöntemi oldu ve insanlar “konu modeli” dediğinde hâlâ kastettikleri şey bu.
Varsayımlarını da söylemekte fayda var, çünkü bizim derlemimize kötü oturuyorlar. LDA belgeler üzerinde bir kelime torbası modeli ve her belgenin, içinden bir karışım kestirmeye yetecek kadar kelime içermesine ihtiyaç duyuyor. Buradaki medyan yorum 19 kelime. 19 token’dan on bileşenli bir karışım kestirmek çok şey beklemek demek.
11.8.2 NMF: aynı şekil, önsel dağılımlar olmadan
Non-negative matrix factorization (negatif olmayan matris ayrışımı) (Lee ve Seung 1999), belge-terim matrisini \(V \approx WH\) biçiminde, tek bir kısıtla çarpanlarına ayırıyor: \(W\) ve \(H\) negatif eleman içeremez. Hiçbir şey birbirini götüremediği için bulduğu parçalar toplamsal oluyor ve metinde bu, okunabilir kelime listeleri üretme eğiliminde. Üretici bir hikâyesi ve önsel dağılımları yok; yalnızca bir matris ayrışımı. Bunun pratikte pek önemli olmadığı ortaya çıkıyor. Ayrıca genellikle ham sayımlar yerine tf-idf üzerinde çalıştırılıyor ve bu, kısa belgelere daha uygun.
11.8.3 Önce kümele, sonra betimle: c-TF-IDF
Üçüncü aile modellemeyi tamamen atlıyor. Kümeleriniz zaten elinizde (Bölüm 11.5). Her kümeyi tek bir uzun belge sayın, içindeki her şeyi birleştirin ve kelimelerini küme içi terim frekansına karşı kümeler arası ters frekansla puanlayın:
\[ W_{t,c} = \operatorname{tf}_{t,c} \times \log\!\left(1 + \frac{A}{\operatorname{tf}_t}\right) \]
Burada \(\operatorname{tf}_{t,c}\), \(t\) teriminin \(c\) kümesindeki frekansı; \(A\) küme başına ortalama kelime sayısı; \(\operatorname{tf}_t\) ise terimin derlemin tamamındaki frekansı. Bu, BERTopic’in merkezindeki numara olan c-TF-IDF (Grootendorst 2022). En yükseğe koyduğu kelimeler, bu kümede sık ve derlem genelinde seyrek olanlar — ki bu neredeyse ama tam olarak “burada yaygın, başka yerde nadir” değil, çünkü \(\operatorname{tf}_t\) içinde \(c\) kümesinin kendi katkısı da var. Küçük bir küme için fark ihmal edilebilir. Derlemin yarısını tutan bir küme için değil: o kümeye has kelimeler, tam da ona has oldukları için cezalandırılıyor. En büyük kümenizin etiketi neden bu kadar yavan diye şaşırmadan önce bilmekte fayda var.
Burada ne olduğu konusunda net olmak gerek. c-TF-IDF bir konu modeli değil; başkasının kümelemesine uygulanan bir etiketleme yordamı. Modellemenin tamamını embedding ile k-means yaptı. Bu aileyi icat eden de BERTopic değil: top2vec (Angelov 2020) belgeleri ve kelimeleri tek bir uzaya gömüyor, belgeleri HDBSCAN ile kümeliyor ve her küme merkezine en yakın kelime vektörlerini konu diye okuyor — aynı iskelet, farklı bir etiketleme adımı, iki yıl önce. Modellemenin başkasına bırakılması bir avantaj: anlamsal işi, sizin derleminizin içerdiğinden çok daha fazla metinle eğitilmiş bir model yapıyor. Ama konular da kümelemenin her kusurunu miras alıyor; Bölüm 11.9 bunu birazdan kendi hatamız üzerinden gösterecek.
11.8.4 Puanlamak
Karşılaştırmak için bir sayıya ihtiyacımız var. Konu tutarlılığı (topic coherence), bir konunun en üstteki kelimelerinin gerçek belgelerde gerçekten bir arada geçip geçmediğini ölçüyor. Standart varyantı NPMI (Bouma 2009):
\[ \operatorname{NPMI}(w_i, w_j) = \frac{\log \dfrac{P(w_i, w_j)}{P(w_i)\,P(w_j)}}{-\log P(w_i, w_j)} \]
Bu değerin önce bir konunun ilk 10 kelimesindeki tüm kelime çiftleri üzerinden, sonra da konular üzerinden ortalaması alınıyor. \(-1\) ile \(1\) arasında değişiyor; pozitif olması, kelimelerin rastlantıdan beklenenden daha sık birlikte göründüğü anlamına geliyor.
“Birlikte”nin ne demek olduğunu söylemeden formül hesaplanamaz ve verdiğiniz cevap sayıları ciddi biçimde değiştirir; o yüzden söyleyelim: buradaki eş-oluşum belge düzeyinde. \(P(w_i)\), 49.849 yorumdan \(w_i\)’yi en az bir kez içerenlerin oranı; \(P(w_i, w_j)\) ise ikisini birden içerenlerin oranı. Bir yorum tek bir bağlam; içindeki tekrarlar iki kez sayılmıyor. Alternatif gelenek olan 10 ya da 20 token’lık kayan pencere uzun belgeler için standart ama 19 kelimelik bir yorumda hiçbir anlam ifade etmiyor. Hiç birlikte geçmeyen çiftler ıraksamaya bırakılmak yerine \(\varepsilon\) ile yumuşatılıp \(-1\)’e çekiliyor. Bütün olasılıklar derlemin kendisinden, 8.651 terimlik sabit bir sözlük üzerinden geliyor; sözlük, elle yazılmış bir Türkçe stop word (etkisiz kelime) listesiyle oluşturuldu. Dolayısıyla beş yöntem aynı zeminde puanlanıyor.
Hangi tutarlılık ölçüsünü kullandığımıza dair bir not, çünkü başka bir ölçüyle karşılaşacaksınız. gensim.CoherenceModel’in en çok kullanılan ayarı — ve çoğu BERTopic öğreticisinin varsayılanı — NPMI değil C_v. C_v, NPMI’yı bağlam vektörleri üzerinde dolaylı bir kosinüs doğrulama adımıyla sarmalıyor. Bu adım sayesinde C_v, özgün değerlendirmede insan puanlarıyla biraz daha iyi ilişkilendi (Röder vd. 2015); ama üzerine akıl yürütmek de epeyce zorlaştı. Değerleri sözlükler arasında karşılaştırılamıyor, kararsız olduğu biliniyor ve C_V’yi tanımlayan ekibin kendi aracı Palmetto’nun belgeleri bile artık kullanılmamasını önerdi. Biz NPMI kullanıyoruz, çünkü ne hesapladığını tek satırda yazabiliyoruz — bir sonraki tabloyu denetlenebilir kılan tek şey de bu.
| yöntem | NPMI | eğitim süresi | neye ihtiyaç duyuyor |
|---|---|---|---|
| LDA, \(K=10\) | +0,0737 | 133,1sn | ham sayımlar |
| NMF, \(K=10\) | +0,1183 | 1,0sn | tf-idf |
| LSA \(k\)=10 üzerinde c-TF-IDF | +0,1340 | 0,03sn | mevcut bir kümeleme |
| MiniLM \(k\)=10 üzerinde c-TF-IDF | +0,1002 | 0,02sn | mevcut bir kümeleme |
| E5 \(k\)=10 üzerinde c-TF-IDF | +0,1064 | 0,02sn | mevcut bir kümeleme |
Öne çıkan sonuç klasik yöntem için rahatsız edici. LDA, NMF’ten 133× daha yavaş ve tutarlılıkta daha düşük puan alıyor. Bunu hangi uygulamayla ölçtüğümüzü de söyleyelim, çünkü böyle bir farkta uygulama hikâyenin yarısı. sklearn.decomposition.LatentDirichletAllocation varsayılan olarak batch (toplu) varyasyonel Bayes ile eğitiliyor (learning_method="batch") ve max_iter=10 geçişten sonra duruyor; doc_topic_prior ile topic_word_prior da varsayılan \(1/K\) değerlerinde bırakıldı. Collapsed Gibbs örneklemesi (MALLET; Python’da tomotopy ya da lda paketi — gensim’in LdaModel’i Gibbs değil, çevrimiçi varyasyonel Bayes kullanıyor) daha da yavaş ama genellikle daha iyi konular üretiyor; \(\alpha\)’yı düşürmek de aşağıda teşhis edilen sorunun kısa metinler için standart çaresi. Yani satırı scikit-learn’ün varsayılan LDA’sı, 19 kelimelik yorumlarda scikit-learn’ün varsayılan NMF’ine yeniliyor diye okuyun — bir uygulayıcının gerçekten karşılaştığı karşılaştırma bu, ama model ailesi hakkında bir hüküm değil.
Bu yön, kısa metin literatürünün raporladığı yönle aynı; o literatürün var olmasının da bir sebebi var. Belgeleriniz kısaysa, Dirichlet karışımının belge başına bir konu dağılımı kestirmek için elinde neredeyse hiçbir şey kalmıyor. Bu rejim için kurulmuş modeller ilkesel cevabı veriyor: belgeler yerine derlem genelinde havuzlanmış kelime çiftlerini modelleyen biterm topic model (Yan vd. 2013) ve belgeye bir karışım yerine tek bir konu atayan Dirichlet multinomial mixture (Yin ve Wang 2014). Ucuz cevap ise tf-idf üzerinde sıradan bir matris ayrışımı. Kısa metin üzerinde bir LDA hattı devraldıysanız, yanına NMF çalıştırmak bir öğleden sonra alır ve tartışmayı büyük ihtimalle bitirir.
Üç c-TF-IDF satırının maliyeti fiilen sıfır, çünkü kümelemenin bedeli zaten ödenmişti. Ve gözle görülür biçimde farklı kelime listeleri üretiyorlar. E5 artı c-TF-IDF’in on kümesinden üçü için döndürdüğü şey (çıktıda topic = konu):
topic 2 koku kokusu parfüm kalıcı güzel tavsiye parfümü aldım
topic 3 kitap kitabı tavsiye güzel ederim sürükleyici okudum akıcı
topic 9 telefon iyi şarj yok güzel telefonu gayet ürün var
Parfüm, kitap, telefon. Bu kategorilerin var olduğunu modele kimse söylemedi. Kümelemenin gerçekten iyi olduğu şey bu; ayrıca dikkat edin, bulunan yapı bir ürün kategorisi yapısı — gizliden gizliye umduğumuz (Bölüm 11.5) duygu yapısı değil. ARI’nın sıfır olmasının sebebi de bu.
Tutarlılık bir vekil ölçü ve zayıf bir vekil. Chang vd. (2009), herkesin en başta yapması gereken deneyi yaptı: insanlardan bir konunun kelime listesine sokulmuş, konuya uymayan kelimeyi bulmalarını istediler (word intrusion, araya sızan kelime testi). Ayrılmış (held-out) veri üzerinde olabilirliği en yüksek olan modellerin en az yorumlanabilir konuları ürettiğini buldular; yani otomatik bir ölçüt insan yargısından ayrışabiliyordu. Onların ölçütü olabilirlikti, tutarlılık değil; NPMI tabanlı tutarlılık ölçüleri sonradan geldi. Tutarlılık ölçüleri için daha yeni bir meta-değerlendirme olan Hoyle vd. (2021) iki şey gösteriyor. Otomatik tutarlılık ölçüleri, konu kalitesine dair insan yargılarını güvenilir biçimde izlemiyor. Alandaki değerlendirme pratiği de o kadar tutarsız ki yayımlanmış karşılaştırmalar çoğu zaman birbiriyle kıyaslanamıyor. Doogan ve Buntine (2021) aynı sonuca uygulama tarafından varıyor. Otomatik konu metrikleri kullanışlıdır, güvenilir değil. Bir sonraki kısım, kendi tutarlılık sayımızın yalnızca isabetsiz kalmadığı, tam ters yönü gösterdiği bir vaka.
11.9 Kümelemenin bulduğu hata
Sonuç tablosuna bir daha bakın. LSA üzerindeki c-TF-IDF beşin en iyisi olan +0,1340 aldı. Tutarlılığın, kelimeleri gerçekten birlikte giden konuları ödüllendirmesi gerekiyor; o hâlde doğal bir sonraki adım, bu puanı kazandıran konuyu okumak. O koşunun konu başına puanları:
topic 0 1 2 3 4 5 6 7 8 9
NPMI .1095 .0654 .0566 .0591 .1059 .0933 .1022 .5075 .1879 .0523
7 numaralı konu +0,5075 alıyor — ikinci en iyinin neredeyse üç katı ve deneyin tamamındaki en yüksek konu başına tutarlılık. Kelimeleri:
topic 7 bi ye fi tavsi çi ederi si ni li yi
Bunlar kelime değil, kelime parçaları. Ve yöntem onları bölümdeki en tutarlı konu olarak puanladı, çünkü gerçekten de son derece tutarlılar. Neredeyse kusursuz biçimde birlikte geçiyorlar, çünkü hepsini aynı belgelerdeki aynı kusur üretiyor.
11.9.1 İzini sürmek
Zincir kısa ve her halkası bir REPL’de (Python’un etkileşimli komut satırında) kontrol edilebilir:
>>> "TAVSİYE".lower()
't a v s i ̇ y e' # burada aralıklı yazıldı: 7 değil, 8 kod noktası
>>> [f"U+{ord(c):04X}" for c in "TAVSİYE".lower()]
['U+0074','U+0061','U+0076','U+0073','U+0069','U+0307','U+0079','U+0065']
İ, U+0130 — LATIN CAPITAL LETTER I WITH DOT ABOVE; noktalı ve noktasız i’nin farklı harfler olduğu Türkçede gayet normal bir harf. Python’un str.lower() metodu dile özgü (locale-aware) değil. U+0130’u i’ye (U+0069) ve ardından gelen U+0307, COMBINING DOT ABOVE’a küçültüyor; çünkü düz bir i zaten bir nokta taşıyor ve Unicode’da içine katlanacak “üstünde fazladan nokta olan i” diye önceden birleştirilmiş bir karakter yok.
Bu derlemle ilgili bir gerçek, zincirin nerede başladığını değiştiriyor. Bölüm 4’ün bulduğu gibi yorumlar zaten küçük harfle geliyor: içlerinde tek bir büyük harf kalmamış, dolayısıyla bizim str.lower() çağrımız burada hiçbir şey üretmiyor. Birleştirici noktalar metin bize ulaştığında zaten oradaydı — büyük olasılıkla veri kaynağındaki önceki bir işleme adımında, tam da bu varsayılan küçük harfe çevirme yüzünden. Yukarıdaki REPL satırları böyle bir işaretin nasıl doğduğunu gösteriyor; aşağıdaki halkalar ise ardından gelen hiçbir işlemin onu neden silmediğini.
Şimdi ikinci halka. Normalleştirme sizi kurtarmıyor:
>>> "\u0307" in unicodedata.normalize("NFC", "TAVSİYE".lower()) # True
>>> "\u0307" in unicodedata.normalize("NFKC", "TAVSİYE".lower()) # True
Yukarıdaki nedenle hem NFC hem NFKC diziyi olduğu gibi bırakıyor: normalleştirilecek bir birleşik biçim yok. “Her şeyi NFKC’ye çevirelim gitsin” alışkanlığı, bu hatanın fark edilmeden üretime kadar ulaşmasını sağlayan şeyin ta kendisi.
Üçüncü halka tokenizer. scikit-learn’ün varsayılan token deseni (?u)\b\w\w+\b ve birleştirici işaret bir kelime karakteri değil, dolayısıyla:
>>> re.findall(r"(?u)\b\w\w+\b", "TAVSİYE".lower())
['tavsi', 'ye']
>>> re.findall(r"(?u)\b\w\w+\b", "tavsiye")
['tavsiye']
Tavsiye — bu derlemdeki belgelerin %19,8’inde geçen, yorumlara özgü en sık kelime — sessizce ikiye bölünüyor; ama yalnızca metninde bu başıboş işaret bulunan belgelerde — muhtemelen birinin onu bir zamanlar büyük İ ile yazdığı belgelerde.
Bir büyük harften bozuk bir sözlüğe dört adım
İnsanları tuzağa düşüren adım 3. “Biz her şeyi NFKC’ye normalleştiriyoruz” cümlesi bunu kapsıyormuş gibi geliyor ama kapsamıyor. Fazladan nokta taşıyan bir i için önceden birleştirilmiş bir karakter yok; dolayısıyla normalleştirmenin yapacak bir işi yok ve yine de başarılı olduğunu bildiriyor.
Tek satırlık düzeltme ve çözümün neden .lower() da .casefold() da olmadığı. Küçültmeden sonra birleştirici işareti silmek — s.replace("\u0307", ""), karakter baskıda görünmez olduğu için kaçış dizisiyle yazıldı — ['tavsiye']’yi geri getiriyor. str.casefold()’un yardımcı olmadığına dikkat edin. O da locale duyarlı değil ve aynı sekiz kod noktasını üretiyor; bunu bilmek önemli, çünkü “lower yerine casefold kullan” en yaygın önerilen çözüm ve burada yanlış. Python’un standart kütüphanesinde Türkçe büyük-küçük harf dönüşümü hiç yok; gerçek locale duyarlı dönüşüm için ICU gerekiyor (PyICU: icu.UnicodeString(s).toLower(icu.Locale("tr"))). Çoğu hat için daha ucuz ve tamamen yeterli cevap, iki Türkçe harfi küçültmeden önce kendiniz eşlemektir — Bölüm 4’teki tr_lower da bunu yapıyor. Yine de iki işi birbirinden ayırın. tr_lower sizin kodunuzun bu işareti üretmesini engeller; metinde zaten bulunan bir işareti ise silemez — bu derlemde olduğu gibi. Size verilmiş bir metni yalnızca yukarıdaki replace onarır. Hangisini seçerseniz seçin, test paketinizde tutmanız gereken test şu: assert tokenize("TAVSİYE") == tokenize("tavsiye").
Aynı hata sınıfını hiç Türkçe bilmeden yakalayan ikinci bir koruma daha var: ilk 10 kelimesinin yarısından fazlası kısa token olan her konuyu işaretleyin — sum(len(w) <= 3 for w in top10) > 5. 7 numaralı konu bu testten 10 üzerinden 8 alıyor. Gerçekten kısa içerik kelimeleri olan dillerde arada bir yanlış alarm verecektir; onlara bakmak da tek satıra mal olur. Türkçeye özgü dönüşümlerin tamamı için bkz. Bölüm 16.
11.9.2 Neye mal oldu
Hata ilginç. Ama metin bütünlüğü kontrolünü isteğe bağlı sanan herkesin önüne konması gereken kısım, hatanın neye mal olduğu.
| ölçüm | değer |
|---|---|
| U+0307 içeren belge | 4.183 (derlemin %8,39’u) |
| bunların LSA kümesi 7 içindeki payı | %30,9 |
| küme 7’nin büyüklüğü | 1.365 belge |
| küme 7’de etkilenen belgeler | %94,7 |
| geri kalan her yerde etkilenenler | %6,0 |
| küme içindeki zenginleşme | 15,8× |
| yalnızca bu hata yüzünden var olan sözlük türleri | 1.607 |
| düzeltildiğinde net sözlük değişimi | 86.196 → 85.224 |
Buradaki sözlük büyüklüğü 86.196; bölümün başında raporlanan 86.245 değil. Birbiriyle ilgisiz iki sebebi var ve bunları ayırmak için yeniden koşmak gerekti. 49’un 45’i tek karakterlik token’lar: rakamlar, _ ve tek harfler. scikit-learn’ün gerçek varsayılan deseni \b\w\w+\b bunları atıyor, kurulumdaki çıplak \w+ ise tutmuştu. Kalan 4’ü de, çıkarılan 151 yakın kopyayla (Bölüm 11.3) birlikte elendi. İki karar da bilinçli alınmamıştı. Sözlüğü iki seferde de aynı biçimde sayın; yoksa sayıları karşılaştırmayın.
Ortadaki satırları dikkatle okuyun, çünkü bu kısmın bütün meselesi onlar. k-means’e Unicode hakkında hiçbir bilgi verilmedi. Ona 256 LSA boyutu verildi. Buna rağmen %6,0’lık bir arka plana karşı %94,7 etkilenmiş bir küme topladı — hatayı, kesin biçimde ve kimse söylemeden buldu. Bunu yapabildi, çünkü sistematik bir metin kusuru veride gerçek bir değişim ekseni oluşturuyor ve kümelemenin işi gerçek değişim eksenlerini bulmak.
Uydurulmuş sözlük, Türkçe konuşan hiç kimsenin yazmadığı 1.607 türden oluşuyor: alişveri, acti, alternati, alabi. Bu, tf-idf matrisinde boşa harcanan 1.607 öznitelik demek. Her biri, kesilip çıkarıldığı gerçek kelimenin belge frekansını seyreltiyor.
Net değişim 1.607’den küçük ve aradaki fark bir cümleyi hak ediyor, çünkü ters anlaşılması kolay. Metni onarmak o 1.607 parçayı kaldırıyor ve daha önce hiç tek parça hâlinde görünmemiş 635 tür yaratıyor — alişverişim, acemiliğini, admin — bu derlemde yalnızca bozuk hâlde var olan kelimeler. Böylece sözlük 86.196’dan 85.224’e iniyor; net küçülme 972, yani kaldırılan 1.607 eksi geri gelen 635. Düzeltme yalnızca silmiyor; eksik olduğunu bilmediğiniz kelimeleri size geri veriyor.
Ama geri gelenlerin hepsi doğru yazılmış değil: alişverişim hâlâ yanlış. Kaynak metinde ALIŞVERİŞ küçültülürken İ ile birlikte noktasız I da (ı yerine) i olmuş. U+0307’yi silmek bu ikinci hatayı geri almaz; üstelik I → i dönüşümü geride bir işaret bırakmadığı için onu bu yolla bulamazsınız bile. Sözlükte bilinen kelimelerin yanlış yazılmış biçimlerini aramak gerekir; lab’deki IŞIK testi (Bölüm 11.15) bu hatayı kendi hattınızda yakalamak için.
Kümeleme lehindeki argüman, abartmadan ifade edildiğinde budur. Kümeleme, etiketlere karşı ARI ≈ 0 aldı. Bu ölçüte göre (Bölüm 11.5) hiçbir şey bulamadı. Aynı kümeleme, 80 milyon konuşuru olan bir dilde yazılmış metindeki gerçek bir kusuru da ayırıp çıkardı: belge başına 256 sayıyla ve kimse ona böyle bir kusur aramasını söylemeden. Verinizde ne olduğunu — bilerek koymadığınız parçalar dâhil — denetimsiz yöntemlerle öğrenirsiniz.
Burada etkileyici olanın ne olduğu konusunda kesin olun, çünkü bu hikâyenin cazip versiyonu yanlış. Bölüm 4 bu hatayı kaçırmış değil. "İYİ".lower() arızasını açıkça belgeliyor, kendi kodu bu hataya yol açmasın diye tr_lower tanımlıyor, metinde zaten bulunan başıboş U+0307 işaretlerini sayıyor ve onları silip hasarı ölçmenizi isteyen bir alıştırma veriyor. O bölüm biliyordu, çünkü Türkçe bilen bir insan bunu biliyordu ve yazmıştı.
Asıl dikkat çekici olan, kümelemenin bunu yeniden keşfetmesi. Bölüm 4’ün Türkçe konuşan birine ihtiyacı vardı; k-means’e vektörlerden başka hiçbir şey gerekmedi ve aynısını, takımınızdaki kimsenin okuyamadığı bir dildeki derlemde de yapacak. Aktarılabilir iddia bu ve ikisinden küçük olanı — tam da bu yüzden akılda tutulması gereken o. Yalnızca zaten bildiğiniz hataları bulan bir yöntem değersizdir; bir hatanın neye benzediği söylenmeden onları bulan bir yöntem ise her şeye doğrultabileceğiniz bir alettir.
Bu vaka ayrıca, otomatik bir ölçütün insan yargısından ayrışabileceğinin (Chang vd. (2009) bunu olabilirlik için, Hoyle vd. (2021) tutarlılık ölçüleri için gösterdi) kendi sayılarımızla görülen uç bir örneği. Bölümün tamamındaki en yüksek tutarlılığa sahip konu, hiçbir anlamı olmayan konuydu. Onu atıp kalan dokuzun ortalamasını alın: LSA’nın c-TF-IDF tutarlılığı +0,1340’tan +0,0925’e düşüyor — hem MiniLM’in (+0,1002) hem de E5’in (+0,1064) altına — bu da onu üç c-TF-IDF satırı arasında birincilikten sonunculuğa taşıyor. Metrik çöpü fark etmemekle kalmadı; yöntemi o çöp sayesinde birinci sıraya koydu.
Kesin konuşmak gerekirse +0,0925 dokuz konuluk bir ortalama ve on konuluk ortalamalarla karşılaştırılıyor, yani birebir denk bir kıyas değil. Olmasına da gerek yok: mesele değişimin büyüklüğü. On konudan biri — üstelik bir insanın iki saniyede eleyeceği türden biri — ortalamanın, sıralamayı tersine çevirmeye yetecek kadarını taşıyordu.
11.10 Getiri: “başarısız” bir kümeleme ne işe yarar
Bölümün iki kez ertelediği soruyu cevaplama vakti. ARI ≈ 0, bölümlemenin etiket bölümlemesi olmadığını söylüyor. Bölümlemenin işe yaramaz olduğunu söylemiyor; bu ikisini birbirine karıştırmak da insanların işine yarayacak bir sonuçtan kendi kendilerini ikna edip vazgeçmelerinin en yaygın yolu.
O yüzden bir uygulayıcının gerçekten sorduğu bir soruyu sorun. Bir etiketleme bütçeniz var. Bu 49.849 yorumun 5.000’ini okuyabilirsiniz. Bir belgenin hangi kümede olduğunu bilmek, hangi 5.000’i okumanız gerektiğini değiştiriyor mu?
Derlem %93,66 olumlu, yani %6,34 olumsuz. Rastgele okuyun, okuduğunuzun %6,34’ü şikâyet olur. Şimdi etiketleri açın ve \(k=10\)’da her kümenin içindeki olumlu oranı ölçün — bu tanıyı ancak derlem tesadüfen etiketli olduğu için yapabildik; kümeleme etiketleri hiç görmedi.
Son sütundaki sayı lift (göreli artış): bir kümenin içindeki olumsuz oranın, derlemin tamamındaki olumsuz orana bölümü. Lift 1,0, kümenin rastgele okumaktan daha iyi olmadığı anlamına geliyor; lift 4,0 ise ondan çekilen bir belgenin şikâyet olma olasılığının dört kat daha yüksek olduğu anlamına geliyor. “Okuma bütçemi nereye harcamalıyım” sorusunun doğrudan cevabı bu; ARI’yı değil onu istememizin sebebi de bu.
| temsil | olumlu oran, en düşük küme → en yüksek | en kötü kümedeki olumsuz lift |
|---|---|---|
| LSA | %89,4 → %98,9 | 1,67× |
| MiniLM | %82,3 → %99,4 | 2,79× |
| E5 | %73,2 → %99,5 | 4,23× |
E5’in en kötü kümesi, %6,34’lük taban orana karşı %26,8 olumsuz. Bu küme derlemin %13,25’ini — 6.605 belgeyi — tutuyor; dolayısıyla o oranın %95 Wilson aralığı %25,7–%27,9 ve lift 4,06×–4,40× arasında. (Wilson aralığı bir oran için güven aralığı; basit normal yaklaşımın aksine, oran 0’a ya da 1’e yakınken ve örneklem küçükken de [0, 1] içinde kalır ve kapsama oranını korur.) Aralığı da, onu üreten küme büyüklüğünü de yazın: paydası verilmemiş bir lift kimsenin denetleyemeyeceği bir sayıdır ve Bölüm 11.15 da bunu kendi derleminiz için sizden istiyor. Aralık, etkinin şüpheli olmayacağı kadar dar — o kümeden çektiğiniz her belgenin şikâyet olma olasılığı, rastgele çekilmiş bir belgeye göre kabaca dört kat yüksek. Bu büyük bir etki ve ARI bunun hiçbirini göremedi, çünkü ARI bölümlemenin tamamının etiketlemenin tamamını yeniden üretip üretmediğini soruyor — bunun cevabı da hayır.
Model sıralamasına az önce ne olduğuna dikkat edin. ARI ile ölçüldüğünde üç temsil ayırt edilemiyordu — hepsi ≈ 0, en iyisi 0,0083. Kararla doğrudan ilgili ölçüyle ise temiz biçimde ve beklediğiniz sırada ayrışıyorlar: 1,67× / 2,79× / 4,23×. Metrik hiçbir şey ölçmüyor değildi; yanlış şeyi ölçüyordu.
Aynı üç kümeleme, iki soru, zıt cevaplar
Bölümden akılda kalması gereken şekil bu. Aynı küme atamaları, standart değerlendirmeye göre değersiz ve sizin gerçek kararınıza bağlı değerlendirmeye göre değerli olabilir — hem de aynı anda. İkisinden hangisini raporladığınız sizin verdiğiniz bir karar ve çoğu insan bu kararı fark etmeden veriyor.
11.10.1 Eğrinin yalnızca ilk noktası değil, tamamı
Bir küme, bir eğri üzerinde bir nokta. Asıl soru şu: on kümenin hepsini olumsuz oranlarına göre sıralayıp en kötüden başlayarak okusanız, her durma noktasında derlemin ne kadarını okumuş ve şikâyetlerinin ne kadarını bulmuş olurdunuz?
En kötü kümeden başlayarak okuyun; eğri köşegenden ayrılıyor
Önemli olan tek kısım sol uç, çünkü sabit bir okuma bütçesi o bölgeye düşüyor. E5, okumanın %13’ü karşılığında şikâyetlerin %56’sını buluyor; LSA aynı recall için derlemin %35,6’sına ihtiyaç duyuyor.
Kesikli köşegen, rastgele sırayla okumanın size verdiği şey: derlemin %40’ını okuyun, şikâyetlerin %40’ını bulun. Onun üstündeki her eğri, kümelemenin yarattığı değer.
Akılda tutulacak tek sayı:
Derlemin %13,3’ünü — E5’in olumlu oranı en düşük olan tek kümesini — okumak, derlemdeki tüm olumsuz yorumların %56,0’ını ortaya çıkarıyor.
Bu, sabit bir okuma bütçesinin getirisinde 4,2× iyileşme demek; hem de hiç etiket görmemiş bir kümelemeden. Gerçek işiniz “şikâyetleri bul ki ürünü düzeltelim” ise bu kümeleme işi yaptı ve bu arada aldığı 0,0075’lik ARI o iş açısından ilgisiz.
Bunu doğrulanmış bir politika olarak değil, betimsel bir sonuç olarak okuyun. Kümeler denetimsiz, ama okunma sırası değil: on küme, 49.849 referans etiketin tamamından hesaplanan olumsuzluk oranına göre sıralandı ve sonra recall aynı etiketlere karşı ölçüldü. Bu, kendi cevap anahtarına karşı puanlanan bir oracle sıralaması, yani bütün referans etiketleri bilen ideal sıralama. Size kümelerin sıralanmaya değecek kadar ayrışabildiğini söyler; gerçekten kurabileceğiniz bir sıralamanın ne kadar iyi olacağını söylemez. Uygulanabilir hâli birkaç yüz etikete mal olur: kümeleri küçük ve etiketli bir geliştirme örnekleminde sıralayın, sonra recall’u ayrık bir test örnekleminde ölçün. 8. alıştırma bu deney; onunla bu sayı arasındaki fark da burada kullandığımız kestirmenin bedeli.
Sıralama yalnızca ilk noktada değil, eğrinin büyük kısmında da korunuyor. MiniLM her bütçede LSA’nın üstünde ve E5, pratikte çalışılacak tüm aralık boyunca ikisinin de üstünde. LSA’nın, E5’in %13,3’te ulaştığı recall’a ulaşması için derlemin %35,6’sını okuması gerekiyor — aynı sonuç için yaklaşık 2,7 katı okuma.
Bir çekince de kuyrukta: okunan oran kabaca %76 ile %85 arasındayken MiniLM, recall’da E5’in yaklaşık 0,1 yüzde puanı üstüne çıkıyor. Bu veride gerçek bir kesişme ama üzerine karar verilecek bir şey değil, çünkü o noktada ikisi de olumsuzların %97’sini bulmuş oluyor ve siz derlemin dörtte üçünü okumakla beşte dördünü okumak arasında seçim yapıyorsunuz. Triyaj eğrileri sol uç için var.
11.10.2 Kümenin içinde gerçekte ne var
Metrikler ucuz; belgeleri okuyun. E5’in en kötü kümesinden rastgele çekilmiş beş olumsuz yorum:
ürün paslandı. almanızı tavsiye etmem
hiçbir işe yaramıyor. hatta dahada kötü hale getiriyor. kesinlikle alınmaz.
ürün çok çabuk ısınıyor ve çok yavaş
kalitesiz, arka plaka fotoğraftaki gibi tek parça değil, montajı zor.
hiç beklediğim gibi değildi, yorumlardaki tüm olumsuzluklar aynen çıktı.
Bunlarda ince bir ayrım yok. Bir ürün müdürünün pazartesi sabahı ihtiyaç duyduğu yorumlar bunlar ve kümeleme, “şikâyet” diye bir kategori olduğu kendisine söylenmeden onların orantısız bir kısmını tek bir grupta topladı.
Aktarılabilir ders. Bir kümelemenin “başarısız olduğunu” raporlamadan önce, kümelemenin desteklemesi gereken kararı yazın ve onu ölçün. Saflık, ARI ve NMI “etiketlerimi geri getirdin mi” sorusunu cevaplıyor. Lift, belirli bir bütçedeki recall ve ilk içgörüye kadar geçen süre ise “yardımcı oldun mu” sorusunu cevaplıyor. Bunlar farklı sorular ve aynı koşuda zıt cevapları olabilir.
11.11 Kümeleri bir dil modeliyle adlandırmak
c-TF-IDF size on kelime veriyor. Paydaş bir ifade istiyor. Hattın içinde bir LLM’in tartışmasız doğru araç olduğu tek yer burası ve nedeni konusunda kesin olmakta fayda var: adlandırma düşük riskli, yüksek hacimli ve doğrulanabilir bir görev. On etiket var ve her biri belgelere bakılarak otuz saniyede kontrol edilebilir. Dil modellerini konular üzerinde kullanmak artık bir numara değil, belgelenmiş bir yaklaşım: Pham vd. (2024), konuları önermeyi de belgeleri onlara atamayı da bir modele bırakıyor ve sonucu LDA ve BERTopic ile karşılaştırıyor. Biz modeli bu işin yalnızca ikinci ve daha güvenli yarısı için kullanıyoruz; bu bölümün savunduğu iş bölümü de bu: embedding gruplar, dil modeli betimler.
Prompt (istem), Bölüm 17’nin ayrıntısıyla işleyeceği ilkeye dayanıyor: modele yalnızca görev tarifini değil, kanıtı da verin:
Below are the 10 most distinctive words for a cluster of Turkish product
reviews, and 8 reviews sampled from it.
Distinctive words: koku, kokusu, parfüm, kalıcı, güzel, tavsiye, parfümü,
aldım, ederim, var
Reviews:
1. ...
2. ...
Give a 2-5 word English label naming what this cluster is about. If the
reviews do not share a coherent subject, answer exactly: NO COHERENT THEME.
Prompt’u İngilizce yazdık ve İngilizce etiket istedik. Türkçe bir paydaş için son talimatta Türkçe etiket isteyin (2-5 word Turkish label) ya da prompt’un tamamını Türkçe yazın; aşağıdaki üç ayrıntı değişmez.
Bunun faydalı olmasıyla bir yük olması arasındaki farkı üç ayrıntı belirliyor:
- Belgeleri örnekleyin, yalnızca kelimeleri vermekle yetinmeyin. Kelimeler zaten kayıplı bir özet; yalnızca
bi ye fi tavsi çiverilen bir LLM ona bir tema uyduracaktır. Bölüm 11.9 bu başarısızlığı anlatıyor. - Ona bir kaçış kapısı bırakın.
NO COHERENT THEMEseçeneği, modeli bir etiket üretecinden çöp kümelerin zayıf bir dedektörüne çeviren şey. Modelin adlandırmayı reddettiği bir küme, bizzat sizin bakmanız gereken bir kümedir. - Yalnızca merkezin yakınından değil, kümenin tamamından örnekleyin. Merkeze yakın belgeler en tipik olanlar; dolayısıyla yalnızca merkezden alınan bir örneklem her kümeyi olduğundan derli toplu gösterir ve tam da adlandırmadan önce bilmek isteyeceğiniz heterojenliği gizler.
Bu kısımda vermemiz gereken ama elimizde olmayan tek sayı. 2. kural bir dedektör hakkında bir iddia. Bu bölümün kendi kuralı ise bir dedektörü ölçmeden ona güvenmemek (uyarıcı hikâye için bkz. Bölüm 11.9). Test elimizin altında ve on bir prompt’a mal oluyor: bu şablonu on E5 kümesinin hepsinde ve LSA 7 numaralı kümede — hiçbir anlamı olmayan on tokenizer parçasında — çalıştırın. Kaç E5 etiketinin 20 belgelik bir kontrolü geçtiğini, NO COHERENT THEME’in kaç kez devreye girdiğini ve LSA 7’de devreye girip girmediğini kaydedin. Biz çalıştırmadık; o yüzden 2. kuralı ölçülmüş bir güvence değil, bir tasarım ilkesi sayın. Kendi hattınıza taşımaya değer olan da son hücre: hiç devreye girmeyen bir kaçış kapısı dedektör değil, süstür.
Üretilmiş bir etiket bir bulgu değil, bir hipotezdir. Model beş binin içinden on kelime ve sekiz belge gördü. Aslında birbiriyle ilgisiz üç şeyin yapıştırılmasından ibaret bir küme için akıcı ve makul bir isim üretecektir, çünkü akıcı ve makul isimler üretmek onun yaptığı iş. Etiketlerden herhangi biri bir slayta girmeden önce her birini, kendi örneklediğiniz 20 belgeye bakarak kontrol edin.
11.12 Sezgi kontrolleri
Her birini açmadan önce cevaplayın. Altısı da bu bölümün tartışmayla değil ölçümle çözdüğü sorular, dolayısıyla cevapları kontrol edebileceğiniz sayılar taşıyor.
Not1. İki belge 0,91 kosinüs alıyor. Yakın kopya mıdırlar?
Rastgele çift arka planı ortaya konmadan bunu kimse söyleyemez, siz de dâhil. tf-idf ile bu derlemdeki ilgisiz iki yorum ortalama 0,0182 alıyor ve 4,5 milyon rastgele çiftin 99. yüzdeliği 0,1300 — yani 0,91 ölçeğin çok ötesinde ve “yakın kopya” doğru okuma. E5 ile aynı derlemin rastgele çift ortalaması 0,8547, standart sapması 0,0278 ve 99. yüzdeliği 0,9155. Orada 0,91, birbiriyle hiç ilgisi olmayan belgelerin ortalamasının yaklaşık iki standart sapma üstünde kalıyor ve 0,90’da eşiklenmiş bir kopya dedektörü, rastgele çiftlerin %1’inden fazlasını işaretlerdi (99. yüzdelik bu eşiğin üstünde) — 49.849 belgelik bir derlemde on milyondan fazla çift.
Aynı sayı, zıt sonuçlar. İkisini ayıran tek şey, tek bir benzerliğe bakmadan önce bir kez çalıştırılan dört satır kod.
Not2. Silhouette’iniz 0,10’u hiç geçmiyor ve ARI’nız sıfır. Kümeleme başarısız mı oldu?
Bu iki sayı, bölümlemenin iyi ayrılmamış olduğunu ve etiket bölümlemesi olmadığını söylüyor. Hiçbiri bölümlemenin işe yaramaz olduğunu söylemiyor; söylüyormuş gibi davranmak da insanların kullanılabilir bir sonuçtan kendi kendilerini ikna edip vazgeçmelerinin en yaygın yolu.
ARI +0,0075 alan aynı \(k=10\) E5 kümelemesinin, %6,34’lük taban orana karşı %26,8 olumsuz olan bir kümesi var — 4,23× lift — ve derlemin %13,3’ünü oracle küme sırasıyla okumak şikâyetlerinin %56,0’ını buluyor. Bu iki cümle arasında kümeleme değişmedi; soru değişti.
Dolayısıyla doğru teşhis nadiren “kümeleme başarısız oldu” olur. Genellikle “onu kimsenin sormadığı bir soruya karşı puanladım” olur. Kümelemenin desteklemesi gereken kararı yazın, onu ölçün ve ancak ondan sonra karar verin.
Not3. Tekilleştirme neden kümelemeden sonra değil de önce yapılır?
Çünkü k-means her merkezi üyelerinin ortalamasına taşıyor; yani tek bir cümlenin altmış kopyası, o merkezin nereye ineceği konusunda altmış oy kullanıyor. Bir kopya grubu bir satır değil, bir ağırlıktır. Aynı sav, kestirdiğiniz her idf ve sonraki adımlarda çalıştırdığınız her konu modeli için de geçerli.
İkinci sebep, sayının toplama hattınız hakkında ek maliyeti olmayan bir tanı olması. Bizde \(J \geq 0{,}8\)’de 151 fazlalık belge çıktı; bu sonuç 27 saniyede, \(1{,}25 \times 10^9\) ikili karşılaştırmanın ezici çoğunluğu hiç yapılmadan geldi. Sayı %20 çıksaydı durup veri kazıyıcının (scraper) kodunu okumaya giderdiniz ve bu, öğleden sonranızı herhangi bir kümelemeden daha iyi değerlendirmek olurdu.
Sayıyı raporlarken her seferinde belirtilecek bir çekince: bu bir alt sınır. threshold=0.8’de datasketch, 128 hash’i öyle bantlıyor ki benzerliği tam olarak 0,8 olan bir çift 0,40 olasılıkla inceleniyor. “En az 151”, asla “tam olarak 151” değil.
Not4. HDBSCAN derleminizin %97’sine gürültü diyor. Bir meslektaşınız önce UMAP ile beş boyuta inmeyi öneriyor, “çünkü o zaman küme buluyor.” Ne dersiniz?
Cümlenin doğru olduğunu ve kanıt olmadığını. UMAP, bir \(k\)-en yakın komşu çizgesini korumak için düşük boyutlu bir yerleşimi optimize ediyor. Bir derlemi beş boyuta sıkıştırmak, özgün uzayda böyle bir kontrast olsun ya da olmasın, yoğunluk kontrastı imal ediyor. UMAP’ten sonra küme belirmesi, UMAP çalıştırmanın beklenen sonucudur; verinizle ilgili bir keşif değil.
Bunu bir bulguya çevirecek şey, UMAP’in hiç görmediği bir kontrol: gruplar dışarıda tutulmuş bir şeyi öngörüyor mu, n_neighbors ve random_state değişimine dayanıyor mu, derlemin rastgele bir yarısında ayakta kalıyorlar mı. Bizim kendi kanıtımız ters yönü gösteriyor — HDBSCAN özgün E5 uzayında çevresinden belirgin biçimde daha yoğun bir bölge bulamadı, k-means de sınır bulamadı; yani UMAP’in ortaya çıkaracağı pek bir yoğunluk değişimi yok ve ondan sonra beliren yapıyı büyük ölçüde UMAP’in kendisi üretiyor.
Bunların hiçbiri UMAP hattını yayına almanızı yasaklamıyor. Ama resmin gücüne değil, sonraki adımlarda ölçülen sayının gücüne dayanarak yayına alın.
Not5. En iyi konunuz, ikinci en iyinin üç katı tutarlılık alıyor. Önce ne yaparsınız?
Onu okursunuz. Bizimki bi ye fi tavsi çi ederi si ni li yi idi — aynı belgelerdeki aynı Unicode kusurunun imal ettiği on tokenizer parçası. Neredeyse kusursuz bir eş-oluşum göstermelerinin ve NPMI’nın onlara +0,5075 vermesinin sebebi de bu. Bu değer, bölümün tamamındaki en yüksek konu başına tutarlılık. Tutarlılık eş-oluşumu ödüllendiriyor ve sistematik bir hata, herhangi bir derlemdeki en güvenilir eş-oluşum.
Hasar o tek konuyla da sınırlı değildi. Onu atmak LSA’nın ortalamasını +0,1340’tan +0,0925’e indiriyor — üç c-TF-IDF satırı arasında birincilikten sonunculuğa. On konudan biri, üstelik bir insanın iki saniyede eleyeceği türden biri, sıralamayı tek başına taşıyordu. Otomatik bir ölçütün insan yargısından ayrışabileceğini Chang vd. (2009) 2009’da olabilirlik için gösterdi; tutarlılık ölçüleri için benzer sonucu Hoyle vd. (2021) raporladı. Bizim vakamız bunun uç bir örneği.
Not6. 500 belge etiketleyip bir sınıflandırıcı eğitebilirdiniz. Kümeleme ne zaman hâlâ doğru araç?
Sınıfların ne olduğunu henüz bilmediğinizde. İşin özü bu: bir sınıflandırıcı bir etiket listesine ihtiyaç duyar ve kümeleme, bu listenin ne olması gerektiğini keşfetmenin sayılı sağlam yollarından biri. “k-means çalıştır, küme başına 20 belge oku, okuduklarına göre kılavuzun taslağını çıkar” bir etiketleme projesini başlatmanın gerçek ve ucuz bir yolu; kılavuzun ayakta kalıp kalmadığını ardından nasıl kontrol edeceğinizi de Bölüm 5 anlatıyor.
Üç durum daha: kimsenin okuyamayacağı kadar çok belgeniz var ve hangilerini okuyacağınızı seçmek zorundasınız (Bölüm 11.10); bir derlemi, sizin gibi onu okumayacak birine anlatmanız gerekiyor (Bölüm 11.8); ya da verinizde gerçekte ne olduğunu — kimsenin bilerek koymadığı parçalar dâhil — bilmek istiyorsunuz (Bölüm 11.9).
Ve en az onun kadar önemli olan tersi: sınıfları zaten biliyorsanız ve etiketlemeye gücünüz yetiyorsa, etiketleyin. Kümeleme daha ucuz bir sınıflandırıcı değildir ve olmayacaktır.
11.13 Mülakat soruları
Atıf üzerine — Bölüm 2’deki ile aynı uyarı. Bunlar, ikisi de ücretsiz olan iki güvenilir açık kaynakta tekrar tekrar karşımıza çıkan sorular: Chip Huyen’in Introduction to Machine Learning Interviews kitabı (Huyen 2021) ve AIMLInterviews. Kaynak göstermeden “X şirketinin sorduğu sorular” diye liste veren sayfalara temkinle yaklaşın; bir soruyu bir şirkete atfetmek için doğrulanabilir bir kaynak arayın.
Küme sayısını nasıl seçersiniz? Mülakatçıların duymak istediği cevap, sorunun öncülünü reddederek başlıyor. İçsel indeksler birbirini tutmuyor — bizimkiler bir temsilde optimumu 50, 2 ve 50’ye, bir başkasında 2, 2 ve 4’e koydu — ve üç durumun ikisinde “optimum” düz bir çizgi üzerindeki %1–7’lik bir salınımdı. Bunun yerine ne yapacağınızı söyleyin: üç ya da dört \(k\) değerinde kümeleyin, küme başına 20 belge okuyun ve her kümesini tek satırda anlatabildiğiniz \(k\)’yi tutun. Ardından dirsek yöntemini, yalnızca kullanmadığınızı ve nedenini söylemek için anın: optimum atalet yapısı gereği monoton biçimde düşer ve bu, kullanılabilir bir bükülme olacağını hiçbir şekilde garanti etmez. Bükülmeyi nerede gördüğünüz de eksen sınırlarınıza bağlıdır (Schubert 2023).
k-means mi HDBSCAN mi? k-means küresel ve benzer yayılımlı kümeler, aykırı değer olmaması ve bilinen bir \(k\) varsayıyor; metinde canınızı yakan, herkesin adını andığı varsayım değil, 2. ve 3. varsayımlar. HDBSCAN dördünü de bırakıyor ve bir gürültü sınıfı ekliyor. Belgelerin çoğunun belirli bir gruba ait olmadığı bir derlem için doğru yapı da bu. Sorun şu ki HDBSCAN cevap vermeyi reddedebilir — ve bu derlemde reddetti.
min_cluster_sizedeğerine göre %53–100 gürültü verdi, hiçbir ayarda üçten fazla küme bulmadı; gürültü oranının en düşük olduğu ayarda (LSA ve MiniLM’de %53–55) bile geri kalanın neredeyse tamamını, derlemin %45–47’sini tutan tek bir yığında topladı. Güçlü bir cevap, “ikisini de çalıştırın, çünkü ayrıştıkları yerler size bilgi verir” der. Farklı varsayımlara dayanan iki yöntemin de yapı olmadığını söylemesi, ikisinden birinin tek başına söylemesinden çok daha güçlü bir kanıttır.Metinde neden Öklit değil de kosinüs? Çünkü ham uzunluk konuyu değil belge uzunluğunu taşıyor ve neredeyse hiçbir zaman uzunluğa göre kümelemek istemezsiniz. Bunun ötesinde bilmeye değer olan şu: \(\ell_2\) ile normalleştirilmiş vektörlerde ikisi monoton biçimde ilişkilidir, \(d^2 = 2 - 2\cos\); dolayısıyla aynı en yakın komşuları verirler. Ama aynı k-means sonucunu vermezler: birim vektörlerin aritmetik ortalaması bir birim vektör değildir, bu yüzden iki yordam ikinci yinelemeden itibaren ayrışır. Pratik kural: normalleştirin, sonra metriği algoritma ile raporladığınız her puan arasında tutarlı tutun. Kosinüsle kurulmuş bir kümeleme üzerinde Öklit uzaklığıyla hesaplanan bir silhouette, sizin kümelemenizi ölçmüyordur.
Bir milyar belgede yakın kopyaları bulun. Shingle, MinHash, bant, kova, doğrula — ve sonra yaklaşıklığın gerçekte neye mal olduğunu söyleyin; çoğu cevabın eksik bıraktığı yer burası. LSH, tam doğrulamayı geçen yanlış pozitif üretmiyor; ama yanlış negatif üretiyor: 0,8 eşiğinde 13’erli 9 banda bölünmüş 128 hash ile \(J = 0{,}9\)’daki bir çift 0,93, \(J = 0{,}8\)’deki bir çift 0,40 ve \(J = 0{,}7\)’deki bir çift 0,08 olasılıkla inceleniyor. Bu bir kusur değil, bilinçli bir tasarım tercihi; kopya sayılarının alt sınır olarak raporlanmasının sebebi de bu. Sabit bir derlemi denetlemek yerine yeni gelen belgeleri kalıcı bir dizine karşı kontrol etmeniz gerektiğinde, alternatif olarak SimHash’i (Charikar 2002) anın.
Etiketiniz yokken bir kümelemeyi nasıl değerlendirirsiniz? İçsel indeksler ve sınırlarıyla başlayın, sonra asıl cevaba gelin: bölümlemeyi değil, kararı değerlendirin. Örnekleyin ve okuyun; bir insanın her kümeyi adlandırabildiğini kontrol edin; sonraki adımlarda bir kullanım varsa onu doğrudan ölçün. Kendi sayılarımız savın kendisi — ARI üç temsili ayıramadı, hepsi ≈ 0; oysa en kötü kümedeki lift, tıpatıp aynı atamalardan onları 1,67× / 2,79× / 4,23× diye sıraladı. Ne kadar küçük olursa olsun etiketli bir alt kümeniz varsa, o size bütün içsel indekslerin toplamından daha fazlasını kazandırır.
LDA mı, daha yenisi mi? Kararı veren varsayımı söyleyin: LDA, her belgede bir karışım kestirmeye yetecek kadar kelime isteyen, kelime torbasına dayalı bir karışım modeli. Medyan uzunluğu 19 kelime olan yorumlarımızda NMF’ten 133× daha yavaştı ve daha az tutarlıydı (+0,0737’ye karşı +0,1183). Kısa metin için tf-idf üzerindeki NMF daha iyi bir klasik varsayılan. Modern varsayılan ise önce kümele, sonra betimle: embedding’leri çıkarın, kümeleyin ve c-TF-IDF ile etiketleyin (Grootendorst 2022); kümeleme hazır olduktan sonra bu adımın ek bir maliyeti yok. Açıkça dile getirmeniz gereken ödünleşim (trade-off) şu: c-TF-IDF, embedding’in bütün anlambilimini ve kümelemenin bütün hatalarını miras alıyor ve bir konu modeli değil, bir etiketleme yordamı. Belgeler uzunsa ve gerçekten bir atama değil belge başına bir karışıma ihtiyacınız varsa LDA hâlâ doğru cevap.
11.14 2026 alet çantası
Bu bölümdeki her şey tek bir dizüstü bilgisayarda, aşağıdaki sürümlerle çalıştırıldı. Bir kitapta sürüm sabitlemek, kitabın zamanla eskimesini baştan kabul etmek demek; ama sabitlememek daha kötü — buradaki sayılar yalnızca belirtilmiş bir yığına karşı yeniden üretilebilir.
| kütüphane | kullanılan sürüm | burada ne işe yarıyor |
|---|---|---|
scikit-learn |
1.9.0 | TfidfVectorizer, TruncatedSVD, KMeans, HDBSCAN, LatentDirichletAllocation, NMF ve bütün metrikler |
sentence-transformers |
5.7.0 | MiniLM ve E5’i yükleme ve batch’ler hâlinde işleme |
torch |
2.13.0 | embedding’lerin hesaplandığı MPS (Apple GPU’larının Metal arka ucu) |
numpy / scipy |
2.5.2 / 1.18.0 | yoğun ve seyrek doğrusal cebir |
pandas |
3.0.5 | derlem işleme, Parquet gidiş-dönüşü |
datasketch |
2.0.0 | Bölüm 11.3 için MinHash ve LSH dizini |
umap-learn |
0.5.12 | tartışılan izdüşüm (Bölüm 11.7) |
Sürümler tekrarlanabilirliğin yarısı; öteki yarısı hiperparametreler ve bu bölüm onları eksik raporluyor. Bunlardan herhangi birini yeniden çalıştırmadan önce kapatmanız gereken üç boşluk var. KMeans’in rastgeleliği k-means++ başlatmasından geliyor; bu yüzden bölümlemeyi random_state ve n_init belirliyor. n_init’in varsayılanı da scikit-learn 1.4’ten beri "auto"; yani varsayılanın kendisi sürüme bağlı. HDBSCAN’in, taradığımız min_cluster_size’ın (Bölüm 11.7) yanında min_samples, metric, cluster_selection_method ve cluster_selection_epsilon parametreleri var. LatentDirichletAllocation’ın ise learning_method, max_iter ve iki Dirichlet önseli. Kendi koşularınızda hepsini açıkça sabitleyin ve sayıların yanına yazın — değiştirmediklerinizi de, çünkü “varsayılanı kullandık” ifadesi ancak hangi sürümün varsayılanı olduğunu söylediğinizde bir anlam taşır.
Bilmeye değer, yukarıda kullanılmayanlar:
| kütüphane | güncel sürüm | ne zaman kullanılır |
|---|---|---|
bertopic |
0.17.4 | embed → UMAP → HDBSCAN → c-TF-IDF hattının tamamı tek bir nesne olarak; konu birleştirme, hiyerarşi ve LLM ile adlandırma dâhil. Bir demoya giden en hızlı yol; kümelere güvenmeden önce yoğunluk kısmını (Bölüm 11.7) okuyun |
faiss-cpu |
1.15.0 | kaba kuvvet (brute-force) komşu araması pahalılaştığında yaklaşık en yakın komşular — kabaca yüz bin belgeden sonrası (yoğun bir \(n \times n\) float32 benzerlik matrisi bu bölümün 49.849 belgesinde bile ~10 GB tutar) |
usearch |
2.26.0 | aynı işi yapan, FAISS’e göre daha hafif ve daha yeni bir alternatif |
gensim |
4.4.0 | klasik konu modeli alet çantası; LDA türevleri ve CoherenceModel için hâlâ referans uygulama |
top2vec |
1.0.36 | otomatik konu sayısıyla ortak belge/kelime embedding’leri; kavramsal olarak BERTopic’e yakın ve ondan daha eski |
chromadb |
1.5.9 | vektörlerin bir betiğin değil bir uygulamanın sorgulayacağı biçimde kalıcı olması gerektiğinde — retrieval-augmented generation’a (RAG; Bölüm 20) giden köprü |
Hangisini seçmeli: her durum için tek satır. ~100 bin belgenin altında bu bölümdeki her şeyi scikit-learn yapıyor. Her adımın ne yaptığını görebilmek için o yirmi satırı kendiniz yazmalısınız. Bunun üstünde, komşu araması için FAISS ya da usearch ekleyin. Anlamaktan çok cilalı bir çıktı istediğinizde BERTopic’i kullanın — ve Unicode hatasını anlatan kısmı (Bölüm 11.9) okuduğunuza göre, onun hangi varsayılanlarına güvenmemeniz gerektiğini artık biliyorsunuz.
11.15 Lab: sahibi olduğunuz bir derlem için triyaj eğrisi kurun
Teslim edeceğiniz şey, “derlemin %X’ini okumak Z’lerin %Y’sini buluyor” biçiminde tek bir cümle ve onu haklı çıkaran eğri. Kümelemeye bütçe ayrılmasını sağlayan şey bu cümle ve bir silhouette puanından çok daha değerli.
11.15.1 Neye ihtiyacınız var
Anladığınız bir alanda birkaç bin kısa belgeden oluşan herhangi bir derlem — destek talepleri, anketlerdeki açık uçlu cevaplar, hata kaydı (issue) başlıkları, sınav cevapları. Önemsediğiniz tek bir ikili özellik de gerekiyor (şikâyet / değil, acil / değil, konu dışı / değil); bu özelliği derlemin tamamında değil, bir örneklem üzerinde etiketleyebilmelisiniz. 300 belge etiketlemek yeterli ve zaten bütün mesele bu: lab, küçük bir bütçeye sahip olmayı simüle ediyor.
scikit-learn ve sentence-transformers her şeyi hallediyor. 50 bin belgede E5 geçişi bir dizüstü GPU’sunda (Apple Silicon, mps) 104 saniye sürdü. CPU’da kabaca bir büyüklük mertebesi daha uzun sürmesini bekleyin; yani 5 bin belge için birkaç dakika ayırın ve hesaplamayı bu kısmın geri kalanını okumadan önce başlatın.
11.15.2 Adım 1 — önce tekilleştirin ve neyi çıkardığınızı sayın
Her şeyden önce, yakın kopyalar kısmında (Bölüm 11.3) yaptığımız gibi \(J \geq 0{,}8\)’de MinHash + LSH çalıştırın. Grup sayısını ve en büyük grubu raporlayın. Derleminizin kabaca %5’inden fazlası yakın kopyaysa durun ve nedenini bulun — büyük ihtimalle bir veri toplama hatası keşfetmişsinizdir ve bu zaten raporlanmaya değer bir sonuçtur.
11.15.3 Adım 2 — bilinçli olarak iki ayrı temsil çıkarın
Hem bir tf-idf → SVD(256) temsili hem de bir cümle embedding’i temsili kurun. Karşılaştırmalı bir şey söyleyebilmek için en az iki temsil gerekir; asıl ilginç kısım da karşılaştırmanın kendisi. Kümelemeden önce rastgele çift arka planını hesaplayın: 2.000 belge örnekleyin, bütün ikili kosinüsleri alın ve her uzay için ortalamayla standart sapmayı kaydedin. Sonrasında baktığınız her benzerliği yorumlamak için bunlara ihtiyacınız olacak; hesaplamak da dört satır kod tutuyor.
11.15.4 Adım 3 — \(k\)’yi tarayın ve hayal kırıklığına hazır olun
Her iki temsilde \(k \in \{2, 5, 10, 20, 50\}\) için k-means çalıştırın. Silhouette puanını (derlem büyükse sabit bir örneklem üzerinde), en büyük kümenin boyutunu ve eğitim süresini kaydedin. Silhouette’i \(k\)’ye karşı çizin.
Eğriniz düz ve düşükse bizim sonucumuzu yeniden üretmişsinizdir ve bunu yanlış yaptığınız sonucuna varmamalısınız. En büyük küme sütununa dikkat edin: en büyük grubu derlemin %60’ını tutan bir “kümeleme”, hangi \(k\)’yi istemiş olursanız olun tek bir yığın ve etrafa saçılmış kırıntılardır.
11.15.5 Adım 4 — kümeye göre tabakalandırarak 300 belge etiketleyin
İnsanların atladığı adım bu. Seçtiğiniz \(k\)’de, rastgele 300 yerine her kümeden \(300/k\) belge (örneğin \(k=10\)’da kümenin her birinden 30) örnekleyin ve ikili özelliğinizi elle etiketleyin. Tabakalandırma, bir sonraki adımı bu bütçeyle mümkün kılan şey: rastgele 300’lük bir örneklem, en seyrek kümenize yalnızca birkaç belge koyar ve size güvenemeyeceğiniz bir küme başına oran verir.
Küme başına olumlu oranı ve her biri için %95’lik bir aralık yazın. \(n=30\)’da bu aralıklar geniş — %50 civarında kabaca \(\pm 17\) puan — dolayısıyla onları nokta kestirimleri olarak değil, “bu küme derlemden hiç farklı mı?” sorusunun cevabı olarak görün.
11.15.6 Adım 5 — eğri ve cümle
Kümeleri ölçtüğünüz orana göre, en kötüden başlayarak sıralayın. Sonra listede yukarıdan aşağı ilerleyin; her kümede okunan derlem payını ve buna karşılık bulunan özellik payını biriktirin. Bunun için tam olarak bildiğiniz küme boyutlarını ve kestirdiğiniz oranları kullanın. Eğriyi, getiri kısmındaki gibi (Bölüm 11.10) köşegene karşı çizin.
Sonra cümleyi yazın. Eğriniz köşegenle çakışıyorsa doğru cümle şu olur: “kümeleme bu derlemde bu özelliğin triyajına yardım etmiyor” — ki bu da bir bulgudur, size bir öğleden sonraya mal olmuştur ve üzerine bir hat kurmaktan sizi kurtarmıştır.
11.15.7 Daha ileri gitmek
- Adım 5’i diğer temsille yeniden çalıştırın. Bizim LSA ile E5 temsillerimiz ARI altında ayırt edilemezken lift’te 2,5× farklıydı. Sizinkiler de öyle olabilir; öyleyse embedding modelinizi kanıta dayanarak seçmiş olursunuz.
- Unicode kontrolünü (Bölüm 11.9) kendi metninizde, hangi dilde olursa olsun çalıştırın: küçültüp tokenize etmenin idempotent olduğunu — ikinci kez uygulandığında sonucun değişmediğini — doğrulayın;
İSTANBUL’un küçük harfeistanbul,IŞIK’ın daışıkolarak çevrildiğini sınayın; düzgün normalleştirdiğinizde yok olan sözlük türlerini de sayın. - Kümelerinizi ilgili kısımdaki tarifle (Bölüm 11.11) bir LLM’e adlandırtın, sonra her etiketi kendi örneklediğiniz 20 belgeye karşı kontrol edin. Kaç etiketin bu kontrolden geçtiğini sayın. Bir sonraki partiye ne kadar güveneceğinizi bu orana göre ayarlarsınız.
11.16 Alıştırmalar
Hiçbir şey ölçmeyen metrik. k-means kısmındaki (Bölüm 11.5) taramada elde edilen en iyi ARI 0,0083’tü. Aynı kümelemeler getiri kısmında (Bölüm 11.10) ise 1,67×, 2,79× ve 4,23× değerleriyle temiz biçimde ayrıştı. İki sayı da doğru. ARI’nın neyi saydığından yola çıkarak, bir bölümlemenin karar açısından bu kadar anlamlı sinyal taşıyıp yine de nasıl sıfır puan alabildiğini açıklayın. Sonra ARI’nın tam olarak 0, bir kümedeki lift’in ise 2× olduğu küçük bir çözümlü örnek kurun: on belge, iki etiket, iki küme.
Hesaplamadığınız bir arka plan. Bir meslektaşınız, derlemindeki iki belgenin E5 altında 0,91 kosinüs benzerliği olduğunu raporluyor ve yakın kopya oldukları sonucuna varıyor. Benzerlik kısmındaki (Bölüm 11.2) sayıları kullanarak çıkarımın nesinin yanlış olduğunu, meslektaşınızın bu çıkarımı yapmadan önce hangi tek niceliği hesaplaması gerektiğini ve o niceliğin hangi değerinin sonucunu makul kılacağını söyleyin.
Sahip olmadığınız tokenizer testi. Bölüm 11.9, birebir tekilleştirmeden ve hem NFC hem NFKC normalleştirmesinden sonra bile kalan bir kusur buldu. Bölüm 4, kendi kodu bu kusuru üretmesin diye
tr_loweryazdı; ama kendisine verilen metinde zaten bulunan işaretleri geri alamadı. (a) Aynı kusurlu hat üzerinde eğitilip test edilen bir sınıflandırıcının neden çok az ya da hiç görünür doğruluk kaybı göstermediğini açıklayın. (b) Bunu birdenbire görünür kılacak dağıtım değişikliğini adlandırın. (c) Konuşmadığınız bir dilde bu tür hataları yakalamak için sürekli entegrasyon (CI) test paketine ekleyeceğiniz üç satırlık özellik testini yazın —assert tokenize(s.upper()) == tokenize(s)ifadesinin yanlış cevap olduğunu ve nedenini de belirterek.Yoğunluğu doğru okumak. HDBSCAN derlemin LSA’da %97’sine, E5’te %99,5’ine gürültü dedi. Bir takım arkadaşınız önce UMAP ile 5 boyuta inmeyi öneriyor, “çünkü o zaman küme buluyor”. (a) UMAP’in girdide neyi değiştirerek kümelerin belirmesine yol açtığını açıklayın. (b) “UMAP orada olan yapıyı açığa çıkardı” ile “UMAP olmayan yapıyı yarattı” arasında ayrım yapacak bir deney tasarlayın. (c) Hangi sonucun sizi UMAP hattını yine de yayına almaya razı edeceğini söyleyin.
Tutarlılık tuzağı, kendi verinizde. Çalıştırdığınız herhangi bir konu modelinden en yüksek tutarlılıklı konuyu alın ve o konuda en yüksek puanı alan 20 belgeyi okuyun. Konu gerçekse, bir meslektaşın yeni belgeleri o konuya atamak için kullanabileceği tek satırlık tarifi yazın. Değilse, modelin gerçekte neye takıldığını belirleyin. Hangisinin olduğunu raporlayın — ve bu bölümde koşunun tamamındaki en yüksek tutarlılıklı konunun ikinci durum olduğunu not edin.
Bir dipnottaki, ölçmediğimiz iddia. Bölüm 11.2’deki uzaklıklarla ilgili dipnot, \(\ell_2\)-normalleştirilmiş vektörler üzerindeki Öklit k-means ile küresel k-means’in “metinde genellikle benzer yerlere düştüğünü” söylüyor ve bunun doğrulanmamış bir kanı olduğunu kabul ediyor. Meseleyi çözün. Küresel k-means’i yazın — her güncellemeden sonra merkezleri birim uzunluğa yeniden normalleştiren Lloyd algoritması — ikisini de aynı vektörler üzerinde \(k=10\)’da çalıştırın ve her temsil için iki bölümleme arasındaki ARI’yı raporlayın. Sonra Bölüm 11.10’daki en kötü küme lift’inin kıpırdayıp kıpırdamadığına bakın. İki sonuçtan hangisinin dipnotu değiştirmenize yol açacağını ve nasıl değiştireceğinizi söyleyin.
İndekssiz \(k\) seçimi. 40.000 destek talebiniz ve her biri bir kategoriyi sahiplenecek altı kişilik bir destek ekibiniz var. Hiçbir içsel doğrulama indeksi kullanmadan belirli bir \(k\) değerini gerekçelendirin. Hangi durumun sizi bu değeri gözden geçirmeye iteceğini söyleyin. Ayrıca bu akıl yürütmenin bir dirsek grafiğinden neden yalnızca daha kullanışlı değil, daha sağlam temelli olduğunu açıklayın.
Triyaj sonucunu uygulanabilir bir politikaya çevirin. Bölüm 11.10, on kümeyi bütün referans etiketlerden hesaplanan bir olumsuzluk oranına göre sıralıyor ve recall’u aynı etiketlere karşı puanlıyor. Bunu etiket sızıntısı olmadan yeniden yapın: rastgele bir test yarısı ayırın, diğer yarıdan 300 belgelik bir geliştirme örneklemi etiketleyin, kümeleri yalnızca o örneklemdeki olumsuzluk oranına göre sıralayın ve triyaj eğrisini test yarısında okuyun. %13,3’te %56,0 sonucunun ne kadarının ayakta kaldığını ve geliştirme örneklemini 100’e küçültüp 1.000’e büyüttüğünüzde cevabın nasıl oynadığını bildirin.
11.17 Daha derine inmek için
Herhangi bir makaleden önce: kümelemenizi iki farklı seed ile çalıştırıp atamaları (örneğin aralarındaki ARI ile) karşılaştırın. Ayrışıyorlarsa, yazmak üzere olduğunuz her yorum aslında seed hakkındadır. Aynı kontrolü derlemin rastgele altörneklemlerinde (bootstrap ya da rastgele yarılar) de yapın: yalnızca yeniden örnekleme altında ayakta kalan kümeler üzerine yorum yazın.
| kaynak | ne olduğu |
|---|---|
| BERTopic belgelendirmesi | alışılmadık derecede iyi hazırlanmış — “best practices” sayfası neyin ters gittiği konusunda kısa bir ders |
| UMAP belgelendirmesi: “Using UMAP for Clustering” | UMAP çıktısı üzerinde kümelemenin tuzaklarını açıkça yazıyor (yoğunluğu tam korumaması, kümelerde sahte kopmalar yaratabilmesi); bu bölümün alanındaki en yaygın hata |
| scikit-learn kümeleme rehberi | algoritmalar yan yana, her birinin yaptığı varsayım açıkça yazılmış |
hdbscan |
gürültü işleme kısmını okuyun; derleminizin neden bu kadar büyük bir kısmının etiketsiz döndüğünü açıklıyor |
| Sentence Transformers | buradaki her şeyin üzerine kurulduğu embedding’ler, hangisini seçeceğinize dair açık bir rehberle |
| Visualizing High-Dimensional Space — Google | bir izdüşümün neyi koruyup neyi korumadığı üzerine dört dakika; herhangi bir UMAP grafiğine güvenmeden önce izleyin |
| konu | kaynak |
|---|---|
| herkesin başladığı konu modeli | Blei vd. (2003) |
| ve insanların çıktısında gerçekte ne gördüğü | Chang vd. (2009) |
| bunun yerine embedding artı kümeleme | Grootendorst (2022) |
| “gürültü” diyebilen yoğunluk kümelemesi | Campello vd. (2013); McInnes ve Healy (2017) |
| muhtemelen fazla yorumladığınız izdüşüm | McInnes vd. (2018) |
| \(k\)’yi seçmek ve ölçütlerin neden ayrıştığı | Rousseeuw (1987); Schubert (2023) |
| bölümlemeleri doğru dürüst karşılaştırmak | Hubert ve Arabie (1985); Rosenberg ve Hirschberg (2007) |
| tutarlılık ve sınırları | Bouma (2009) |
| ölçekte yakın kopya tespiti | Broder (1997); Charikar (2002); Manku vd. (2007) |
| tekilleştirmenin ön eğitim verisinde neden önemli olduğu | Lee vd. (2022); Penedo vd. (2024) |
| kosinüs benzerliğini fazla birebir okumak | Steck vd. (2024) |
11.18 Akılda kalması gerekenler
- Kümeleme, derlemi okuyamadığınızda ve etiketiniz olmadığında yaptığınız şeydir. Sınıflandırmanın zayıf bir biçimi değil; farklı bir soruyu cevaplıyor ve sınıflandırıcıları değerlendiren metrikler onu doğru değerlendiremiyor.
- Benzerlik, belgelerin değil geometrinin bir özelliğidir. 0,98’lik bir kosinüs, rastgele iki belgenin ne aldığını bilene kadar hiçbir şey ifade etmez. Dört uzayımızda rastgele çift ortalaması 0,018 ile 0,855 arasında değişti, yani aynı sayı bir uzayda “yakın kopya”, bir başkasında “sıradan” demek. Arka planı her zaman hesaplayın.
- Her şeyden önce tekilleştirin. Ucuzdur ve bölümde kod satırı başına en yüksek getiriyi sağlayan iştir. Elde ettiğiniz sayı da veri toplama hattınız hakkında bir tanı koyar. \(J \geq 0{,}8\)’de 1,25 milyar çiftin tamamını karşılaştırmadan, 27 saniyede 151 belge çıkardık.
- k-means sizin adınıza dört varsayım yapıyor — küresel kümeler, benzer yayılım, aykırı değer yokluğu ve bilinen bir \(k\) — ve metin derlemlerinde sorun çıkaranlar, herkesin endişelendiği varsayım değil, 2 ve 3 numaralı olanlar.
- Düz bir silhouette eğrisi bir bulgudur. Bizimki 42 koşuda 0,1042’yi hiç geçmedi. HDBSCAN da bundan bağımsız olarak,
min_cluster_sizedeğerine göre aynı derlemin %53–100’üne gürültü dedi ve hiçbir ayarda üçten fazla küme döndürmedi. Gürültü oranının en düşük olduğu ayarda (LSA ve MiniLM’de %53–55) bile geri kalanı, derlemin kabaca %45’ini tutan tek bir yığında topladı. Farklı varsayımlara dayanan iki yöntemin sınır olmadığı konusunda hemfikir olması, ikisinden birinin tek başına söylemesinden daha güçlü bir kanıt. - Dirsek yöntemini kullanmayın. Monoton bir eğri, kullanılabilir bir bükülme vaadi değildir; bükülmeyi nerede gördüğünüz de eksen sınırlarınıza bağlıdır. Schubert (2023) bu savı uzun uzun kuruyor.
- Kısa belgeler LDA’yı bozuyor. 19 kelimelik yorumlarda NMF’ten 133× yavaştı ve daha az tutarlıydı. Kısa metin üzerinde bir LDA hattı devraldıysanız, mevcut olanı savunmadan önce yanında NMF çalıştırın.
- Modern varsayılan: önce kümele, sonra betimle. Kümeleriniz hazırsa c-TF-IDF’in ek bir maliyeti yok. Embedding’in bütün anlambilimini miras alıyor; kümelemenin bütün hatalarını da.
- Konu tutarlılığı çöple maksimize edilebilir. Bölümün tamamındaki en yüksek puanlı konumuz, +0,5075 ile, on tokenizer parçasıydı. Bu konuyu çıkarmak, onu üreten yöntemi birincilikten sonunculuğa düşürdü. Otomatik bir ölçütün insan yargısından ayrışabileceğini Chang vd. (2009) olabilirlik için, Hoyle vd. (2021) tutarlılık ölçüleri için gösterdi; bizim vakamız bunun uç bir örneği.
- Denetimsiz yöntemler verinizde gerçekte ne olduğunu bulur — koymadığınız parçalar dâhil. k-means’e Unicode hakkında hiçbir şey söylenmemişti; yine de belgelerinin %94,7’si bir Unicode kusurundan etkilenmiş bir küme oluşturdu. Derlemin genelinde bu oran %6,0’dı. Bölüm 4 o kusuru Türkçe konuşan biri bildiği için biliyordu; kümeleme onu böyle biri olmadan buldu.
str.lower()Türkçeye duyarlı değil ve NFKC sizi kurtarmayacak."TAVSİYE".lower()ifadesi['tavsi', 'ye']olarak tokenize ediliyor. Genel bir gidiş-dönüş doğrulamak yerine önemsediğiniz durumları sabitleyin —assert tokenize("TAVSİYE") == tokenize("tavsiye").tokenize(s.upper()) == tokenize(s)daha derli toplu görünüyor ve doğru kodda bile başarısız oluyor, çünkü Python’unstr.upper()metodu da Türkçeye duyarlı değil:i’yiİyerineI’ya çeviriyor, yani küçültücünüz ne kadar iyi olursa olsuniyigeriıyıolarak dönüyor.- Bölümlemeyi değil, kararı ölçün. ARI üç temsilimizi ayırt edemedi; triyaj eğrisi onları temiz biçimde ve beklenen sırada sıraladı. Referans etiketlerin tamamına bakılarak seçilmiş bir sıralamayla derlemin %13,3’ünü okumak, şikâyetlerinin %56,0’ını buldu — her dışsal indekste sıfır alan bir kümelemeden, sabit bir bütçe üzerinde 4,2× getiri. Devreye alabileceğiniz bir politika için o sıralamanın bir örneklemde seçilip başka bir örneklemde ölçülmesi gerekir.
- “Kümeleme başarısız oldu” neredeyse her zaman erken bir yargıdır. Desteklemesi gereken kararı yazın, onu ölçün ve ancak ondan sonra karar verin. Sınıflar belli olduğunda ve etiketlemeye gücünüz yettiğinde iş sınıflandırmaya geçer; sıradaki bölüm, Bölüm 12, oradan devam ediyor.
\(\lVert a \rVert = \lVert b \rVert = 1\) ise \(d_{\text{euc}}(a,b)^2 = 2 - 2\cos(a,b)\) olur; yani birine göre sıralamak diğerine göre sıralamaktır. Bunu fazla genellemeyin. Bu eşitlik “aynı en yakın komşular” demenize izin verir, “aynı algoritma” demenize değil. Lloyd’un k-means’i her merkezi üyelerinin aritmetik ortalamasıyla değiştirir. Birim vektörlerin ortalaması ise birim vektör değildir; bu yüzden ikinci yinelemeden itibaren normalleştirilmiş embedding’ler (gömme) üzerindeki Öklit k-means ile küresel k-means gerçekten farklı işlemlerdir. Metin verisinde genellikle benzer yerlere vardıkları söylenir; biz burada bunu kontrol etmedik. O cümle bir ölçüm değil, yaygın bir kanı. Yirmi satırlık bir küresel k-means (merkezleri her yinelemede yeniden normalleştirin) yazıp scikit-learn’ün
KMeans’iyle aynı vektörler üzerinde \(k=10\)’da ARI ile karşılaştırmak bu derlem için meseleyi bir öğleden sonrada çözer; Bölüm 11.16 bunu sizden istiyor. Bu bölümdeki her embedding kümelemeden önce \(\ell_2\)-normalleştiriliyor ve her silhouettemetric="cosine"ile hesaplanıyor; böylece atama adımı puanlama adımıyla anlaşıyor.↩︎