İçeriğe geç
academia.sh

Ders 04 / 20

Lojistik Bağlanım

Doğrusal bir düzlemin çıktısının olasılığa sıkıştırılması ve o olasılığın eşikten önce sürekli olduğunun ölçülmesi: on iki sabit sütunla model sınama kümesinde 0,8016 verir ve taban çizgisini 0,0437, yani on bir aboneyi geçer. Dokuz aday denendiğinde doğrulama kümesinde beşi 0,8373 ile berabere kalır ve o beşin sınama sayıları 0,7937 ile 0,8016 arasında bölünür; doğrulamadan okunan ayar sınamada 0,7937 verir, fark iki abonedir. Sınama kümesindeki 252 abonenin 252'si farklı bir olasılık alır; eşik 0,20'den 0,80'e süpürüldüğünde tek bir model doğrulukta 0,7183 ile 0,8016 arasında yedi ayrı sayı verir, işaretlenen abone 102'den 5'e iner ve 0,40 ile 0,60 arasında 27 abone sınıf değiştirir.

İçindekiler

Üç derste hedef sürekli bir sayıydı ve model o sayıyı doğrudan söyledi. Kursun through-line problemi ise bir sınıflandırmadır: bir abone kaçak ya da arıza şüphesi taşıyor mu, ve oradaki taban çizgisi 0,7579. Aynı doğrusal düzlem bu problemde doğrudan kullanılamaz. Düzlemin çıktısı eksi sonsuzdan artı sonsuza uzanır; etiket ise yalnız sıfır ile birdir. Bir aboneye “-3,4 şüphelidir” demek anlamsızdır.

Köprü, düzlemin çıktısını sıfır ile bir arasına sıkıştıran S biçimli bir işlevdir. Sıkıştırılmış sayı bir olasılık gibi okunur ve model bu haliyle lojistik bağlanım adını alır — bağlanım yordamıdır, çünkü sürekli bir sayı kestirir; sınıflandırıcı olması ancak o sayıya bir eşik uygulandıktan sonradır. Bu dersin ölçüsü tam olarak buradadır: eşik uygulanmadan önce çıktının ne taşıdığı. Eşiği seçmek ayrı bir iştir ve model-degerlendirme konusuna bırakılır.

  • DM27. Küme, bölme ve tohum önceki üç dersteki gibidir. Hedef şüpheli etiketidir ve taban çizgisi en sık sınıfı söylemektir: sınama kümesinde 0,7579.
  • DM28. Öznitelik kümesi M27/K02’nin bıraktığı on iki sütundur ve kurs boyunca sabit kalır: ortalama tüketim, oynaklık, hane büyüklüğü, memnuniyet, dönem sayısı, sıfır okuma göstergesi, kişi başına tüketim ve beş bölge göstergesi. Bağlanım derslerinin dışarıda bıraktığı sütunlar burada kullanılır, çünkü hedef artık tüketim değil etikettir.
  • DM29. Sütunlar eğitim kümesinden öğrenilen ortalama ve değişkenlikle ölçeklenir. M27/K02’nin Hazırlama Adımları konusu bu adımın eğim temelli bir modelde zorunlu olduğunu ölçmüştü; burada varsayılır.
  • DM30. Beş bölge göstergesinin hepsi kullanılır. Bağlanım derslerinde biri referans olarak dışarıda bırakılmıştı; eğim temelli çözüm tekil takım çözmediği için burada gerekmiyor.
  • DM31. Çözüm eğim inişidir: ağırlıklar kayıp yüzeyinin eğimi yönünde adım adım güncellenir. Ayar değişkenleri öğrenme adımı ve tur sayısıdır.
  • DM32. Denenen aday sayısı 9’dur: üç öğrenme adımı, üç tur sayısı.
  • DM33. Ölçü doğruluktur ve sınama kümesi 252 abonedir; bir abone 0,0040 eder. Doğruluğun neyi sakladığı ve hangi ölçütle değiştirilmesi gerektiği model-degerlendirme/0102’ye bırakılır.
  • DM34. Eşik süpürmesi bu derste seçim yapmaz; tek bir modelin eşikten bağımsız olduğunu göstermek için basılır. İşletme noktasının bir bedel hesabıyla seçilmesi model-degerlendirme/03’ün konusudur.
  • DM35. Söylenen olasılığın gerçekleşen orana oturup oturmadığı ayrı bir sorudur ve model-degerlendirme/04’e bırakılır.

Düzlemden Olasılığa

Kurulum kümeyi üretir, on iki sütunu sabitler ve iki oranı basar.

# lojistik.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# hedef bu derste kacak ya da ariza suphesi etiketidir.
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),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    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:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def olcekli(x):                             # OGRENME egitimden, UYGULAMA her kumeye
    return [1.0] + [(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN]


print(f"egitim {len(EGT)}, dogrulama {len(DOG)}, sinama {len(SIN)}, sutun {len(ALAN)}")
print(f"supheli orani egitimde {sum(x['supheli'] for x in EGT) / len(EGT):.4f}, "
      f"sinamada {sum(x['supheli'] for x in SIN) / len(SIN):.4f}")
print(f"taban cizgisi (en sik sinif) sinamada {TABAN:.4f}")
egitim 756, dogrulama 252, sinama 252, sutun 12
supheli orani egitimde 0.2222, sinamada 0.2421
taban cizgisi (en sik sinif) sinamada 0.7579

Sıkıştırma ve eğim inişi birlikte durur. Sıkıştırılan sayı, doğrusal puanın logit (log-odds) olarak okunmasıyla aynı şeydir: puan sıfırken olasılık 0,5, puan büyüdükçe bire, küçüldükçe sıfıra gider ve hiçbir zaman uçlara değmez.

def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


X = [olcekli(x) for x in EGT]
Y = [x["supheli"] for x in EGT]
P = len(X[0])


def lojistik(adim, tur):                    # MODELDIR: lojistik baglanim
    w = [0.0] * P
    for _ in range(tur):
        g = [0.0] * P
        for i in range(len(X)):
            h = sikistir(sum(w[j] * X[i][j] for j in range(P))) - Y[i]
            for j in range(P):
                g[j] += h * X[i][j]
        for j in range(P):
            w[j] -= adim * g[j] / len(X)
    return w


def olasilik(w, x):
    return sikistir(sum(a * b for a, b in zip(w, olcekli(x))))


def dogruluk(w, s, esik=0.5):
    return sum((olasilik(w, x) > esik) == x["supheli"] for x in s) / len(s)


SONUC = []
print(f"{'ogrenme adimi':>14} {'tur':>5} {'egitimde':>9} {'dogrulama':>10} {'sinama':>8}")
for adim in (0.1, 0.3, 1.0):
    for tur in (100, 300, 600):
        w = lojistik(adim, tur)
        SONUC.append((adim, tur, dogruluk(w, DOG), dogruluk(w, SIN), w))
        print(f"{adim:>14} {tur:>5} {dogruluk(w, EGT):>9.4f} "
              f"{SONUC[-1][2]:>10.4f} {SONUC[-1][3]:>8.4f}")
en_d = max(SONUC, key=lambda t: t[2])
en_s = max(SONUC, key=lambda t: t[3])
print(f"\ntaban cizgisi {TABAN:.4f}, denenen aday sayisi {len(SONUC)}")
print(f"dogrulamadan okunan ayar ({en_d[0]}, {en_d[1]}): dogrulama {en_d[2]:.4f}, "
      f"sinama {en_d[3]:.4f}")
print(f"sinamadan okunsaydi ayar ({en_s[0]}, {en_s[1]}): dogrulama {en_s[2]:.4f}, "
      f"sinama {en_s[3]:.4f}")
print(f"iki secim arasindaki fark {en_s[3] - en_d[3]:.4f}, yani "
      f"{round((en_s[3] - en_d[3]) * len(SIN))} abone")
print(f"dogrulamada ayni en yuksek sayiyi veren aday "
      f"{sum(1 for t in SONUC if abs(t[2] - en_d[2]) < 1e-12)}")
W = en_d[4]
 ogrenme adimi   tur  egitimde  dogrulama   sinama
           0.1   100    0.8175     0.8056   0.8016
           0.1   300    0.8201     0.8373   0.7937
           0.1   600    0.8188     0.8373   0.8016
           0.3   100    0.8201     0.8373   0.7937
           0.3   300    0.8175     0.8333   0.8016
           0.3   600    0.8148     0.8333   0.8016
           1.0   100    0.8161     0.8333   0.8016
           1.0   300    0.8148     0.8373   0.8016
           1.0   600    0.8148     0.8373   0.8016

taban cizgisi 0.7579, denenen aday sayisi 9
dogrulamadan okunan ayar (0.1, 300): dogrulama 0.8373, sinama 0.7937
sinamadan okunsaydi ayar (0.1, 100): dogrulama 0.8056, sinama 0.8016
iki secim arasindaki fark 0.0079, yani 2 abone
dogrulamada ayni en yuksek sayiyi veren aday 5

Üçlü tamamlandı: taban çizgisi 0,7579, ailenin sayısı 0,8016, denenen aday sayısı 9. Fark 0,0437, yani sınama kümesinde on bir abone. Dokuz adayın sınama sütunu yalnız iki ayrı değer alıyor — 0,7937 ve 0,8016 — ve aradaki fark iki abonedir. Öğrenme adımı ile tur sayısı bu problemde birbirinin yerine geçiyor: küçük adımla altı yüz tur, büyük adımla üç yüz tur aynı yere varıyor.

Son satır kursun kuralını beklenmedik bir yerden gösteriyor. Dokuz adayın beşi doğrulama kümesinde tam olarak aynı sayıyı, 0,8373’ü veriyor. Doğrulama kümesi 252 satırdır ve 0,0040’lık adımlarla ölçer; beş farklı ayarın aynı basamağa düşmesi olağandır. Ama o beş aday sınama kümesinde aynı sayıyı vermiyor. Beraberliği bozan kural — tablodaki ilk sırayı almak — modelin hiçbir özelliği değildir ve iki abone ediyor.

Çıktı Eşikten Önce Süreklidir

Seçilen model tek bir ayardır, ama tek bir sayı vermez. Verdiği şey 252 olasılıktır ve o olasılıklardan bir sınıf çıkarmak ayrı bir karardır.

esit = [t for t in SONUC if abs(t[2] - en_d[2]) < 1e-12]
print(f"dogrulamada berabere kalan {len(esit)} adayin sinama sayilari: "
      f"{sorted({round(t[3], 4) for t in esit})}")
p = sorted((olasilik(W, x), x["supheli"]) for x in SIN)
print(f"sinamada farkli olasilik degeri {len({round(q, 9) for q, _ in p})}/{len(SIN)}, "
      f"en dusuk {p[0][0]:.4f}, en yuksek {p[-1][0]:.4f}\n")
print(f"{'olasilik araligi':<18} {'abone':>6} {'supheli':>8} {'supheli orani':>15}")
for k in range(5):
    a, b = k / 5, (k + 1) / 5
    d = [q for q in p if a <= q[0] < b or (k == 4 and q[0] >= b)]
    g = sum(t[1] for t in d)
    print(f"[{a:.1f}, {b:.1f})".ljust(18)
          + f" {len(d):>6} {g:>8} {g / len(d) if d else 0.0:>15.4f}")
print(f"\n{'esik':>6} {'dogruluk':>9} {'isaretlenen':>12} {'yakalanan':>10} "
      f"{'kacirilan':>10}")
for e in (0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80):
    isaret = sum(1 for q, _ in p if q > e)
    yakalanan = sum(1 for q, y in p if q > e and y)
    print(f"{e:>6.2f} {dogruluk(W, SIN, e):>9.4f} {isaret:>12} {yakalanan:>10} "
          f"{sum(t[1] for t in p) - yakalanan:>10}")
print(f"\n0,40 ile 0,60 arasinda sinif degistiren abone "
      f"{sum(1 for q, _ in p if 0.40 < q <= 0.60)}")
print(f"esik 0,5 sabit tutulunca dogruluk {dogruluk(W, SIN):.4f}, "
      f"taban cizgisi {TABAN:.4f}, en iyi esik 0,60'ta {dogruluk(W, SIN, 0.60):.4f}")
dogrulamada berabere kalan 5 adayin sinama sayilari: [0.7937, 0.8016]
sinamada farkli olasilik degeri 252/252, en dusuk 0.0196, en yuksek 0.9838

olasilik araligi    abone  supheli   supheli orani
[0.0, 0.2)            150       15          0.1000
[0.2, 0.4)             52       18          0.3462
[0.4, 0.6)             27       11          0.4074
[0.6, 0.8)             18       12          0.6667
[0.8, 1.0)              5        5          1.0000

  esik  dogruluk  isaretlenen  yakalanan  kacirilan
  0.20    0.7183          102         46         15
  0.30    0.7659           68         35         26
  0.40    0.7817           50         28         33
  0.50    0.7937           31         20         41
  0.60    0.8016           23         17         44
  0.70    0.7897           16         12         49
  0.80    0.7778            5          5         56

0,40 ile 0,60 arasinda sinif degistiren abone 27
esik 0,5 sabit tutulunca dogruluk 0.7937, taban cizgisi 0.7579, en iyi esik 0,60'ta 0.8016

İkinci satır dersin en yalın bulgusudur: 252 abonenin 252’si farklı bir olasılık alıyor. Model bir etiket üretmiyor, bir sıralama üretiyor. En düşük olasılık 0,0196, en yükseği 0,9838; sıkıştırma uçlara değmiyor, çünkü S biçimli işlev sıfıra ve bire ancak sonsuzda ulaşır.

Aralık tablosu o sıralamanın boş olmadığını gösteriyor. En alt aralıktaki 150 abonenin 15’i, yani onda biri şüpheli; en üst aralıktaki beş abonenin beşi de şüpheli. Sıralama etiketle aynı yönde gidiyor. Söylenen olasılığın gerçekleşen orana oturup oturmadığı — örneğin 0,4–0,6 aralığındaki oranın 0,4074 çıkması — ayrı bir sorudur ve model-degerlendirme/04’e bırakılır.

Eşik tablosu dersin başlığını taşıyan sayıyı veriyor. Tek bir model, tek bir ağırlık kümesi, tek bir eğitim — ve yedi ayrı doğruluk sayısı: 0,7183’ten 0,8016’ya. Eşik 0,20’de model 102 aboneyi işaretliyor ve 61 şüphelinin 46’sını yakalıyor; eşik 0,80’de yalnız beş abone işaretleniyor ve beşi de gerçekten şüpheli, ama 56 şüpheli kaçıyor. Bunların hiçbiri farklı bir model değil.

Bu yüzden “modelin doğruluğu 0,7937’dir” cümlesi eksiktir. Doğru cümle şudur: 0,5 eşiğiyle 0,7937’dir. Eşik bir model özelliği değil, bir karardır ve karar 0,40 ile 0,60 arasında gezdirilirse 27 abone sınıf değiştirir. Hangi eşiğin seçileceği yakalanan kaçakla boşa giden saha ziyaretinin bedeline bağlıdır; o hesap model-degerlendirme/03’ün konusudur ve burada yapılmaz.

Özet

  • Lojistik bağlanım bir sınıflandırıcı değil, olasılık kestiren bir bağlanım yordamıdır; sınıflandırıcı olması ancak bir eşik uygulandıktan sonradır.
  • On iki sabit sütunla model sınama kümesinde 0,8016 veriyor; taban çizgisi 0,7579, fark 0,0437 ve denenen aday sayısı 9’dur.
  • Dokuz adayın beşi doğrulama kümesinde tam olarak 0,8373 ile berabere kalıyor ama sınamada 0,7937 ile 0,8016’ya bölünüyor; beraberliği bozan kural modelin özelliği değildir ve iki abone eder.
  • Sınama kümesindeki 252 abonenin 252’si farklı bir olasılık alıyor, en düşüğü 0,0196, en yükseği 0,9838. Model bir etiket değil, bir sıralama üretiyor ve sıralama etiketle aynı yönde gidiyor.
  • Aynı model eşik 0,20’den 0,80’e süpürüldüğünde 0,7183 ile 0,8016 arasında yedi ayrı doğruluk veriyor; işaretlenen abone 102’den 5’e iniyor ve 0,40 ile 0,60 arasında 27 abone sınıf değiştiriyor.

Sonraki Adım

Bu dersin modeli on iki katsayı taşıyor ve o katsayılar okunabilir: her biri bir sütuna aittir, işareti ve büyüklüğü vardır. Doğrusal modellerin en çok anılan üstünlüğü budur. Sonraki ders o üstünlüğü bir övgü olarak değil bir sayı olarak ele alır: okunabilir katsayılı bir modelin ayrılmış kümedeki sayısı ile bu konudaki en iyi ailenin sayısı arasındaki fark kaç abonedir, ve katsayıya bakarak ne söylenebilir, ne söylenemez. Konunun kapanışı da oradadır.

İ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