İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat