Ders 10 / 12
Boyut Azaltmanın Öznitelik Rolü
On üç ham özniteliğin yerine bileşen temelli bir temsil konduğunda ayrılmış küme sayısının ve yorumlanabilirliğin ne olduğunun ölçülmesi: ham sütunlar sınamada 0,8254 verirken iki bileşen 0,8175, üç bileşen 0,8056, beş bileşen 0,7778, sekiz bileşen 0,7460 veriyor ve hiçbir bileşen sayısında ham temsile yetişilemiyor. En büyük bileşen payını taşıyan bileşen tek başına 0,7381 ile tabanın altında kalırken payı 0,093 olan beşinci bileşen 0,7659 veriyor. Ham temsilde bölmelerin 0,35'i ortalama tüketimden okunurken bileşen temsilinde aynı pay adı olmayan bir karışıma düşüyor.
İçindekiler
Önceki ders sütun sayısını azaltmanın bir yolunu ölçtü: sütunları teker teker tutmak ya da atmak. Gömülü yöntem yirmi beş adaydan on dördünü tuttu ve ayrılmış kümede 0,8254 verdi; iki dersin elle ölçerek kurduğu on üç sütunluk küme de aynı sayıyı verdi. Tutulan sütunların hepsinin bir adı var ve ne anlama geldikleri biliniyor.
Sütun sayısını azaltmanın ikinci yolu sütunları atmak yerine karıştırmaktır. On üç sütun, her biri on üçünün ağırlıklı toplamı olan birkaç yeni sütuna dönüştürülebilir; bunlara bileşen denir ve bileşenler kümedeki değişkenliği en çok taşıyan yönlerden başlayarak sıralanır. M26/K05’in keşifsel analiz kursu bileşen payını orada ölçmüştü ve kuram burada tekrarlanmaz. Bu dersin sorduğu tek soru şudur: bileşenler bir öznitelik olarak ne yapıyor — kaç bileşende ham özniteliklerin ayrılmış küme sayısına yetişiliyor ve karşılığında ne kaybediliyor.
- OS22. Ham temsil on üç sütundur: M27/K01’in on bir sütunu,
kisi_basivea_muhur. Ayrılmış kümedeki sayısı 0,8254’tür ve bu dersin karar öncesi çizgisidir. - OS23. Ölçek ve bileşen yönleri yalnız eğitim kümesinden öğrenilir, üç kümeye de aynı sayılarla uygulanır. Bütün kümeden öğrenilseydi ölçüm şişerdi.
- OS24. Bileşenler ders içinde yazılır: standartlaştırılmış eğitim sütunlarının eşdeğişim dizeyi kurulur, en büyük yönü yineleme ile bulunur, bulunan yön dizeyden çıkarılır ve işlem on üç kez yinelenir. Kitaplık çağrılmaz.
- OS25. Yineleme sayısı her bileşen için 200’dür; bu sayı sonuca bakılarak seçilmemiştir. Kalan büyüklüğü ’nin altına düşerse yineleme erken durur.
- OS26. Bileşen payı, bileşenin taşıdığı değişkenliğin toplam değişkenliğe oranıdır.
- OS27. Bileşenler etiketi görmez. Sıralamaları değişkenliğe göredir, ayrım gücüne göre değildir.
- OS28. Model değişmez: derinlik 6 karar ağacı. Taban çizgisi 0,7579’dur.
- OS29. Yorumlanabilirlik ölçüsü, ağacın bölmelerinin hangi sütundan okunduğudur; her bölme böldüğü satır sayısıyla ağırlıklandırılır.
On Üç Sütun, On Üç Bileşen
# ORTAK — MODELDIR. M27/K01'in KURGU abone tablosu ayni tohumla yeniden uretilir; # model derinlik 6 karar agacidir. Onceki dersten kalan tek yeni sutun kisi_basi. import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10), ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05), ("merkez", 0.18, 23, 0.05)] def uretec(t): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki(): s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki def ayrik(u, w): t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 ABONE, VERI = [], [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]) memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) if r() >= 0.046: ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun}) for k in ABONE: r, v = uretec(TOHUM + 7000 + k["no"]), [] for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): v.append(0.0 if r() < 0.038 else math.floor( k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100) r() if not v: continue ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"]) z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3] + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30) x = {"no": k["no"], "hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v), "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35), "bolge_ad": k["bolge"][0]} for b in BOLGE: x["b_" + b[0]] = int(k["bolge"][0] == b[0]) VERI.append(x) TEMEL = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"] TABAN_ALAN = TEMEL + ["kisi_basi"] for x in VERI: x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3) def karistir(veri, tohum): r, s = uretec(tohum), list(range(len(veri))) for i in range(len(s) - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] return [veri[i] for i in s] K = karistir(VERI, TOHUM + 90000) EGT, DOG, SIN = K[:756], K[756:1008], K[1008:] def gini(s): p = sum(x["supheli"] for x in s) / len(s) if s else 0.0 return 2 * p * (1 - p) def agac(s, derinlik, alanlar, enaz=2): p, en = sum(x["supheli"] for x in s) / len(s), None if derinlik and len(s) >= 2 * enaz and 0.0 < p < 1.0: for a in alanlar: d = sorted({x[a] for x in s}) for v in (d[1:] if len(d) < 10 else [d[int(i * len(d) / 10)] for i in range(1, 10)]): sol = [x for x in s if x[a] < v] sag = [x for x in s if x[a] >= v] if min(len(sol), len(sag)) < enaz: continue k = gini(s) - (len(sol) * gini(sol) + len(sag) * gini(sag)) / len(s) if en is None or k > en[0]: en = (k, a, v, sol, sag) if en is None or en[0] <= 1e-9: return {"tahmin": int(p > 0.5)} return {"alan": en[1], "esik": en[2], "sol": agac(en[3], derinlik - 1, alanlar, enaz), "sag": agac(en[4], derinlik - 1, alanlar, enaz)} def tahmin(d, x): while "tahmin" not in d: d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"] return d["tahmin"] def dogruluk(d, s): return sum(tahmin(d, x) == x["supheli"] for x in s) / len(s) def taban(egt, s): c = int(sum(x["supheli"] for x in egt) * 2 > len(egt)) return sum(x["supheli"] == c for x in s) / len(s) def olc(alanlar, derinlik=6): m = agac(EGT, derinlik, alanlar) return dogruluk(m, EGT), dogruluk(m, SIN)
Bileşenleri bulmak için üç adım gerekir: sütunları ortak bir ölçeğe getirmek, eşdeğişim dizeyini kurmak ve en büyük değişkenliği taşıyan yönü bulup dizeyden çıkarmak. Üçüncü adım on üç kez yinelenince on üç bileşen çıkar. Ölçek ve yönlerin hepsi yalnız eğitim kümesinden okunur.
for x in VERI: r = uretec(TOHUM + 61000 + x["no"]) r(), r() x["a_muhur"] = int(r() < (0.42 if x["supheli"] else 0.10)) HAM_ALAN = TABAN_ALAN + ["a_muhur"] ORT = {a: sum(x[a] for x in EGT) / len(EGT) for a in HAM_ALAN} SAC = {a: max(1e-9, (sum((x[a] - ORT[a]) ** 2 for x in EGT) / len(EGT)) ** 0.5) for a in HAM_ALAN} for x in VERI: x["_z"] = [(x[a] - ORT[a]) / SAC[a] for a in HAM_ALAN] n = len(HAM_ALAN) C = [[sum(x["_z"][i] * x["_z"][j] for x in EGT) / len(EGT) for j in range(n)] for i in range(n)] def carp(m, v): return [sum(m[i][j] * v[j] for j in range(len(v))) for i in range(len(m))] BILESEN, PAY = [], [] A = [satir[:] for satir in C] for _ in range(n): v = [1.0 / (i + 1) for i in range(n)] for _ in range(200): w = carp(A, v) u = sum(q * q for q in w) ** 0.5 if u < 1e-12: break v = [q / u for q in w] lam = sum(v[i] * carp(A, v)[i] for i in range(n)) BILESEN.append(v) PAY.append(max(0.0, lam)) A = [[A[i][j] - lam * v[i] * v[j] for j in range(n)] for i in range(n)] TOP = sum(PAY) for x in VERI: for i, v in enumerate(BILESEN): x["c" + str(i)] = round(sum(x["_z"][j] * v[j] for j in range(n)), 4) HAM = olc(HAM_ALAN) print(f"{'temsil':<22} {'sutun':>5} {'pay':>7} {'egitimde':>9} {'ayrilmis':>9} {'fark':>8}") print(f"{'ham oznitelikler':<22} {n:>5} {'':>7} {HAM[0]:>9.4f} {HAM[1]:>9.4f}") for k in (1, 2, 3, 5, 8, 11, 13): e, s = olc(["c" + str(i) for i in range(k)]) print(f"{'bilesen ' + str(k):<22} {k:>5} {sum(PAY[:k]) / TOP:>7.3f} {e:>9.4f} " f"{s:>9.4f} {s - HAM[1]:>+8.4f}") print(f"\ntaban cizgisi {taban(EGT, SIN):.4f}")
temsil sutun pay egitimde ayrilmis fark ham oznitelikler 13 0.8876 0.8254 bilesen 1 1 0.177 0.8003 0.7381 -0.0873 bilesen 2 2 0.323 0.8651 0.8175 -0.0079 bilesen 3 3 0.432 0.8677 0.8056 -0.0198 bilesen 5 5 0.630 0.9074 0.7778 -0.0476 bilesen 8 8 0.877 0.9074 0.7460 -0.0794 bilesen 11 11 0.990 0.8995 0.7817 -0.0437 bilesen 13 13 1.000 0.9048 0.7897 -0.0357 taban cizgisi 0.7579
Sorunun ilk yarısının yanıtı tablodadır: hiçbir bileşen sayısında ham özniteliklere yetişilemiyor. En yakın satır iki bileşendir; 0,8175 ile ham temsilin 0,0079 altında, yani iki abone. On üç sütun iki sütuna indirilmiş ve iki abone kaybedilmiştir. Bu, bir sıkıştırma kararı olarak savunulabilir bir dengedir.
Tablonun asıl bulgusu bundan sonra geliyor. Bileşen sayısı arttıkça sayı iyileşmiyor: üç bileşende 0,8056, beşte 0,7778, sekizde 0,7460. Bileşen payı ise düzenli olarak büyüyor — 0,323’ten 0,877’ye. İki sütun aynı yöne gitmiyor. On üç bileşenin hepsi kullanıldığında bilgi kaybı yoktur, temsil ham temsilin döndürülmüş hâlidir ve yine de sayı 0,7897’de kalıyor; fark 0,0357. Karar ağacı bölmelerini eksenlere dik yapar ve döndürülmüş bir eksende aynı ayrımı kurmak için daha çok bölme gerekir. Bileşen temsili modelden bağımsız değildir.
Pay Sıralaması Ayrım Sıralaması Değildir
Bileşenler etiketi hiç görmez; sıralamaları yalnız hangi yönde daha çok değişkenlik olduğuna bakar. Etiketin o yönlerde durup durmadığı ayrı bir sorudur ve ölçülmesi gerekir.
def kullanim(d, s): say = {} def gez(d, s): if "tahmin" in d: return say[d["alan"]] = say.get(d["alan"], 0) + len(s) gez(d["sol"], [x for x in s if x[d["alan"]] < d["esik"]]) gez(d["sag"], [x for x in s if x[d["alan"]] >= d["esik"]]) gez(d, s) t = sum(say.values()) return ", ".join(f"{a} {say[a] / t:.2f}" for _, a in sorted((-say[a], a) for a in say)[:4]) print("ham temsilde en cok bolunen:", kullanim(agac(EGT, 6, HAM_ALAN), EGT)) print("bilesen temsilinde :", kullanim(agac(EGT, 6, ["c" + str(i) for i in range(13)]), EGT)) for i in (0, 1): y = sorted(((-abs(BILESEN[i][j]), HAM_ALAN[j], BILESEN[i][j]) for j in range(n))) print(f"c{i} yukleri (pay {PAY[i] / TOP:.3f}): " + ", ".join(f"{a} {w:+.2f}" for _, a, w in y[:4]) + f", ... kalan {n - 4} sutunun toplam agirligi " f"{sum(abs(w) for _, _, w in y[4:]):.2f}") print() print(f"{'tek bilesen':<14} {'pay':>7} {'egitimde':>9} {'ayrilmis':>9}") for i in range(5): e, s = olc(["c" + str(i)]) print(f"{'c' + str(i):<14} {PAY[i] / TOP:>7.3f} {e:>9.4f} {s:>9.4f}")
ham temsilde en cok bolunen: ort_tuketim 0.35, oynaklik 0.19, a_muhur 0.17, kisi_basi 0.14 bilesen temsilinde : c0 0.29, c1 0.25, c8 0.12, c2 0.11 c0 yukleri (pay 0.177): kisi_basi +0.54, ort_tuketim +0.53, b_bati -0.34, b_dogu +0.30, ... kalan 9 sutunun toplam agirligi 1.16 c1 yukleri (pay 0.146): oynaklik +0.62, sifir_okuma +0.51, donem +0.42, a_muhur +0.29, ... kalan 9 sutunun toplam agirligi 0.86 tek bilesen pay egitimde ayrilmis c0 0.177 0.8003 0.7381 c1 0.146 0.8267 0.7421 c2 0.109 0.8188 0.7579 c3 0.105 0.7937 0.7579 c4 0.093 0.8148 0.7659
Son tablo pay sıralamasının ayrım sıralaması olmadığını sayıyla gösteriyor. Payı en büyük bileşen
c0, tek başına 0,7381 veriyor — taban çizgisinin 0,0198 altında. Payı yarısı kadar olan
c4 ise 0,7659 veriyor ve tabanın üstünde kalıyor. “En çok değişkenliği taşıyan yön” ile “en çok
ayıran yön” iki ayrı şeydir, ve bileşenler yalnız birincisine göre sıralandığı için ilk k bileşeni
almak ayrım açısından keyfi bir kesmedir.
İki bileşenin birlikte 0,8175 vermesi de buradan anlaşılıyor: c0 tüketim büyüklüğünü,
c1 ise oynaklık ile sıfır okumayı taşıyor. Etiketin iki ayrı nedeni iki ayrı bileşene düşmüş
durumda ve model ikisini birleştirebiliyor.
Yorumlanabilirlikten Kaybedilen
Kaybın ikinci yarısı sayıda değil, adlarda. Ham temsilde bölmelerin 0,35’i ort_tuketim‘den,
0,19’u oynaklik‘tan, 0,17’si mühür göstergesinden okunuyor. Bu üç satır bir saha ekibine
verilebilir: yüksek tüketim, oynak okuma ve mühür kaydı. Bileşen temsilinde aynı liste c0 0,29,
c1 0,25, c8 0,12 diye çıkıyor ve hiçbir şey söylemiyor.
Bileşenin ne olduğu ancak yükleri okunarak anlaşılır ve yükler tek bir sütuna işaret etmez. c0
kişi başı tüketim ile ortalama tüketimi ağırlıklı olarak taşıyor, ama geri kalan dokuz sütunun
toplam ağırlığı 1,16 — yani bileşenin yarıdan fazlası, dört büyük yükün dışındaki sütunlardan
geliyor. “Bu abone niçin şüpheli işaretlendi” sorusunun yanıtı ham temsilde bir sütun adı ve bir
eşiktir; bileşen temsilinde on üç sayının ağırlıklı toplamıdır.
Karar, iki kaybın karşılaştırılmasıdır. İki bileşene inmek 0,0079 sayı ve on bir sütunluk saklama kazandırır; karşılığında modelin verdiği her kararın gerekçesini bir tabloya yazma olanağı kaybedilir. Kaçak şüphesi gibi bir alanda ikinci kayıp genellikle daha pahalıdır, çünkü bir aboneye yapılan işlemin gerekçesi sorulabilir. Bileşen temsilinin öznitelik rolü bu yüzden dar bir roldür: sütun sayısı gerçekten yönetilemeyecek kadar büyükse ya da sütunlar birbirinin kopyasıysa değerlidir, tek tek ölçülmüş on üç sütun varken değildir.
Özet
- Ham on üç sütun ayrılmış kümede 0,8254 veriyor; hiçbir bileşen sayısı buna yetişemiyor, en yakın satır iki bileşenle 0,8175 (fark 0,0079, iki abone).
- Bileşen payı büyürken ayrılmış küme sayısı büyümüyor: üç bileşende 0,8056, beşte 0,7778, sekizde 0,7460; on üç bileşende bilgi kaybı yokken sayı yine 0,7897’de kalıyor.
- Payı en büyük bileşen tek başına 0,7381 ile tabanın altında kalırken payı 0,093 olan beşinci bileşen 0,7659 veriyor; pay sıralaması ayrım sıralaması değildir.
- Yorumlanabilirlik ölçülebilir bir kayıptır: ham temsilde bölmelerin 0,35’i ortalama tüketimden okunuyor, bileşen temsilinde aynı pay adı olmayan bir karışıma düşüyor.
- Ölçek ve bileşen yönleri yalnız eğitim kümesinden öğrenilir; bütün kümeden öğrenilseydi ölçüm şişerdi.
Sonraki Adım
Dört derste hazırlama adımlarının sayısı arttı ve her birinde aynı cümle tekrarlandı: bu adım yalnız eğitim kümesinden öğrenilir. Ölçek ortalaması, bölge ortancası, seçilen sütun kümesi, bileşen yönleri — dördü de eğitilmiş nesnelerdir ve dördü de elle, ayrı ayrı, doğru sırayla uygulanmak zorundadır. Bu zincir elle uygulandığında kaç adımın yanlış kümeden öğrenildiğini saymak gerekir. Sonraki ders hazırlama ile modeli tek bir nesnede birleştirir ve boru hattı olmadan kaç adımın sızdığını ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.