---
title: 'Bağımsızlık Varsayımlı Olasılıksal Sınıflandırıcı'
source: 'https://academia.sh/tr/kurslar/denetimli-ogrenme/bagimsizlik-varsayimli-siniflandirici'
course: 'Denetimli Öğrenme'
language: tr
updated: '2026-08-17T18:10:21+00:00'
license: 'CC BY-SA 4.0'
---

# Bağımsızlık Varsayımlı Olasılıksal Sınıflandırıcı

Sütunları toplamak yerine sayan bir ailenin ölçülmesi: sekiz sütunun 201.600 bileşimi yerine 80 hücrelik bir sayım tablosu tutulur, yirmi aday denenir ve doğrulama kümesinden seçilen aday sınama kümesinde 0,7817 verir. Sıfır sayım bir sınıfı tümüyle eler; 60 satırlık eğitimde 137 sınama satırı vetolanır ve düzleştirme vetoyu kaldırır ama doğruluğu güvenceye almaz. Aynı bilgiyi taşıyan sütun sekiz kez eklendiğinde uç olasılıklı abone 2'den 169'a, ortalama güven 0,842'den 0,970'e çıkar; sıralamanın üst 61'indeki isabet 29'dan 33'e gider.

Önceki ders on iki sütunu tek bir uzaklık toplamına indirdi. O toplamda bölge göstergesiyle
ortalama tüketim aynı terim listesinde durur ve kararı hangisinin taşıdığı görünmez; kategorik
bir alan için "uzaklık" zaten sonradan takılmış bir kavramdır. Bu ders sütunları toplamayan,
**sayan** bir aile alır: her sütunun her düzeyinin her sınıf altında kaç kez göründüğünü sayar.

Sayarak sınıflandırmanın önünde bir engel vardır. Belirli bir sütun bileşiminin kaç kez şüpheli
çıktığını doğrudan saymak mümkün değildir, çünkü bileşimlerin neredeyse tamamı eğitim kümesinde
hiç görülmemiştir. Aile bu engeli tek bir varsayımla aşar: sınıf verildiğinde sütunların
birbirinden bağımsız olduğunu kabul eder ve ortak sayımı tek tek sütun sayımlarının
**çarpımıyla** değiştirir. Varsayım bu kümede doğru değildir; ders yanlışlığın iki ayrı sonucunu
ayrı ayrı sayar.

- **DO9.** Küme, bölme ve taban çizgisi değişmez: 1.260 abonelik **kurgu** tablo, tohum 20260218,
  bölme 756/252/252, sınama kümesinde taban çizgisi 0,7579 ve 61 şüpheli abone.
- **DO10.** Öznitelik kümesi sabittir; değişen yalnız **gösterimidir**. Bölgenin beş ikili sütunu
  tek bir beş düzeyli sütuna döner, ortalama tüketim M26'dan gelen 10, 25 ve 40 m³ tarife
  basamaklarına, oynaklık ile kişi başına tüketim eşit sayıda satır taşıyan aralıklara ayrılır.
  Aralık sınırları **yalnız eğitim kümesinden** öğrenilir.
- **DO11.** İki ayar değişkeni vardır ve ikisi de veriden öğrenilmez: aralık sayısı ve
  **düzleştirme** katsayısı. Çarpım logaritma toplamı olarak hesaplanır; sekiz küçük olasılığın
  doğrudan çarpımı kayan noktada sıfıra iner.
- **DO12.** **Önsel**, bir sınıfın eğitim kümesindeki oranıdır; **sonsal**, sütunlar görüldükten
  sonraki olasılığıdır. Karar eşiği 0,5'tir; eşik seçimi kursun değerlendirme konusuna bırakılır.
- **DO13.** Metin sınıflandırma kurulmaz ve M27/K06'ya bırakılır; kullanılan bütün alanlar kurgu
  abone tablosunun kategorik alanlarıdır.
- **DO14.** Seçim doğrulama kümesinden okunur. Sıralama ölçümünde en yüksek olasılıklı 61 abone
  alınır; 61, sınama kümesindeki gerçek şüpheli sayısıdır.

## Sayımdan Olasılığa

Kurulum kümeyi üretir, düzey gösterimini kurar ve varsayımın gerekçesini iki sayıyla verir.

```python
# sayan-model.py — MODELDIR. M27/K01 ve K02'nin KURGU abone tablosu ayni tohumla
# uretilir; oznitelik kumesi sabittir, yalniz gosterimi duzeylere cevrilir.
import collections
import math
import statistics

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 = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "bolge_ad": k["bolge"][0],
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    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:]
TABAN_SIN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def basamak(v):                             # tarife basamaklari 10 / 25 / 40 m3
    return 0 if v < 10 else (1 if v < 25 else (2 if v < 40 else 3))


def kesimler(egt, a, n):                    # OGRENME: aralik sinirlari egitimden
    v = sorted(x[a] for x in egt)
    return [v[int(i * len(v) / n)] for i in range(1, n)]


def duzey(v, kesim):
    return sum(1 for k in kesim if v >= k)


def kategorik(s, kesim):                    # UYGULAMA
    return [({"tarife": basamak(x["ort_tuketim"]), "bolge": x["bolge_ad"],
              "hane": x["hane"], "memnuniyet": x["memnuniyet"], "donem": x["donem"],
              "sifir_okuma": x["sifir_okuma"],
              "oynaklik": duzey(x["oynaklik"], kesim["oynaklik"]),
              "kisi_basi": duzey(x["kisi_basi"], kesim["kisi_basi"])}, x["supheli"])
            for x in s]


SUTUN = ["tarife", "bolge", "hane", "memnuniyet", "donem", "sifir_okuma",
         "oynaklik", "kisi_basi"]
KESIM = {a: kesimler(EGT, a, 8) for a in ("oynaklik", "kisi_basi")}
KE, KD, KS = kategorik(EGT, KESIM), kategorik(DOG, KESIM), kategorik(SIN, KESIM)
print(f"egitim {len(KE)}, sinama {len(KS)}, sinamada supheli {sum(y for _, y in KS)}, "
      f"taban cizgisi {TABAN_SIN:.4f}")
DUZEY = {a: {x[a] for x, _ in KE} for a in SUTUN}
bilesim, hucre = 1, 0
for a in SUTUN:
    bilesim, hucre = bilesim * len(DUZEY[a]), hucre + 2 * len(DUZEY[a])
print(f"sutun {len(SUTUN)}, bilesim sayisi {bilesim}, egitim satiri {len(KE)}, "
      f"sutunlara ayrilmis sayim tablosunda hucre {hucre}")
```

```
egitim 756, sinama 252, sinamada supheli 61, taban cizgisi 0.7579
sutun 8, bilesim sayisi 201600, egitim satiri 756, sutunlara ayrilmis sayim tablosunda hucre 80
```

İkinci satır varsayımın gerekçesidir. Sekiz sütunun düzeyleri 201.600 ayrı bileşim üretiyor ve
elde 756 eğitim satırı var; ortak sayımı doğrudan tutmak bir seçenek değildir. Sütunları ayrı
ayrı saymak aynı tabloyu **80 hücreye** indirir. Bedeli çarpmanın kendisindedir: bir abonenin
şüpheli olma olasılığı, sınıfın önseli ile her sütundaki düzeyinin o sınıf altındaki oranlarının
çarpımıdır ve bu çarpım ancak sütunlar **sınıf verildiğinde** bağımsızsa doğru sayıyı verir.

## Modelin Sayısı ve Yirmi Aday

Model iki ayar değişkeniyle yazılır ve bir ızgara taranır. Basılan tablo doğrulama kümesinindir;
sınama kümesinin sayıları özet satırlarında verilir.

```python
def ogren(kume, sutun):                     # MODELDIR: sayimlar ve onsel oranlar
    top = collections.Counter(y for _, y in kume)
    say = {(a, c): collections.Counter(d[a] for d, y in kume if y == c)
           for a in sutun for c in (0, 1)}
    return top, say, {a: len({d[a] for d, _ in kume}) for a in sutun}


def sonsal(m, d, sutun, alfa):              # sinif 1 olasiligi; carpim log toplamidir
    top, say, ds = m
    n, lg = sum(top.values()), []
    for c in (0, 1):
        t = math.log(top[c] / n)
        for a in sutun:
            pay = say[(a, c)][d[a]] + alfa
            t = -math.inf if pay <= 0.0 else t + math.log(pay / (top[c] + alfa * ds[a]))
        lg.append(t)
    if lg[0] == -math.inf and lg[1] == -math.inf:
        return None                         # her iki sinif da elendi: model susuyor
    e = [math.exp(t - max(lg)) for t in lg]
    return e[1] / (e[0] + e[1])


def degerlendir(egt, hedef, sutun, alfa):
    m, p, susan = ogren(egt, sutun), [], 0
    for d, y in hedef:
        o = sonsal(m, d, sutun, alfa)
        if o is None:
            susan, o = susan + 1, 0.0
        p.append((o, y))
    return sum((o > 0.5) == y for o, y in p) / len(p), p, susan


IZGARA, ALFALAR = {}, (0.0, 0.25, 1.0, 4.0)
for n in (3, 4, 6, 8, 12):
    KS_N = {a: kesimler(EGT, a, n) for a in ("oynaklik", "kisi_basi")}
    E2, D2, S2 = kategorik(EGT, KS_N), kategorik(DOG, KS_N), kategorik(SIN, KS_N)
    for alfa in ALFALAR:
        IZGARA[(n, alfa)] = (degerlendir(E2, D2, SUTUN, alfa)[0],
                             degerlendir(E2, S2, SUTUN, alfa)[0])
print(f"{'aralik':>6}" + "".join(f"{a:>9}" for a in ALFALAR) + "   (dogrulama)")
for n in (3, 4, 6, 8, 12):
    print(f"{n:>6}" + "".join(f"{IZGARA[(n, a)][0]:>9.4f}" for a in ALFALAR))
sd = max(IZGARA, key=lambda a: (IZGARA[a][0], -a[0], -a[1]))
ss = max(IZGARA, key=lambda a: (IZGARA[a][1], -a[0], -a[1]))
print(f"\ndenenen aday {len(IZGARA)}")
for ad, a in (("dogrulamadan", sd), ("sinamadan", ss)):
    print(f"{ad + ' secilen:':<22}aralik {a[0]}, alfa {a[1]} -> dogrulama "
          f"{IZGARA[a][0]:.4f}, sinama {IZGARA[a][1]:.4f}")
print(f"ailenin sayisi {IZGARA[sd][1]:.4f}, taban cizgisinin "
      f"{IZGARA[sd][1] - TABAN_SIN:+.4f} ustunde; iki secim kumesi "
      f"{IZGARA[ss][1] - IZGARA[sd][1]:+.4f} ayriliyor")
```

```
aralik      0.0     0.25      1.0      4.0   (dogrulama)
     3   0.7540   0.7540   0.7540   0.7579
     4   0.7540   0.7540   0.7540   0.7579
     6   0.7738   0.7738   0.7659   0.7698
     8   0.7778   0.7778   0.7857   0.7857
    12   0.7579   0.7579   0.7619   0.7698

denenen aday 20
dogrulamadan secilen: aralik 8, alfa 1.0 -> dogrulama 0.7857, sinama 0.7817
sinamadan secilen:    aralik 4, alfa 4.0 -> dogrulama 0.7579, sinama 0.7857
ailenin sayisi 0.7817, taban cizgisinin +0.0238 ustunde; iki secim kumesi +0.0040 ayriliyor
```

Ailenin sayısı **0,7817**'dir, taban çizgisini 0,0238 — altı abone — geçer ve **20 aday**
denenerek bulunmuştur. Önceki dersin örnek tabanlı yordamı aynı öznitelik kümesiyle 0,7937
okumuştu. Olasılık üreten ve açık bir varsayıma dayanan bu aile, uzaklık toplayan yordamın
**gerisinde** kaldı; fark üç abone. Kursun ikinci iddiasının ilk örneği budur ve saklanmaz.

İki seçim kümesi ayrı adaylar veriyor. Doğrulamadan sekiz aralık ile 1,0 çıkıyor; sınamadan
bakılsaydı dört aralık ile 4,0 seçilir ve bildirilen sayı 0,7857 olurdu. O adayın doğrulama
sayısı 0,7579'dur, yani yirmi adayın en kötüleri arasındadır.

## Sıfır Sayım ve Düzleştirme

Seksen hücrenin en seyreği tarife sütununun en üst basamağı ile şüpheli sınıfının kesişimidir ve
sayımı sıfırdır: kırk metreküpü aşan tüketimi olan bir abone eğitimde şüpheli olarak hiç
görülmemiş. Çarpımda bir sıfır, öteki yedi sütunun söylediği her şeyi siler. **Düzleştirme** her
sayıma küçük bir sabit ekler; gerekçesi bir başarım ayarı değil bu yapısal kusurdur.

```python
def veto_hesabi(egt, hedef, sutun, tum_duzey):
    gorulen = {(a, c): {d[a] for d, y in egt if y == c} for a in sutun for c in (0, 1)}
    bos = sum(len(tum_duzey[a] - gorulen[(a, c)]) for a in sutun for c in (0, 1))
    veto = yanlis = 0
    for d, y in hedef:
        elenen = [c for c in (0, 1) if any(d[a] not in gorulen[(a, c)] for a in sutun)]
        if elenen:
            veto, yanlis = veto + 1, yanlis + (y in elenen)
    return bos, veto, yanlis


print(f"{'egitim':>6} {'bos hucre':>10} {'vetolanan':>10} {'yanlis veto':>12} "
      f"{'alfa=0':>8} {'alfa=1':>8}")
for m in (60, 120, 250, 500, 756):
    b, v, y = veto_hesabi(KE[:m], KS, SUTUN, DUZEY)
    print(f"{m:>6} {b:>10} {v:>10} {y:>12} "
          f"{degerlendir(KE[:m], KS, SUTUN, 0.0)[0]:>8.4f} "
          f"{degerlendir(KE[:m], KS, SUTUN, 1.0)[0]:>8.4f}")
```

```
egitim  bos hucre  vetolanan  yanlis veto   alfa=0   alfa=1
    60          8        137           24   0.7341   0.7302
   120          4         56            9   0.7460   0.7579
   250          2          1            1   0.7381   0.7540
   500          1          1            1   0.7659   0.7698
   756          1          1            1   0.7778   0.7817
```

Altmış satırlık eğitimde seksen hücrenin sekizi boştur ve bu sekiz boşluk 252 sınama satırının
**137'sini** vetoluyor; 24'ünde vetolanan sınıf abonenin gerçek sınıfıdır, yani karar sekiz
sütunun kanıtına değil tek bir eksik sayıma dayanıyor. Eğitim 756 satıra çıktığında boş hücre
bire, veto tek satıra iner; düzleştirme katsayısı sıfırdan büyük olduğu anda veto tümüyle
kalkar.

Son iki sütun düzeltmenin sınırını gösteriyor. Altmış satırlık eğitimde düzleştirme sayıyı
0,7341'den 0,7302'ye **düşürüyor**; 120 satırda 0,7460'tan 0,7579'a çıkarıyor. Ödediği şey
doğruluk değil, modelin susmaması.

## Varsayım Bozulduğunda

Koşullu bağımsızlık ölçülebilir bir iddiadır: iki sütunun sınıf içindeki ortak sayımı tek tek
oranlarının çarpımından ne kadar sapıyor. Sapma sıfırsa varsayım o çift için doğrudur.

```python
def bagimlilik(kume, a, b):     # sinif verildiginde ortak sayimin carpimdan sapmasi
    t = 0.0
    for c in (0, 1):
        alt = [d for d, y in kume if y == c]
        n = len(alt)
        pa = collections.Counter(d[a] for d in alt)
        pb = collections.Counter(d[b] for d in alt)
        pab = collections.Counter((d[a], d[b]) for d in alt)
        t += n / len(kume) * sum(abs(pab[(u, v)] / n - pa[u] * pb[v] / n / n)
                                 for u in pa for v in pb) / 2
    return t


for a, b in (("hane", "kisi_basi"), ("donem", "oynaklik"),
             ("donem", "sifir_okuma")):
    print(f"{a:<8} {b:<12} sapma {bagimlilik(KE, a, b):.3f}")


def kopyali(kume, k):           # ayni bilgiyi tasiyan sutunun tabloya yeniden girmesi
    return [(dict(d, **{f"tarife_{i}": d["tarife"] for i in range(k)}), y)
            for d, y in kume]


POZ = sum(y for _, y in KS)
print(f"\n{'kopya':>5} {'sutun':>6} {'dogruluk':>9} {'uc olasilik':>12} "
      f"{'ort guven':>10} {'ust-' + str(POZ) + ' isabet':>14}")
for k in (0, 1, 2, 4, 8):
    sut = SUTUN + [f"tarife_{i}" for i in range(k)]
    d, p, _ = degerlendir(kopyali(KE, k), kopyali(KS, k), sut, 1.0)
    ust = sorted(p, key=lambda t: -t[0])[:POZ]
    print(f"{k:>5} {len(sut):>6} {d:>9.4f} "
          f"{sum(1 for o, _ in p if o > 0.99 or o < 0.01):>12} "
          f"{statistics.fmean(max(o, 1 - o) for o, _ in p):>10.3f} "
          f"{sum(y for _, y in ust):>14}")
```

```
hane     kisi_basi    sapma 0.407
donem    oynaklik     sapma 0.235
donem    sifir_okuma  sapma 0.011

kopya  sutun  dogruluk  uc olasilik  ort guven  ust-61 isabet
    0      8    0.7817            2      0.842             29
    1      9    0.7778            5      0.862             32
    2     10    0.7778           17      0.889             33
    4     12    0.7817           72      0.932             32
    8     16    0.7857          169      0.970             33
```

Varsayım bu tabloda zaten bozuktur. Hane büyüklüğü ile kişi başına tüketimin sapması 0,407'dir ve
bu tanımın kendisidir: kişi başına tüketim, ortalama tüketimin hane büyüklüğüne bölünmüş halidir.
Dönem sayısıyla oynaklık 0,235 sapıyor, çünkü tek dönemi olan abonenin oynaklığı sıfırdır. En
bağımsız çift 0,011 ile dönem sayısı ve sıfır okumadır.

Alt tablo iki sonucu ayırır. **Olasılık çıktısı uçlara gidiyor:** uç olasılıklı abone sayısı
2'den 169'a, ortalama güven 0,842'den 0,970'e çıkıyor; aynı kanıt sekiz kez çarpıldığında model
bağımsız sekiz kanıt görmüş gibi davranır. **Sıralama ise ayakta kalıyor:** üst 61 abonedeki
gerçek şüpheli sayısı 29'dan 33'e çıkıyor, doğruluk 0,7817'den 0,7857'ye gidiyor. Kopyalanan
sütun bütün abonelerin skorunu aynı yönde ittiği için sıralamayı bozmuyor; bozduğu şey **sayının
büyüklüğüdür**. Bu ailenin çıktısı bir sıralama skoru olarak kullanılabilir, bir güven ölçüsü
olarak kullanılamaz.

## Özet

- Sekiz sütunun 201.600 bileşimine karşılık 756 eğitim satırı vardır; koşullu bağımsızlık
  varsayımı sayım tablosunu 80 hücreye indirir ve ailenin tek gerekçesi budur.
- Ailenin sayısı 0,7817'dir, taban çizgisini 0,0238 geçer ve **20 aday** denenerek bulunmuştur;
  önceki dersin örnek tabanlı yordamı aynı öznitelik kümesiyle 0,7937 okumuştu.
- Sınamadan seçim yapılsaydı başka bir aday seçilir ve bildirilen sayı 0,7857 olurdu.
- Sıfır sayım bir sınıfı tümüyle eler: 60 satırlık eğitimde 137 sınama satırı vetolanıyor,
  24'ünde vetolanan sınıf doğru sınıftır. Düzleştirme vetoyu kaldırır ama doğruluğu güvenceye
  almaz; 60 satırda sayı 0,7341'den 0,7302'ye düşüyor.
- Varsayım bozulduğunda iki sonuç ayrışır: uç olasılıklı abone 2'den 169'a çıkarken üst 61'deki
  isabet 29'dan 33'e gidiyor.

## Sonraki Adım

Bu ailenin kararı bütün eğitim satırlarının sayımına dayanıyor: sınırdan uzakta duran abone ile
tam sınırın üstünde duran abone aynı hücreyi bir birim büyütüyor. Önceki dersin komşu yordamında
da 31 komşunun her biri eşit oy veriyordu. Sonraki ders bunun tersini yapan bir aile alır. **Marj
temelli sınıflandırıcı** yalnız sınıra yakın örneklerle ilgilenir; sınırı iki sınıf arasındaki
boşluğun ortasına oturtur ve kararı taşıyan örnekleri **destek vektörü** olarak açıkça sayar.
Ders marj genişliğini ayarlayan katsayıyı süpürür, her genişlikte kaç örneğin kararı taşıdığını
basar ve eğri sınırı sütun açmadan üreten **çekirdek dönüşümünü** açıkça hesaplanmış polinom
öznitelikleriyle ölçer.
