Ders 12 / 12
Çapraz Doğrulama ile Uyum
Hazırlama zincirinin kat dışında ve kat içinde öğrenilmesinin verdiği iki çapraz doğrulama sayısının ayrılmış kümedeki gerçek sayıyla karşılaştırılması: sınama kümesindeki gerçek sayı 0,7817 iken kat içinde hazırlama 0,7966, kat dışında hazırlama 0,8105 veriyor ve kat içinde hazırlamanın sapması 0,0149, kat dışındakinin 0,0288'dir. Zincirin üçüncü adımı kat dışına çıktığı anda sayı 0,7966'dan 0,8115'e sıçrıyor. Tek bölmenin verdiği 0,8254 dört katın en yükseğine eşittir ve gerçek sayıdan 0,0437 uzaktır. Kurs kapanışında on iki dersin karar öncesi ve karar sonrası sayıları tek tabloda toplanır.
İçindekiler
Önceki ders hazırlama zincirini bir nesneye bağladı ve zincirin tamamının yalnız eğitim kümesinden öğrenildiğini güvence altına aldı. Ölçüm yine tek bir bölmeden okundu: 756 satır eğitim, 252 satır sınama. O 252 satır bir kez kullanıldı ve tek bir sayı verdi. Başka bir bölme başka bir sayı verirdi ve hangisinin doğru olduğunu söylemenin yolu yoktu.
Çapraz doğrulama (cross-validation) bu soruna yanıt verir: elde kalan veri katlara bölünür, her kat sırayla ölçüm kümesi olur, kalanlar eğitim kümesi olur ve sonunda birkaç sayı ile bunların saçılması elde edilir. Hazırlama zinciri işin içine girince yeni bir soru doğar ve kursun ikinci kuralı burada son biçimini alır: zincir kat dışında bir kez mi öğrenilir, yoksa her katın içinde yeniden mi. İki yordam iki ayrı sayı verir; bu ders hangisinin ayrılmış kümedeki gerçek sayıya yakın çıktığını ölçer.
- OS36. Çapraz doğrulama havuzu K01’in eğitim ve doğrulama kümeleridir: 1.008 satır. Sınama kümesinin 252 satırı hiçbir kata, hiçbir hazırlama adımına ve hiçbir seçime girmez.
- OS37. Kat sayısı dörttür; her katta 252 satır ölçüm kümesi olur, yani sınama kümesiyle aynı büyüklükte. Kat sayısı sonuca bakılarak seçilmemiştir.
- OS38. Zincir önceki dersin zinciridir, ölçekleme adımı çıkarılmıştır: doldurma, hedef temelli kodlama, öznitelik seçimi. Ölçeklemenin karar ağacındaki katkısı orada tam sıfır ölçüldü.
- OS39. Kat dışında öğrenilen adım sayısı 0’dan 3’e kadar değiştirilir. Sıfır, zincirin tamamının kat içinde öğrenilmesidir.
- OS40. Gerçek sayı, zincirin 1.008 satırdan öğrenildiği ve sınama kümesinde ölçüldüğü sayıdır: bu kursun tek bir kez okunan sayısıdır.
- OS41. Saçılma, dört kat sayısının kendi ortalamasından ortalama uzaklığıdır ve M26’nın değişkenlik ölçüsüdür.
- OS42. Ayar bütçesi hesabı bu dersin konusu değildir ve M27/K03’e bırakılır; burada hiçbir model ayarı seçilmez, model kurs boyunca sabit kalan derinlik 6 karar ağacıdır.
Kat Dışında ve Kat İçinde
# 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)
Boru hattı önceki dersin nesnesidir. ogren yöntemi bu kez fazladan iki değer alır: kat dışındaki
kaynak ve o kaynaktan öğrenecek adım sayısı. Sıfır verildiğinde zincirin tamamı kendisine verilen
kat içi kümeden öğrenir.
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)) r = uretec(TOHUM + 21000 + x["no"]) x["tarife_kodu"] = (24 * [b[0] for b in BOLGE].index(x["bolge_ad"]) + 4 * (x["hane"] - 1) + int(r() * 4)) x["memnuniyet"] = None if r() < 0.08 else x["memnuniyet"] HAVUZ = TABAN_ALAN + ["a_muhur", "tarife_hedef"] class Doldurma: ad = "doldurma" def ogren(self, s): v = sorted(x["memnuniyet"] for x in s if x["memnuniyet"] is not None) self.nesne = {"ortanca": v[len(v) // 2]} def uygula(self, s): for x in s: if x["memnuniyet"] is None: x["memnuniyet"] = self.nesne["ortanca"] class HedefKodlama: ad = "hedef kodlama" def ogren(self, s): g, self.genel = {}, sum(x["supheli"] for x in s) / len(s) for x in s: g.setdefault(x["tarife_kodu"], []).append(x["supheli"]) self.nesne = {k: sum(v) / len(v) for k, v in g.items()} def uygula(self, s): for x in s: x["tarife_hedef"] = round(self.nesne.get(x["tarife_kodu"], self.genel), 4) class Secim: ad = "secim" def __init__(self, havuz): self.havuz = havuz def ogren(self, s): g0, self.nesne = gini(s), [] for a in self.havuz: d, en = sorted({x[a] for x in s}), 0.0 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)) >= 20: en = max(en, g0 - (len(sol) * gini(sol) + len(sag) * gini(sag)) / len(s)) if en >= 0.004: self.nesne.append(a) def uygula(self, s): pass class BoruHatti: def __init__(self, adimlar, derinlik=6): self.adimlar, self.derinlik = adimlar, derinlik def ogren(self, egt, dis_kaynak=None, dis_sayisi=0): egt = [dict(x) for x in egt] dis = [dict(x) for x in (dis_kaynak or [])] for i, a in enumerate(self.adimlar): if i < dis_sayisi: a.ogren(dis) a.uygula(dis) else: a.ogren(egt) a.uygula(egt) self.model = agac(egt, self.derinlik, self.adimlar[-1].nesne) self.egitimde = dogruluk(self.model, egt) return self def olc(self, s): s = [dict(x) for x in s] for a in self.adimlar: a.uygula(s) return dogruluk(self.model, s) def zincir(havuz=None): return [Doldurma(), HedefKodlama(), Secim(havuz or HAVUZ)] KALAN, KAT = K[:1008], 4 def kat_bol(veri, i, k=KAT): n = len(veri) // k return ([x for j, x in enumerate(veri) if not i * n <= j < (i + 1) * n], veri[i * n:(i + 1) * n]) def capraz(dis_sayisi): v = [] for i in range(KAT): ic, disari = kat_bol(KALAN, i) v.append(BoruHatti(zincir()).ogren(ic, KALAN, dis_sayisi).olc(disari)) return v def ortalama(v): return sum(v) / len(v) def sacilma(v): o = ortalama(v) return (sum((q - o) ** 2 for q in v) / len(v)) ** 0.5 G = BoruHatti(zincir()).ogren(KALAN).olc(SIN) TEK = BoruHatti(zincir()).ogren(K[:756]).olc(K[756:1008]) print(f"{'kat disinda':<12} " + " ".join(f"{'kat ' + str(i + 1):>7}" for i in range(KAT)) + f" {'ortalama':>9} {'sacilma':>8} {'fark':>8}") for d in range(4): v = capraz(d) print(f"{str(d) + ' adim':<12} " + " ".join(f"{q:>7.4f}" for q in v) + f" {ortalama(v):>9.4f} {sacilma(v):>8.4f} {ortalama(v) - G:>+8.4f}") print(f"\ntek bolme 756/252 {TEK:.4f}, fark {TEK - G:+.4f}") print(f"sinama kumesindeki gercek sayi {G:.4f}, taban cizgisi {taban(KALAN, SIN):.4f}")
kat disinda kat 1 kat 2 kat 3 kat 4 ortalama sacilma fark 0 adim 0.7976 0.7738 0.7897 0.8254 0.7966 0.0187 +0.0149 1 adim 0.7976 0.7738 0.7897 0.8254 0.7966 0.0187 +0.0149 2 adim 0.8016 0.8135 0.8333 0.7976 0.8115 0.0139 +0.0298 3 adim 0.8016 0.8056 0.8452 0.7897 0.8105 0.0209 +0.0288 tek bolme 756/252 0.8254, fark +0.0437 sinama kumesindeki gercek sayi 0.7817, taban cizgisi 0.7579
Son sütun dersin yanıtıdır. Zincirin tamamı kat içinde öğrenildiğinde çapraz doğrulama 0,7966 veriyor ve gerçek sayının 0,0149 üstünde kalıyor. Zincirin tamamı kat dışında öğrenildiğinde 0,8105 veriyor ve sapma 0,0288’e, yani iki katına çıkıyor. Kat içinde hazırlama, gerçek sayıya yakın olan yordamdır.
Sıçramanın nereden geldiği ara satırlarda görünüyor. Doldurma kat dışına çıktığında hiçbir şey değişmiyor; hedef temelli kodlama kat dışına çıktığı anda ortalama 0,7966’dan 0,8115’e atlıyor. Seçim buna ölçüm çözünürlüğünün altında bir düşüş ekliyor. Kat dışında hazırlamanın maliyetinin tamamı tek bir adımdan geliyor ve o adım etiketi kullanan adımdır.
Bu, önceki dersteki tabloyla aynı yapıdadır ve aynı nedenle oluşur. Kat dışında öğrenilen hedef temelli kodlama, her katın ölçüm satırlarının etiketlerini o satırların göreceği sayıya karıştırır. Kat sayısı arttıkça ölçüm satırlarının payı düşer ve şişme küçülür; azaldıkça büyür. Bu yüzden kat dışında hazırlanmış bir çapraz doğrulama sayısı kendi kat sayısından bağımsız okunamaz.
Sapmanın işareti de dikkat ister. Kat içinde hazırlama gerçek sayıyı 0,0149 aşıyor, yani hâlâ iyimser; nedeni sızıntı değil, zincirin her katta bir kez daha veriye bakmasıdır. Çapraz doğrulama gerçek sayıyı ölçmez, gerçek sayının etrafındaki bir aralığı ölçer.
Tek Bölmenin Tek Sayısı
Tek bölme 0,8254 veriyor ve gerçek sayıdan 0,0437 uzakta. Bu sayı, kat içinde hazırlanmış dört kat sayısının en yükseğine eşittir. Tek bölme yanlış bir hesap yapmadı; yalnız bu aralığın bir ucuna denk geldi ve tek bir sayı olduğu için hangi uca denk geldiğini söyleyemedi.
Dört katın saçılması 0,0187’dir. Bir bölmeden okunan sayı bu büyüklükte bir dalgalanma taşır ve 0,0119’luk bir katkıyı bu dalgalanmadan ayırmak tek bölmeyle olanaksızdır. Kursun ilk üç dersinde ölçülen 0,0119’luk katkılar bu yüzden “ölçüldü ve sıfırdan ayrılamadı” diye yazıldı.
Çapraz doğrulamanın kattığı şey daha büyük bir sayı değil, sayının yanında bir aralıktır. Ve o aralık ancak hazırlama zinciri kat içinde öğrenildiğinde gerçek aralıktır.
Özet
- Sınama kümesindeki gerçek sayı 0,7817; kat içinde hazırlama 0,7966 (sapma 0,0149), kat dışında hazırlama 0,8105 (sapma 0,0288) veriyor.
- Sapmanın tamamı tek bir adımdan geliyor: doldurma kat dışına çıktığında sayı değişmiyor, hedef temelli kodlama kat dışına çıktığında ortalama 0,7966’dan 0,8115’e sıçrıyor.
- Kat dışında hazırlanmış bir çapraz doğrulama sayısı kat sayısından bağımsız okunamaz, çünkü şişmenin büyüklüğü ölçüm satırlarının paya oranına bağlıdır.
- Tek bölmenin verdiği 0,8254, dört katın en yükseğine eşittir ve gerçek sayıdan 0,0437 uzaktır; tek sayı hangi uca denk geldiğini söyleyemez.
- Katların saçılması 0,0187’dir; bu büyüklükteki bir dalgalanma varken 0,0119’luk bir katkı tek bölmeyle sıfırdan ayrılamaz.
Kurs Kapanışı
On iki dersin hesabı tek tabloda duruyor ve her sayı kendi dersinden okundu. Karar öncesi ve karar sonrası sütunları hep ayrılmış kümede ölçüldü; taban çizgisi bütün derslerde 0,7579’dur.
| Ders | Karar öncesi | Karar sonrası | Katkı |
|---|---|---|---|
| Hazırlama 01 veri temizleme | 0,7659 ham kayıt | 0,7778 üç düzeltme | +0,0119 |
| Hazırlama 02 öznitelik ölçekleme | 0,7579 ölçeksiz | 0,8016 standart puan | +0,0437 |
| Hazırlama 03 kategorik kodlama | 0,7302 alan kullanılmadı | 0,7778 bir-sıcak kodlama | +0,0476 |
| Hazırlama 04 eksik değer | 0,7619 ortanca ile doldurma | 0,8333 eksiklik göstergesi | +0,0714 |
| Hazırlama 05 dengesiz sınıflar | 0,7778 ham küme | 0,7619 iki kat çoğaltma | −0,0159 |
| Hazırlama 06 aykırı değer | 0,7698 kırpma yok | 0,8016 çit ile kırpıldı | +0,0317 |
| Seçim 01 öznitelik üretme | 0,7778 on bir sütun | 0,7897 oran özniteliği | +0,0119 |
| Seçim 02 zaman ve metin | 0,7897 on iki sütun | 0,8214 nottan beş sayı | +0,0317 |
| Seçim 03 öznitelik seçimi | 0,8135 seçim yok | 0,8254 gömülü yöntem | +0,0119 |
| Seçim 04 boyut azaltma | 0,8254 ham on üç sütun | 0,8175 iki bileşen | −0,0079 |
| Seçim 05 boru hatları | 0,8294 elle zincir | 0,7817 boru hattı | −0,0476 |
| Seçim 06 çapraz doğrulama | 0,8105 kat dışında | 0,7966 kat içinde | −0,0139 |
İkinci ve altıncı hazırlama dersinin satırları eğim temelli doğrusal modelden, kalan on satır kursun sabit karar ağacından okunur; beşinci hazırlama dersinin satırı doğruluk sütunudur ve aynı karar yakalanan şüpheli sayısını 21’den 33’e çıkarır.
Kursun birinci kuralı tablonun kendisidir: bir hazırlama adımı, ayrılmış kümede ölçülen katkısı kadar vardır. Katkı sütununda dört satır sıfır ya da eksidir. Bu dördü ölçülmeseydi kümede kalırdı ve dördü de makul bir gerekçeyle savunulurdu.
Kursun ikinci kuralı son iki satırda okunur: her hazırlama adımı yalnız eğitim kümesinden öğrenilir ve ayrılmış kümeye uygulanır. O iki satırdaki eksi işaretler kayıp değil, geri alınmış şişmedir; boru hattı 0,0476, kat içinde hazırlama 0,0139 sayı düşürdü ve düşen sayının hiçbiri öğrenmeden gelmiyordu. Ölçülen katkının işaretine bakmadan önce nereden geldiğine bakmak gerekir.
Geriye kursun başında açılan bir hesap kalıyor. Birinci ders, sınama kümesine her bakışın bir seçim payı biriktirdiğini yazmış ve payın hesabını kursun sonuna bırakmıştı. Tablonun kendisi o hesabı veriyor: on iki satırın her biri iki sayı taşıyor, yani sınama kümesine en az 24 kez bakıldı ve derslerin içindeki süpürmelerle bu sayı çok daha yüksek. Tablodaki hiçbir sayı bu yüzden bir genelleme kestirimi değildir; hepsi bir karşılaştırmadır. Gerçek sayı ancak bu kurs boyunca hiç dokunulmamış bir kümede okunur ve o küme artık yoktur.
On iki derste öznitelikler kuruldu ve her adımın katkısı ayrılmış kümede ölçüldü. Ama bütün bu ölçümler boyunca model hep aynı iki üç aile arasından seçildi: derinlik 6 bir karar ağacı, yanında bir eğim temelli doğrusal model ve bir uzaklık temelli yordam. Ailenin kendisinin ne kattığı hiç sorulmadı; derinliğin niçin altı olduğu, komşu sayısının niçin on beş olduğu ve bu sayıların hangi kümeden okunması gerektiği hiç ölçülmedi. Sonraki kurs, Denetimli Öğrenme, bu soruları ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.