---
title: 'Doğrulama Stratejileri'
source: 'https://academia.sh/tr/kurslar/model-etik-ve-yorum/dogrulama-stratejileri'
course: 'Model Değerlendirme, Yorumlanabilirlik ve Etik'
language: tr
updated: '2026-08-17T18:10:14+00:00'
license: 'CC BY-SA 4.0'
---

# Doğrulama Stratejileri

Aynı sayının bütünde ve on üç alt grupta ayrı ayrı ölçülmesi ve ayrılmış kümenin gerçekten ayrılmış olup olmadığının sınanması: derinlik 6 karar ağacı sınama kümesinde tabanı 0,0198 geçerken alt grupların beşinde tabanın altında kalıyor ve n değeri 25'in üstündeki on iki alt grup arasındaki açıklık 0,3576 çıkıyor. Aynı abonenin 3.199 satırlık okuma tablosunda iki kümeye birden düşmesi 416 aboneyi paylaştırıyor ve derinlik 12'de tabanın üstündeki farkı 0,0108'den 0,1000'e çıkarıyor; grup temelli ayırma bu 0,0892'lik şişmeyi geri alıyor. Şişme yalnız bütündeki sayıyı değil açıklığı da bozuyor: satır bölmesinde 0,1718 görünen alt grup açıklığı grup temelli ayırmada 0,3846.

Yedi kurs boyunca her sayının yanına tabanı yazıldı: bir model tek başına okunmadı, kendisinden
daha aptal bir yordamın aynı ölçüdeki sayısıyla yan yana konuldu, ve son kursta kararı veren
sistemin kendi verisini değiştirdiği de sayıldı. Sorulmayan tek şey **kimin için** ölçüldüğüdür.
Bütün o sayılar abonelerin ortalamasıydı, ve bir ortalama altındaki grupların hiçbirine ait
olmayabilir.

Bu kursun kuralı şudur: **bir sayı, kimin için ölçüldüğü yazılmadan okunamaz; alt grubu yazılmayan
başarım ölçülmemiş sayılır.** Kural her derste üç sayıyla ödenir — bütünde ölçülen sayı, alt
gruplarda ölçülen aynı sayı, aralarındaki **alt grup açıklığı** — ve açıklık görüldüğünde raporda
değişen cümleyle. Bu ders üçlüyü ve alt grupları kurar, ama önce daha öncelikli bir soruyu
yanıtlar: ayrılmış küme gerçekten ayrılmış mıydı.

- **DT1.** Küme yedi kurstan aynen sürer ve **kurgudur**: 3.199 satırlık okuma tablosu, 1.329
  abone, üç dönem, beş bölge, tohum 20260218. Etiket de kurgudur — kaçak ya da arıza şüphesi
  taşıyan abone — ve gerçek bir denetim kaydı değildir.
- **DT2.** Abone düzeyinde 1.260 satır kalır ve **756/252/252** bölünür. Bölme, ölçüt (doğruluk)
  ve taban çizgisi (eğitim kümesinin en sık sınıfı) M27/K01'den devralınır; sınama kümesindeki
  taban **0,7579**'dur. Model **derinlik 6 karar ağacıdır**, standart kitaplıkla yazılır.
- **DT3.** Üç kümenin ayrımı ve zaman sıralı bölme M27/K01'in genelleme konusunda ölçüldü, burada
  tekrarlanmaz; eklenen tek şey **grup temelli ayırmadır**.
- **DT4.** Alt gruplar **dört eksende** tanımlanır ve kurs boyunca sabit kalır: **bölge** (beş
  değer), **tarife basamağı** (ortalama tüketimin düştüğü basamak: 10, 25, 40 m³), **hane
  büyüklüğü** (1–2, 3–4, 5 ve üstü), **okuma sayısı** (az: bir ya da iki dönem; tam: üç dönem).
  Toplam **13 alt grup**.
- **DT5.** Alt grup tanımı bir karardır, bir bulgu değil. **Kaç alt gruba bakıldığı her derste
  yazılır**, çünkü çok bakmak gürültüden bulgu üretir — bu M26/K05'te ölçüldü, tekrarlanmaz.
- **DT6.** Her alt grup sayısının yanına **kaç aboneden okunduğu** yazılır; **n değeri 25'in
  altındaki grup açıklık hesabına girmez**, çünkü 25 abonede tek bir yanlış sayıyı 0,04 oynatır.
- **DT7.** Satır düzeyi tabloda her satır bir **(abone, dönem)** okumasıdır, etiket abonenindir ve
  abone düzeyi özetler satırlara da yazılır. Derinlik **altı adayda** süpürülür.

## Aynı Sayının On Üç Okuması

İlk blok kurguyu üretir, alt grupları tanımlar ve kursun üçlüsünü tek tabloda basar. Ağaç bir
modeldir: her düğümde bir eşik seçer, yaprakta çoğunluk sınıfını söyler.

```python
# MODELDIR. M26'nin KURGU olcum agi ayni tohumla uretilir, okumalar abone duzeyinde
# ozetlenir ve uzerine KURGU bir kacak/ariza suphesi etiketi eklenir.
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, OKUMA, 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 = 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()
    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)
    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": k["bolge"][0]}
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)

ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]


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]


def uce_bol(K):
    a, b = int(len(K) * 0.6), int(len(K) * 0.8)
    return K[:a], K[a:b], K[b:]


def safsizlik(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 = safsizlik(s) - (len(sol) * safsizlik(sol) + len(sag) * safsizlik(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),
            "sag": agac(en[4], derinlik - 1, alanlar)}


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 gruplar(x):                    # dort eksen, on uc alt grup; kurs boyunca sabit
    return [("bolge", x["bolge"]),
            ("tarife", "10" if x["ort_tuketim"] <= 10 else
             ("25" if x["ort_tuketim"] <= 25 else "40")),
            ("hane", "1-2" if x["hane"] <= 2 else ("3-4" if x["hane"] <= 4 else "5+")),
            ("okuma", "az" if x["donem"] <= 2 else "tam")]


ADLAR = sorted({g for x in VERI for g in gruplar(x)})
EGT, DOG, SIN = uce_bol(karistir(VERI, TOHUM + 90000))
M = agac(EGT, 6, ALAN)


def satir(ad, s):
    tb, dg = taban(EGT, s), dogruluk(M, s)
    print(f"{ad:<14} {len(s):>4} {tb:>7.4f} {dg:>7.4f} {dg - tb:>+8.4f}"
          f"{'   n<25, acikliga girmez' if len(s) < 25 else ''}")
    return len(s), tb, dg


print(f"abone {len(VERI)} -- 756/252/252 -- alt grup {len(ADLAR)} (dort eksen)\n"
      f"{'alt grup':<14} {'n':>4} {'taban':>7} {'agac':>7} {'fark':>8}")
satir("BUTUN", SIN)
olcum = {g: satir(" ".join(g), [x for x in SIN if g in gruplar(x)]) for g in ADLAR}
ol = [v[2] for v in olcum.values() if v[0] >= 25]
alti = [" ".join(g) for g, v in olcum.items() if v[2] < v[1]]
print(f"\naciklik ({len(ol)} alt grup): en iyi {max(ol):.4f}, en kotu {min(ol):.4f}, "
      f"aciklik {max(ol) - min(ol):.4f}\ntabanin altinda kalan: {len(alti)}/"
      f"{len(ADLAR)} -- " + ", ".join(alti))
```

```
abone 1260 -- 756/252/252 -- alt grup 13 (dort eksen)
alt grup          n   taban    agac     fark
BUTUN           252  0.7579  0.7778  +0.0198
bolge bati       32  1.0000  0.9688  -0.0312
bolge dogu       36  0.4722  0.6111  +0.1389
bolge guney      58  0.8276  0.8793  +0.0517
bolge kuzey      68  0.8235  0.7794  -0.0441
bolge merkez     58  0.6552  0.6724  +0.0172
hane 1-2         73  0.7534  0.7945  +0.0411
hane 3-4        143  0.7692  0.7762  +0.0070
hane 5+          36  0.7222  0.7500  +0.0278
okuma az         85  0.7882  0.7412  -0.0471
okuma tam       167  0.7425  0.7964  +0.0539
tarife 10        12  0.6667  0.5833  -0.0833   n<25, acikliga girmez
tarife 25       193  0.8394  0.8290  -0.0104
tarife 40        47  0.4468  0.6170  +0.1702

aciklik (12 alt grup): en iyi 0.9688, en kotu 0.6111, aciklik 0.3576
tabanin altinda kalan: 5/13 -- bolge bati, bolge kuzey, okuma az, tarife 10, tarife 25
```

Birinci satır yedi kursun okuduğu satırdır: model tabanı **0,0198** geçiyor. Altındaki on üç satır
aynı modelin aynı ölçüdeki başka sayılarıdır ve en iyisiyle en kötüsü arasındaki **açıklık
0,3576** — bütünde okunan farkın on sekiz katı. Başarım diye rapor edilen 0,7778, doğu
bölgesindeki abone için 0,6111, batıdaki için 0,9688 demektir.

Daha sert olan sayı son satırdadır: model bütünde tabanı geçiyor ama **on üç alt grubun beşinde
tabanın altında** kalıyor. Az okuması olan 85 abonede taban 0,7882, model 0,7412 — model, hiçbir
şey öğrenmeyen yordamdan 4,7 puan kötü. Bütünde ölçülen fark bu grupların hepsini içeriyor ve
hiçbirini göstermiyor.

Taban sütunu niçin böyle olduğunu söylüyor. Batının 32 sınav abonesinin hiçbiri şüpheli değil;
orada "hiçbiri şüpheli değil" demek 1,0000 verir ve hiçbir model bunu geçemez. Doğuda ve tarife 40
basamağında şüpheli oranı yarıyı aştığı için taban 0,50'nin altına düşer, ve model tabanı en çok
orada geçer. Alt grup açıklığı grubun kendi zorluğunu da taşır; bu yüzden her sayının yanında
tabanı durur. Tarife 10 basamağı 12 abone taşıdığı için açıklığa girmiyor.

## Aynı Abone İki Kümede

Bu tablo kümelerin gerçekten ayrılmış olduğunu varsayıyor. Kurgunun ham hâli abone düzeyinde değil
**okuma düzeyindedir**: 1.260 abone için 3.199 satır, ve üç dönem okuma üretmiş bir abonenin üç
satırı vardır, üçünün de etiketi aynıdır. Satırlar karıştırılıp bölündüğü anda aynı abonenin bir
satırı eğitim, öbürü sınama kümesine düşer.

```python
SATIR = []
for x in VERI:
    for i, o in enumerate(OKUMA[x["no"]]):
        SATIR.append(dict(x, okuma=o, sira=i))
SALAN = ["okuma", "sira"] + ALAN

SE, SD, SS = uce_bol(karistir(SATIR, TOHUM + 93000))     # satir bolmesi
G = karistir([x["no"] for x in VERI], TOHUM + 93000)     # grup temelli ayirma
a, b = int(len(G) * 0.6), int(len(G) * 0.8)
KM = {n: (0 if i < a else (1 if i < b else 2)) for i, n in enumerate(G)}
GE = [y for y in SATIR if KM[y["no"]] == 0]
GS = [y for y in SATIR if KM[y["no"]] == 2]

print(f"satir {len(SATIR)} -- satir bolmesi: egitim {len(SE)} sinama {len(SS)}, iki "
      f"kumede birden gorunen abone {len({y['no'] for y in SS} & {y['no'] for y in SE})}"
      f"\ngrup temelli ayirma: egitim {len(GE)} sinama {len(GS)}, ortak abone "
      f"{len({y['no'] for y in GS} & {y['no'] for y in GE})}\ntaban: satir bolmesi "
      f"{taban(SE, SS):.4f}, grup temelli ayirma {taban(GE, GS):.4f}\n\n"
      f"{'derinlik':>8} | {'satir':>7} {'fark':>8} | {'grup':>7} {'fark':>8} "
      f"| {'sisme':>7}")
for d in (2, 4, 6, 8, 10, 12):
    ms, mg = agac(SE, d, SALAN), agac(GE, d, SALAN)
    fs, fg = dogruluk(ms, SS) - taban(SE, SS), dogruluk(mg, GS) - taban(GE, GS)
    print(f"{d:>8} | {dogruluk(ms, SS):>7.4f} {fs:>+8.4f} | {dogruluk(mg, GS):>7.4f} "
          f"{fg:>+8.4f} | {fs - fg:>+7.4f}")
```

```
satir 3199 -- satir bolmesi: egitim 1919 sinama 640, iki kumede birden gorunen abone 416
grup temelli ayirma: egitim 1921 sinama 649, ortak abone 0
taban: satir bolmesi 0.7594, grup temelli ayirma 0.7319

derinlik |   satir     fark |    grup     fark |   sisme
       2 |  0.7812  +0.0219 |  0.7411  +0.0092 | +0.0126
       4 |  0.7781  +0.0187 |  0.7689  +0.0370 | -0.0182
       6 |  0.8078  +0.0484 |  0.7535  +0.0216 | +0.0269
       8 |  0.8266  +0.0672 |  0.7458  +0.0139 | +0.0533
      10 |  0.8375  +0.0781 |  0.7396  +0.0077 | +0.0704
      12 |  0.8594  +0.1000 |  0.7427  +0.0108 | +0.0892
```

Satır bölmesinde 640 sınama satırının sahibi abonelerin **416'sı** eğitim kümesinde de duruyor;
grup temelli ayırmada bu sayı sıfır. İki bölmenin eğitim kümeleri neredeyse aynı büyüklükte
(1.919'a karşı 1.921 satır), yani fark veri miktarından gelmiyor.

Şişme kapasiteyle büyüyor. Derinlik 2'de ağacın ezberleyecek yeri yok; derinlik 4'te şişme geçici
olarak eksi işaretli, çünkü sığ ağaçta bölme gürültüsü sızıntıdan büyük. Derinlik 12'de tablo
açılıyor: satır bölmesi tabanın **0,1000** üstünü gösteriyor, grup temelli ayırma **0,0108**.
Aradaki **0,0892** modelin öğrendiği bir şey değil — ağaç bir aboneyi öznitelik değerlerinden
tanıyıp öbür satırından gördüğü etiketi hatırlıyor.

Zaman sıralı bölme M27/K01'de ölçüldü ve orada kümeler **ne zaman** ölçüldüklerine göre
ayrılmıştı. Grup temelli ayırma başka bir eksende çalışır: kümeler **kimin** verisi olduğuna göre
ayrılır. Bir kayıt birden çok satır üretiyorsa ayırmanın birimi satır değil o kayıttır.

## Şişme Açıklığı Küçültüyor

Sızıntının bütündeki sayıyı şişirdiği bilinen bir sonuçtur. Bu kursun sorusu başkadır: açıklığa
ne oluyor. Aşağıdaki blok iki bölmenin derinlik 12 modellerini alt gruplara indirir.

```python
sa, ga, dus = [], [], []
for g in ADLAR:
    s1 = [y for y in SS if g in gruplar(y)]
    s2 = [y for y in GS if g in gruplar(y)]
    if min(len(s1), len(s2)) >= 60:     # 60 satir ~ 25 abone; DT6'nin satir karsiligi
        sa.append(dogruluk(ms, s1))
        ga.append(dogruluk(mg, s2))
        dus.append((sa[-1] - ga[-1], " ".join(g), sa[-1], ga[-1]))
for f, ad, d1, d2 in sorted(dus, reverse=True)[:2] + sorted(dus)[:1]:
    print(f"{ad:<14} satir {d1:.4f} | grup {d2:.4f} | dusus {f:+.4f}")
print(f"\naciklik -- satir bolmesi {max(sa) - min(sa):.4f} ({min(sa):.4f} .. "
      f"{max(sa):.4f}), grup temelli ayirma {max(ga) - min(ga):.4f} "
      f"({min(ga):.4f} .. {max(ga):.4f}), {len(sa)} alt grup")
```

```
tarife 40      satir 0.7623 | grup 0.5413 | dusus +0.2210
bolge merkez   satir 0.8364 | grup 0.6279 | dusus +0.2085
bolge bati     satir 0.9341 | grup 0.9259 | dusus +0.0081

aciklik -- satir bolmesi 0.1718 (0.7623 .. 0.9341), grup temelli ayirma 0.3846 (0.5413 .. 0.9259), 12 alt grup
```

Sızıntı alt grupları eşit şişirmiyor. En iyi alt grup iki bölmede de aynı yerde ve neredeyse aynı
sayıda: batı, 0,9341 ve 0,9259. İnen şey **kötü uçtur** — tarife 40 basamağı 0,7623'ten 0,5413'e,
merkez bölgesi 0,8364'ten 0,6279'a. Satır bölmesinde alt grup açıklığı **0,1718** görünüyor, grup
temelli ayırmada **0,3846**: sızıntı gruplar arası farkı yarıdan fazla küçültüyor.

Kötü tasarlanmış bir ayırma böylece iki hata birden üretir: bütündeki sayıyı yükseltir ve alt
gruplar arasındaki farkı bastırır. İkincisi daha sessizdir, çünkü tabloya bakan kişi "gruplar
birbirine yakın" diye okur ve alt grup ölçümünü gereksiz bulur.

## Özet

- Kursun üçlüsü kuruldu: bütünde ölçülen sayı, **13 alt grupta** ölçülen aynı sayı, ve aralarındaki
  **alt grup açıklığı**. Eksenler bölge, tarife basamağı, hane büyüklüğü ve okuma sayısıdır; tanım
  bir karardır ve kaç alt gruba bakıldığı her derste yazılır.
- Derinlik 6 karar ağacı sınama kümesinde tabanı 0,0198 geçiyor ama alt gruplarda 0,6111 ile
  0,9688 arasında değişiyor: açıklık **0,3576**, bütündeki farkın on sekiz katı. On üç alt grubun
  **beşinde model tabanın altında** kalıyor.
- Alt grup sayısı, kaç aboneden okunduğu yazılmadan okunamaz; tarife 10 basamağı 12 abone taşıdığı
  için açıklığa girmez.
- Okuma düzeyindeki 3.199 satır karıştırılınca 416 abone iki kümeye birden düşüyor ve derinlik
  12'de tabanın üstündeki fark 0,0108 yerine 0,1000 görünüyor; grup temelli ayırma bu
  **0,0892**'lik şişmeyi geri alır ve şişme kapasiteyle büyür.
- Sızıntı alt grup açıklığını da bozuyor: satır bölmesinde 0,1718 görünen açıklık grup temelli
  ayırmada **0,3846**. Kötü ayırma sayıyı yükseltmekle kalmaz, gruplar arası farkı da bastırır.

## Sonraki Adım

Ölçüt boyunca doğruluk olarak alındı ve hiç sorgulanmadı. Oysa doğruluk iki hata türünü aynı
ağırlıkta sayar: şüphesiz bir aboneyi denetime göndermenin bedeliyle şüpheli bir aboneyi
kaçırmanın bedeli aynı değildir, ve ikisinin oranı değiştiğinde aynı modelin **eşiği** değişir.
Ölçüt tanımları, eşik ve eğriler M27/K03'te kuruldu ve tekrarlanmayacak. Sonraki ders yalnız şunu
ölçer: aynı model iki ayrı bedel yapısında iki ayrı işletme noktası veriyor — ve bedelin alt
gruplarda aynı olmadığı durumda tek bir eşiğin hangi gruba ne yaptığı sayılır.
