Ders 01 / 12
Veri Temizleme
Bir temizleme kararının modele ne kattığının ayrılmış kümede ölçülmesi: ham kayıttaki üç kusur tek tek düzeltilir, model sabit tutulur ve sınama kümesindeki iki sayı yan yana basılır. Birim karışıklığının düzeltilmesi uzaklık temelli yordama on iki abone kazandırırken karar ağacına iki abone kaybettirir; üç kusur birden düzeltildiğinde ağacın sınama doğruluğu 0,7659'dan 0,7778'e, uzaklık temelli yordamınki 0,7540'tan 0,7857'ye çıkar ve taban çizgisi her ikisinde de 0,7579'dur.
İçindekiler
Önceki kurs on bir derste ayrımı kurdu: bir modelin gördüğü veride ölçülen sayı ile görmediği veride ölçülen sayı iki ayrı sayıdır ve her sayının yanına kendi kümesinde hesaplanmış bir taban çizgisi yazılır. O kursun kapanışı bir eksikle bitti. Modele verilen öznitelikler hep hazır kabul edildi: ortalama tüketim bir sayıydı, bölge beş ikili sütundu, oynaklık hesaplanmıştı. Hangi sütunun nasıl bir sayıya çevrildiği ve o çevirinin tabanla arasındaki farkı ne kadar oynattığı hiç sorulmadı.
Bu ders o soruyu sorar ve kursun ölçü birimini kurar. Yöntem her derste aynıdır: model sabit tutulur, yalnız öznitelikler değişir. Tek bir hazırlama kararı açılır ve kapatılır, ayrılmış kümedeki iki sayı yan yana basılır, aradaki fark katkı olarak adlandırılır. Kursun kuralı buradan çıkar: bir hazırlama adımı, ayrılmış kümede ölçülen katkısı kadar vardır. Katkısı ölçülmemiş adım, adım değil alışkanlıktır.
- HA1. Küme M27/K01’den devralınır ve kurgudur: bölgesel ölçüm ağından türetilen 1.260 abone, kaçak ya da arıza şüphesi etiketi, tohum 20260218, bölme 756/252/252.
- HA2. Bu kursta ayrılmış küme sınama kümesidir ve taban çizgisi orada 0,7579’dur — eğitim kümesinin en sık sınıfını her aboneye söylemek. K01’in kuralı gereği her bakış bir seçim payı biriktirir; bu payın hesabı kursun sonuna bırakılır.
- HA3. K01’in kullandığı tablo temizlenmiş tablodur. Bu ders bir adım geriye gider: aynı kurgunun ham kayıt hali, temizleme kararları alınmadan önceki biçimi.
- HA4. Ham kayıtta üç kusur vardır ve üçü de kurgudur. Eski sayaçların bir bölümü tüketimi litre cinsinden bildirir; bölge adı üç ayrı yazımla kaydedilir; okunamayan sayaç ikinci kez okunduğu için aynı abone birden çok satırda görünür.
- HA5. Kusurlar yalnız öznitelik sütunlarını bozar. Etiket denetim sonucudur ve hiçbir kusurdan etkilenmez; bu yüzden taban çizgisi 0,7579 sabit kalır.
- HA6. Bölme abone üzerinden yapılır. Yinelenen satırlar kümeler arasına geçmez, yalnız eğitim kümesindeki ağırlığı değiştirir.
- HA7. İki model ailesi karşılaştırılır: K01’in derinlik 6 karar ağacı ve en yakın on beş komşuya bakan uzaklık temelli bir yordam. İkisi de ders içinde yazılır ve ikisi de birer modeldir; kurs boyunca ayarları değişmez.
- HA8. Ölçü doğruluktur. Sınama kümesi 252 abonedir, bu yüzden bir abone 0,0040 eder ve bundan küçük farklar ölçülmemiş sayılır.
Temizleme yordamının kendisi bu derste kurulmuyor. Eksik değer, tip dönüşümü, yinelenen kayıt ve kategori birleştirme M26’nın Veri Toplama ve Hazırlama kursunda ölçüldü; oradaki ölçü satır sayısıydı — kaç satır düzeldi, kaç satır atıldı. Buradaki soru başkadır: aynı karar ayrılmış kümedeki sayıyı ne kadar oynatıyor ve hangi model ailesi ona duyarlı.
Ham Kayıt ve Üç Kusur
Kurulum kümeyi K01’deki tohumla yeniden üretir, abone üzerinden böler ve eğitim ile sınama kümelerinin ham kayıt halini kurar. Etikete dokunulmaz.
# hazirlama.py — MODELDIR. M27/K01'in kurgu abone tablosu ayni tohumla yeniden # uretilir; uzerine kaydin HAM halindeki uc kusur konur. 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 = [] 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}) OKUMA = {} 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 v is None: 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) VERI.append({"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), "bolge": k["bolge"][0], "supheli": int(z > 1.35)}) 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) EGT0, SIN0 = K[:756], K[1008:] TABAN = sum(x["supheli"] == 0 for x in SIN0) / len(SIN0) YAZIM = {"kuzey": ["kuzey", "Kuzey", "KUZEY"], "guney": ["guney", "Guney"], "dogu": ["dogu", "Dogu"], "bati": ["bati", "BATI"], "merkez": ["merkez", "Merkez "]} def hamla(satirlar, tohum): # litre kaydi + yazim tutarsizligi r, out = uretec(tohum), [] for x in satirlar: y = dict(x) if r() < 0.35: y["ort_tuketim"] = round(y["ort_tuketim"] * 1000, 1) y["oynaklik"] = round(y["oynaklik"] * 1000, 1) v = YAZIM[y["bolge"]] y["bolge"] = v[0] if r() < 0.70 else v[int(r() * (len(v) - 1)) + 1] out.append(y) return out def yinele(satirlar, tohum): # okunamayan sayac ikinci kez okunur r, out = uretec(tohum), [] for x in satirlar: out.append(x) if x["sifir_okuma"] == 1 and r() < 0.85: out += [dict(x), dict(x)] return out HAM_EGT = yinele(hamla(EGT0, TOHUM + 61000), TOHUM + 62000) HAM_SIN = hamla(SIN0, TOHUM + 63000) print(f"egitim {len(EGT0)} abone, ham kayitta {len(HAM_EGT)} satir; " f"sinama {len(SIN0)} abone, {len(HAM_SIN)} satir") print(f"litre cinsinden kaydedilmis satir: egitim " f"{sum(1 for x in HAM_EGT if x['ort_tuketim'] > 1000)}, sinama " f"{sum(1 for x in HAM_SIN if x['ort_tuketim'] > 1000)}") print(f"bes bolge icin {len({x['bolge'] for x in HAM_EGT})} ayri yazim, " f"taban cizgisi (en sik sinif) sinamada {TABAN:.4f}")
egitim 756 abone, ham kayitta 864 satir; sinama 252 abone, 252 satir litre cinsinden kaydedilmis satir: egitim 295, sinama 86 bes bolge icin 11 ayri yazim, taban cizgisi (en sik sinif) sinamada 0.7579
Üç kusurun büyüklüğü ölçülebilir: 756 abone 864 satıra çıkmış, 295 satırda tüketim bin katına kaymış, beş bölge on bir ayrı yazımla kaydedilmiş. Bunlar M26’da satır hesabıyla anlatılan kusurların aynısıdır. Yeni olan, her birinin bir karar olması ve kararın bedelinin modelde okunacak olmasıdır.
Aynı Karar, İki Model Ailesi
Aşağıdaki kod iki modeli yazar ve üç temizleme kararını tek tek uygular. Karar ağacı her düğümde bir öznitelik ve bir eşik seçer, kümeyi ikiye ayırır ve yaprakta çoğunluk sınıfını söyler. Uzaklık temelli yordam bir aboneye en yakın on beş komşuyu bulur ve onların çoğunluğunu söyler; yakınlık, bütün sütunlardaki farkların karelerinin toplamıdır.
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, alan, enaz=2): # MODELDIR: karar agaci, derinlik 6 p = sum(x["supheli"] for x in s) / len(s) 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 = 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, alan, enaz), "sag": agac(en[4], derinlik - 1, alan, enaz)} def agac_tahmin(d, x): while "tahmin" not in d: d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"] return d["tahmin"] def komsu_tahmin(egt, x, alan, k=15): # MODELDIR: uzaklik temelli yordam u = sorted((sum((x[a] - y[a]) ** 2 for a in alan), y["supheli"]) for y in egt)[:k] return int(sum(t[1] for t in u) * 2 > k) def sutunla(egt, sin): # bolge yazimlari ikili sutuna acilir kat = sorted({x["bolge"] for x in egt}) alan = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma"] ac = (lambda s: [dict(x, **{"b_" + k: int(x["bolge"] == k) for k in kat}) for x in s]) return alan + ["b_" + k for k in kat], ac(egt), ac(sin) def olc(egt, sin): alan, e, s = sutunla(egt, sin) m = agac(e, 6, alan) return (sum(agac_tahmin(m, x) == x["supheli"] for x in s) / len(s), sum(komsu_tahmin(e, x, alan) == x["supheli"] for x in s) / len(s)) def birim(s): # litre kaydi metrekupe cevrilir return [dict(x, ort_tuketim=round(x["ort_tuketim"] / 1000, 2), oynaklik=round(x["oynaklik"] / 1000, 2)) if x["ort_tuketim"] > 1000 else dict(x) for x in s] def yazim(s): return [dict(x, bolge=x["bolge"].strip().lower()) for x in s] def yinelenen(s): # ilk okuma tutulur, kopyalar atilir g, out = set(), [] for x in s: if x["no"] not in g: g.add(x["no"]) out.append(x) return out KARAR = [("hicbiri (ham kayit)", lambda e, s: (e, s)), ("birim duzeltildi", lambda e, s: (birim(e), birim(s))), ("yazim birlestirildi", lambda e, s: (yazim(e), yazim(s))), ("yinelenen atildi", lambda e, s: (yinelenen(e), s)), ("ucu birden", lambda e, s: (yinelenen(yazim(birim(e))), yazim(birim(s))))] SONUC = {} print(f"{'uygulanan karar':<22} {'agac':>8} {'uzaklik':>9}") print(f"{'taban cizgisi':<22} {TABAN:>8.4f} {TABAN:>9.4f}") for ad, f in KARAR: SONUC[ad] = olc(*f(HAM_EGT, HAM_SIN)) print(f"{ad:<22} {SONUC[ad][0]:>8.4f} {SONUC[ad][1]:>9.4f}")
uygulanan karar agac uzaklik taban cizgisi 0.7579 0.7579 hicbiri (ham kayit) 0.7659 0.7540 birim duzeltildi 0.7579 0.8016 yazim birlestirildi 0.7738 0.7540 yinelenen atildi 0.7778 0.7659 ucu birden 0.7778 0.7857
İkinci satır dersin çıkış noktasıdır. Ham kayıtla eğitilen uzaklık temelli yordam sınama kümesinde 0,7540 okuyor ve bu, taban çizgisinin altındadır. Hiçbir özniteliğe bakmayan, hiçbir şey öğrenmeyen ve her aboneye aynı yanıtı veren bir yordam ondan iyidir. Aynı ham kayıtla eğitilen ağaç ise tabanı 0,0079 geçiyor. İki model, aynı tablo, iki ayrı işaret.
Üçüncü satır dersin asıl sayısıdır. Birim düzeltmesi uzaklık temelli yordamı 0,7540’tan 0,8016’ya çıkarıyor; ağacı 0,7659’dan 0,7579’a indiriyor. Aynı karar, aynı veri, ters işaret. Sebep modellerin sütunu okuma biçimidir. Ağaç her sütunda yalnız sıraya bakar ve tek bir eşikle böler; birim karışıklığı sıralamayı bozduğunda ağaç önce bin sınırında bölüp sonra sütunu her dalda yeniden kullanabilir, ödediği bedel bir düğüm derinliğidir. Uzaklık temelli yordam ise bütün sütunların farklarını toplar; bin kat büyümüş bir sütun toplamı tek başına belirler ve hane, memnuniyet, dönem, bölge sütunlarının hepsi hesaba katılmaz duruma gelir.
Katkı Kaç Abone Eder
Farkları abone sayısına çevirmek, hangi satırın okunmaya değer olduğunu ayırır.
HAMD = SONUC["hicbiri (ham kayit)"] print(f"{'karar':<22} {'agac katki':>11} {'abone':>6} " f"{'uzaklik katki':>14} {'abone':>6}") for ad, _ in KARAR[1:]: ka, ku = SONUC[ad][0] - HAMD[0], SONUC[ad][1] - HAMD[1] print(f"{ad:<22} {ka:>+11.4f} {round(ka * 252):>6} " f"{ku:>+14.4f} {round(ku * 252):>6}") print(f"\ntabanin ustundeki fark, ham kayitta: agac {HAMD[0] - TABAN:+.4f}, " f"uzaklik {HAMD[1] - TABAN:+.4f}") u = SONUC["ucu birden"] print(f"tabanin ustundeki fark, ucu birden: agac {u[0] - TABAN:+.4f}, " f"uzaklik {u[1] - TABAN:+.4f}")
karar agac katki abone uzaklik katki abone birim duzeltildi -0.0079 -2 +0.0476 12 yazim birlestirildi +0.0079 2 +0.0000 0 yinelenen atildi +0.0119 3 +0.0119 3 ucu birden +0.0119 3 +0.0317 8 tabanin ustundeki fark, ham kayitta: agac +0.0079, uzaklik -0.0040 tabanin ustundeki fark, ucu birden: agac +0.0198, uzaklik +0.0278
Tabloda okunmaya değer tek bir büyük sayı var: birim düzeltmesinin uzaklık temelli yordama kattığı on iki abone. Geri kalan hücreler iki ya da üç abonedir ve 252 abonelik bir kümede iki abone, kümenin kendi rastgeleliğinden ayırt edilemez. Ağacın birim düzeltmesinden gördüğü −0,0079’luk zarar da bu boydadır; işareti eksidir ama okunacak doğru cümle “ağaç için bu adımın katkısı ölçülmemiştir” olur, “ağaca zarar verir” değil. Bu ayrım kurs boyunca sürer: bir katkının işareti, büyüklüğü ölçüm çözünürlüğünü aştığında anlam kazanır.
Son iki satır kararların nereden geldiğini gösteriyor. Üç kusur birden düzeltildiğinde ağaç tabanı 0,0198, uzaklık temelli yordam 0,0278 geçiyor. Bu iki fark öğrenmeden gelir: kusurlar etiketten bağımsız üretildi, hiçbiri şüpheli abonelerde daha sık değil, dolayısıyla hiçbir temizleme kararı modele etiket hakkında saklı bir bilgi taşımıyor. Kursun ilerleyen derslerinde bunun tersi de ölçülecek — katkısı öğrenmeden değil sızıntıdan gelen adımlar vardır ve ikisi ancak kaynağı sorulduğunda ayrılır.
Bir doğrulama daha var. Üç kusur birden düzeltildiğinde ağacın sınama doğruluğu 0,7778 çıkıyor ve bu, M27/K01’in aynı model, aynı bölme ve aynı tohumla okuduğu sayının birebir aynısıdır. Bu tesadüf değil: temizlenmiş tablo, K01’in en baştan kullandığı tablodur. Önceki kurs boyunca görünmeyen şey, o tablonun kendisinin bir dizi karardan çıkmış olmasıydı.
Özet
- Ham kayıtla eğitilen uzaklık temelli yordam sınama kümesinde 0,7540 okuyor ve taban çizgisinin 0,0040 altında kalıyor; aynı tabloyla eğitilen karar ağacı 0,7659 ile tabanı 0,0079 geçiyor.
- Birim karışıklığının düzeltilmesi uzaklık temelli yordama +0,0476, yani on iki abone katıyor; aynı karar karar ağacında −0,0079, yani iki abone eksiye düşürüyor.
- İşaretin ters dönme sebebi modellerin sütunu okuma biçimidir: ağaç her sütunda yalnız sıraya bakar ve karışık birimi bir düğüm derinliğiyle telafi eder, uzaklık temelli yordam bütün sütunları toplar ve bin kat büyümüş bir sütun toplamı tek başına belirler.
- Yazım birleştirme ve yinelenen kayıt atma her iki modelde de iki ya da üç abone oynatıyor; 252 abonelik sınama kümesinde bir abone 0,0040 ettiği için bu farklar ölçülmemiş sayılır.
- Üç kusur birden düzeltildiğinde ağaç 0,7778 okuyor; bu sayı M27/K01’in aynı model ve aynı bölmeyle okuduğu sayının aynısıdır, çünkü K01 zaten temizlenmiş tabloyu kullanıyordu.
Sonraki Adım
Bu derste birim karışıklığının uzaklık temelli yordamı yıktığı görüldü, ama düzeltmeden sonra da o yordam ağaçtan geride kaldı ve tabanı yalnız 0,0278 geçebildi. Sebep tabloda hâlâ duruyor: sütunlar aynı birime çevrildi ama aynı büyüklüğe çevrilmedi. Ortalama tüketim sıfır ile kırk üç arasında değişirken hane büyüklüğü bir ile altı, bölge sütunları sıfır ile bir arasında değişiyor; farkların karelerini toplayan bir yordam için bu, sütunlara sessizce ağırlık vermektir. Sonraki ders iki ölçekleme kararını — standartlaştırma ve normalleştirme — üç model ailesinde ayrı ayrı ölçer, ölçeğin yalnız eğitim kümesinden öğrenilip ayrılmış kümeye uygulandığı disiplini kurar ve hangi model ailesinde katkının sıfır çıktığını sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.