Ders 13 / 20
Karışıklık Matrisi
Aynı doğruluğu veren iki modelin hata dağılımının ayrılması: kırk dokuz aday arasında on dört doğruluk değeri birden çok aday tarafından paylaşılır, 0,7817 veren iki aday 61 şüpheliden birinde 16'sını diğerinde 32'sini yakalar ve işaretlenen abone sayısı 26 ile 58 arasında değişir. Saha ziyareti 1, kaçırılan kaçak 6 birim sayıldığında bedel 296 ile 232 olur, taban çizgisinin bedeli 366'dır ve herkesi şüpheli demek 252 ile taban çizgisinden ucuzdur. Doğrulukta en iyi aday bedelde 263 verirken bedelde en iyi aday doğrulukta kırk dokuz aday içinde yirminci sıradadır.
İçindekiler
Önceki konu yedi model ailesini aynı ayrılmış küme üzerinde denedi ve her sayının yanına o sayıyı bulmak için kaç aday denendiğini yazdı. Karşılaştırmanın tamamı tek bir sayı üzerinden yürüdü: doğruluk. Ailenin kattığı fark da, ayar bütçesinin şişirdiği fark da bu tek sayıda okundu. O sayının hangi hataları sakladığı hiç sorulmadı.
Sınama kümesindeki 252 abonenin 61’i şüpheli. Doğruluğu 0,80 olan bir model elli abonede yanılıyor demektir, ama bu elli yanılgının yönü yazmıyor: şüpheli olmayana şüpheli demek ile şüpheliyi gözden kaçırmak aynı hücreye düşüyor. İkisi birbirinin yerine geçmez — birinin bedeli boşa giden bir saha ziyareti, ötekinin bedeli fark edilmemiş bir kaçaktır.
- MD1. Küme, bölme ve öznitelikler kurs boyunca sabittir: kurgu abone tablosu, 756/252/252 bölme, öznitelik mühendisliği kursunun bıraktığı on iki öznitelik. Değişen tek şey modeldir.
- MD2. Taban çizgisi değişmez: eğitim kümesinin en sık sınıfını her aboneye söylemek. Bu yordam sınama kümesinde 0,7579 verir.
- MD3. Olumlu sınıf şüpheli abonedir. Olumlu/olumsuz sözcükleri değer yargısı değil, sayılan sınıfın adıdır.
- MD4. Model bir olasılık üretir ve bu derste karar eşiği 0,5’te sabittir. Eşiğin kendisi bu konunun üçüncü dersine bırakılır.
- MD5. Kırk dokuz aday denenir: altı derinlik ile yedi sınıf ağırlığının çarpımı olarak kırk iki karar ağacı, yedi sınıf ağırlığında eğim temelli doğrusal model. Sınıf ağırlığı öznitelik mühendisliği kursundaki biçimiyle kullanılır.
- MD6. Bu ders model seçmez; kırk dokuz adayın hepsinin sınama kümesindeki sayısı basılır. Doğrulama kümesinden seçim yapmak üçüncü dersin işidir.
- MD7. Bedel iki kalemden oluşur: işaretlenen her abone için bir saha ziyareti, kaçırılan her şüpheli için bir kaçırılmış kaçak. Ziyaret bedeli işaretlenen bütün abonelere yazılır, ziyaretin sonucu bedeli değiştirmez. Birim değerleri kurgudur ve veriden okunmaz.
Dört Hücre
Karışıklık matrisi (confusion matrix) iki sınıflı bir kararda dört sayı tutar. Model şüpheli dediğinde abone gerçekten şüpheliyse doğru olumlu (true positive), değilse yanlış olumlu (false positive). Model şüpheli demediğinde abone şüpheliyse yanlış olumsuz (false negative), değilse doğru olumsuz (true negative). Doğruluk bu dört sayının ikisini toplayıp dörde böler; kalan bilgi atılır.
# degerlendirme.py — MODELDIR. Kurgu abone tablosu ayni tohumla yeniden uretilir. import math TOHUM, ADAY, 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, OKUMA = [], {} for i in range(ADAY): 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 = uretec(TOHUM + 7000 + k["no"]) for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): OKUMA.setdefault(k["no"], []).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() VERI = [] for k in ABONE: v = OKUMA.get(k["no"]) 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 = {"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)} x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3) for b in BOLGE: x["b_" + b[0]] = int(k["bolge"][0] == b[0]) VERI.append(x) 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:] ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma", "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"] def safsizlik(s): n = sum(x.get("w", 1.0) for x in s) p = sum(x.get("w", 1.0) * x["supheli"] for x in s) / n return 2 * p * (1 - p) def agac(s, derinlik, alan, enaz=2): # MODELDIR: agirlikli karar agaci n = sum(x.get("w", 1.0) for x in s) p = sum(x.get("w", 1.0) * x["supheli"] for x in s) / n en = None if derinlik and len(s) >= 2 * enaz and 0.0 < p < 1.0: for a in alan: 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 = safsizlik(s) - (sum(x.get("w", 1.0) for x in sol) * safsizlik(sol) + sum(x.get("w", 1.0) for x in sag) * safsizlik(sag)) / n if en is None or k > en[0]: en = (k, a, v, sol, sag) if en is None or en[0] <= 1e-9: return {"p": p} return {"alan": en[1], "esik": en[2], "sol": agac(en[3], derinlik - 1, alan, enaz), "sag": agac(en[4], derinlik - 1, alan, enaz)} def olasilik(d, x): while "p" not in d: d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"] return d["p"] def agirlikla(egt, w): return [dict(x, w=(w if x["supheli"] else 1.0)) for x in egt] def matris(skor, veri, esik=0.5): # do, yo, yn, dn m = [0, 0, 0, 0] for x in veri: i = (0 if x["supheli"] else 1) + (0 if skor(x) >= esik else 2) m[i] += 1 return m NS = sum(x["supheli"] for x in SIN) print(f"sinama kumesi {len(SIN)} abone, supheli {NS}, " f"taban cizgisi {1 - NS / len(SIN):.4f}") t6 = agac(EGT, 6, ALAN) m6 = matris(lambda x: olasilik(t6, x), SIN) print(f"derinlik 6 karar agaci: dogruluk {(m6[0] + m6[3]) / len(SIN):.4f}") print(f"{'':>18}{'gercek supheli':>16}{'gercek degil':>14}") print(f"{'supheli dendi':>18}{m6[0]:>16}{m6[1]:>14}") print(f"{'supheli denmedi':>18}{m6[2]:>16}{m6[3]:>14}")
sinama kumesi 252 abone, supheli 61, taban cizgisi 0.7579
derinlik 6 karar agaci: dogruluk 0.7937
gercek supheli gercek degil
supheli dendi 24 15
supheli denmedi 37 176
Doğruluk 0,7937 ve taban çizgisinin üstünde. Matris aynı modeli başka türlü okutuyor: model 61 şüphelinin 24’ünü yakalıyor, 37’sini kaçırıyor, 15 aboneyi de boşuna işaretliyor. Doğruluğun büyük bölümü sağ alt hücreden geliyor — kümede çoğunluk zaten onlar. Taban çizgisinin 0,7579’u tamamen o hücreden gelir: hiç kimseye şüpheli demeyen yordam 191 doğru olumsuz toplar ve 61 yanlış olumsuz biriktirir.
Aynı Sayı, Başka Matris
Doğruluğun bilgi attığı en açık biçimde iki modelin aynı sayıyı vermesiyle görülür. Kırk dokuz aday denenir ve aynı doğruluk değerini paylaşan adaylar aranır.
def olcek(egt, alan): o = {a: sum(x[a] for x in egt) / len(egt) for a in alan} s = {a: (sum((x[a] - o[a]) ** 2 for x in egt) / len(egt)) ** 0.5 or 1.0 for a in alan} return lambda x: [(x[a] - o[a]) / s[a] for a in alan] def dogrusal(egt, alan, w, tur=300, adim=0.5): # MODELDIR: egim temelli dogrusal model f, k, b = olcek(egt, alan), [0.0] * len(alan), 0.0 X = [f(x) for x in egt] y = [x["supheli"] for x in egt] a = [(w if x["supheli"] else 1.0) for x in egt] n = sum(a) for _ in range(tur): gk, gb = [0.0] * len(alan), 0.0 for i, xi in enumerate(X): z = b + sum(k[j] * xi[j] for j in range(len(k))) e = (1 / (1 + math.exp(-max(-30.0, min(30.0, z)))) - y[i]) * a[i] gb += e for j in range(len(k)): gk[j] += e * xi[j] b -= adim * gb / n for j in range(len(k)): k[j] -= adim * gk[j] / n def skor(x): v = f(x) z = b + sum(k[j] * v[j] for j in range(len(k))) return 1 / (1 + math.exp(-max(-30.0, min(30.0, z)))) return skor ADAYLAR = {} for d in (3, 4, 5, 6, 7, 8): for w in (1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0): t = agac(agirlikla(EGT, w), d, ALAN) ADAYLAR[f"agac d{d} a{w}"] = matris(lambda x, t=t: olasilik(t, x), SIN) for w in (1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0): s = dogrusal(EGT, ALAN, w) ADAYLAR[f"dogrusal a{w}"] = matris(s, SIN) ESIT = {} for ad, m in ADAYLAR.items(): ESIT.setdefault(round((m[0] + m[3]) / len(SIN), 4), []).append(ad) paylasilan = {d: v for d, v in ESIT.items() if len(v) > 1} print(f"denenen aday {len(ADAYLAR)}, farkli dogruluk degeri {len(ESIT)}, " f"birden cok aday tarafindan paylasilan {len(paylasilan)}") en = max(paylasilan.items(), key=lambda kv: max(ADAYLAR[a][0] for a in kv[1]) - min(ADAYLAR[a][0] for a in kv[1])) print(f"\n{'aday':<14}{'dogruluk':>9}{'do':>5}{'yo':>5}{'yn':>5}{'dn':>5}{'isaretli':>10}") for d in sorted(paylasilan, reverse=True)[:3]: for ad in paylasilan[d]: m = ADAYLAR[ad] print(f"{ad:<14}{d:>9.4f}{m[0]:>5}{m[1]:>5}{m[2]:>5}{m[3]:>5}{m[0] + m[1]:>10}") print() print(f"en genis ayrisma dogruluk {en[0]:.4f}: {' / '.join(en[1])}")
denenen aday 49, farkli dogruluk degeri 26, birden cok aday tarafindan paylasilan 14 aday dogruluk do yo yn dn isaretli agac d5 a1.0 0.8016 23 12 38 179 35 dogrusal a1.0 0.8016 22 11 39 180 33 dogrusal a1.5 0.8016 29 18 32 173 47 agac d3 a1.0 0.7937 17 8 44 183 25 agac d6 a1.0 0.7937 24 15 37 176 39 agac d4 a1.0 0.7817 16 10 45 181 26 agac d8 a1.0 0.7817 32 26 29 165 58 en genis ayrisma dogruluk 0.7817: agac d4 a1.0 / agac d8 a1.0
Kırk dokuz aday yalnız yirmi altı ayrı doğruluk değeri üretiyor ve bunların on dördü birden çok aday tarafından paylaşılıyor. Tablonun ilk bloğu kümenin en yüksek doğruluğunu gösteriyor: 0,8016 değerini üç aday birden veriyor, üstelik iki ayrı model ailesinden. Yakaladıkları şüpheli sayısı 22, 23 ve 29; işaretledikleri abone sayısı 33, 35 ve 47. Doğrulukla bakan biri için üçü aynı modeldir.
Son blok ayrışmanın en genişi. Doğruluğu 0,7817 olan iki aday 61 şüpheliden birinde 16’sını, öbüründe 32’sini yakalıyor — tam iki katı — ve 26’ya karşı 58 abone işaretliyor. Toplam doğru sayısı 197’de eşitleniyor çünkü ikinci modelin kazandığı 16 doğru olumlu, kaybettiği 16 doğru olumsuzla tam takas oluyor. Doğruluk bu takasa kayıtsızdır; matris değildir.
İki Hatanın Bedeli Bir Değil
Takasın kayıtsız kalmadığı yer, iki hata türünün karşılığının sayıldığı yerdir. Kurgu kümede işaretlenen her abone için bir saha ziyareti yazılır, kaçırılan her şüpheli için bir kaçırılmış kaçak. Ziyaretin birimi 1, kaçırılan kaçağınki 6 alınır; bu iki sayı veriden okunmaz, dışarıdan verilir.
ZIYARET, KACAK = 1.0, 6.0 def bedel(m): return ZIYARET * (m[0] + m[1]) + KACAK * m[2] print(f"{'yordam':<24}{'dogruluk':>9}{'ziyaret':>9}{'kacirilan':>11}{'bedel':>8}") for ad, m in (("taban (hicbiri supheli)", [0, 0, NS, len(SIN) - NS]), ("herkes supheli", [NS, len(SIN) - NS, 0, 0]), ("agac d4 a1.0", ADAYLAR["agac d4 a1.0"]), ("agac d8 a1.0", ADAYLAR["agac d8 a1.0"]), ("agac d5 a1.0", ADAYLAR["agac d5 a1.0"]), ("dogrusal a1.5", ADAYLAR["dogrusal a1.5"])): print(f"{ad:<24}{(m[0] + m[3]) / len(SIN):>9.4f}{m[0] + m[1]:>9}" f"{m[2]:>11}{bedel(m):>8.0f}") a, b = ADAYLAR["agac d4 a1.0"], ADAYLAR["agac d8 a1.0"] oran = ((a[0] + a[1]) - (b[0] + b[1])) / (b[2] - a[2]) print(f"\nesit bedel orani {oran:.2f}: kacirilan bir kacagin bedeli bir saha " f"ziyaretinin {oran:.2f} katini gecince siralama doner") en_d = max(ADAYLAR, key=lambda k: (ADAYLAR[k][0] + ADAYLAR[k][3])) en_b = min(ADAYLAR, key=lambda k: bedel(ADAYLAR[k])) print(f"dogrulukta en iyi aday {en_d}, bedeli {bedel(ADAYLAR[en_d]):.0f}") print(f"bedelde en iyi aday {en_b}, dogrulugu " f"{(ADAYLAR[en_b][0] + ADAYLAR[en_b][3]) / len(SIN):.4f}") print(f"bedelde en iyi adayin dogruluk sirasi " f"{sorted(ADAYLAR, key=lambda k: -(ADAYLAR[k][0] + ADAYLAR[k][3])).index(en_b) + 1}" f" / {len(ADAYLAR)}")
yordam dogruluk ziyaret kacirilan bedel taban (hicbiri supheli) 0.7579 0 61 366 herkes supheli 0.2421 252 0 252 agac d4 a1.0 0.7817 26 45 296 agac d8 a1.0 0.7817 58 29 232 agac d5 a1.0 0.8016 35 38 263 dogrusal a1.5 0.8016 47 32 239 esit bedel orani 2.00: kacirilan bir kacagin bedeli bir saha ziyaretinin 2.00 katini gecince siralama doner dogrulukta en iyi aday agac d5 a1.0, bedeli 263 bedelde en iyi aday dogrusal a3.5, dogrulugu 0.7460 bedelde en iyi adayin dogruluk sirasi 20 / 49
Tablonun ikinci satırı doğruluğun tek yönlü bir ölçü olduğunu tek başına gösteriyor. Herkese şüpheli demek doğrulukta 0,2421 verir — kullanılamaz görünen bir sayı — ama bedelde 252 tutar ve taban çizgisinin 366’sından ucuzdur. İki yordam da hiçbir şey öğrenmemiştir; biri doğrulukta, öteki bedelde iyi görünür.
Aynı doğruluğu veren iki adayın bedeli 296 ile 232. Aradaki 64 birim, doğruluğun sakladığı takasın karşılığıdır. Eşit bedel oranı 2,00 çıkıyor: kaçırılan bir kaçağın bedeli bir saha ziyaretinin iki katının altındaysa az işaretleyen model, üstündeyse çok işaretleyen model ucuzdur. Bu oran veriden okunamaz, ölçüm ağının işletmecisinden gelir — aynı iki sayı, oranın 2’nin hangi tarafında olduğuna göre iki ayrı karar.
Son iki satır kırk dokuz adayın tamamına bakıyor. Doğrulukta en iyi aday bedelde 263 veriyor; bedelde en iyi aday doğruluk sıralamasında yirminci sırada. Bir ölçütte tepede olmak öteki ölçütte tepede olmayı getirmiyor ve fark rastlantı düzeyinde değil. Doğruluk, iki hatayı eşit sayan bir bedel hesabıdır; eşit saymayan her hesap başka bir aday seçer.
Özet
- Karışıklık matrisi iki sınıflı kararı dört sayıya ayırır — doğru olumlu, yanlış olumlu, yanlış olumsuz, doğru olumsuz — ve doğruluk bu dördün ikisini toplayıp toplam gözlem sayısına böler.
- Kırk dokuz aday yalnız yirmi altı ayrı doğruluk değeri üretir; on dört değer birden çok aday tarafından paylaşılır, yani aynı sayı çoğu zaman birden fazla hata dağılımına karşılık gelir.
- Doğruluğu 0,7817 olan iki aday 61 şüpheliden 16’sını ve 32’sini yakalar, 26 ve 58 abone işaretler; kazanılan doğru olumlu sayısı kaybedilen doğru olumsuz sayısıyla tam takas olduğu için doğruluk aynı kalır.
- Saha ziyareti 1, kaçırılan kaçak 6 birim sayıldığında bu iki adayın bedeli 296 ile 232 olur; sıralamanın döndüğü eşit bedel oranı 2,00’dir ve bu sayı veriden değil işletmeden gelir.
- Herkese şüpheli demek doğrulukta 0,2421 ile taban çizgisinin çok altında kalırken bedelde 252 ile taban çizgisinin 366’sını geçer; doğrulukta en iyi aday ile bedelde en iyi aday aynı değildir.
Sonraki Adım
Bu ders dört hücreyi saydı ama hücrelerden türetilen ölçütleri adlandırmadı. Öznitelik mühendisliği kursunun dengesiz sınıflar dersi, doğru işaretlenen azınlık payına kesinlik, yakalanan azınlık payına duyarlılık dendiğini yazmış, ikisinin tanımını ve birbirine karşı okunmasını bu kursa bırakmıştı. Sonraki ders o sözü öder: dört hücreden dört ölçüt türetir, beş modeli bu ölçütlerde ayrı ayrı sıralar ve kaç ölçütte sıralamanın başının değiştiğini sayar. F1 ölçütünün niçin iki sayının ortalaması değil uyumlu ortalaması olduğu, ortalamanın hangi durumda yanıltıcı bir yüksek değer verdiği ile birlikte sayıyla gösterilir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.