İçeriğe geç
academia.sh

Ders 03 / 11

Kendi Kendine Denetimli Öğrenme

Etiket veriden türetilir: her abonenin son okuması gizlenir ve önceki okumalardan kestirilir. Vekil görevde taban çizgisi ayrılmış kümede 6,3776 m³ ortalama mutlak hata verir, en küçük kareler modeli 5,9661 m³ — kazanç 0,4115 m³ ve sıfır etiketle elde edilmiştir. Vekil görevin ürettiği üç sayı asıl göreve taşındığında yalnız kayıt öznitelikleriyle ölçülen 0,7851 sayısı 0,8037'ye çıkar. Aynı gösterim vekil görevin taban çizgisinden kurulduğunda 0,8064 çıkar, yani öğrenilen kısmın katkısı 0,0027 eksidir: fark vekil görevin öğrendiğinden değil, taşınan ham okumadan gelmektedir. Elle çıkarılmış dokuz öznitelik hâlâ 0,8594 vermektedir.

İçindekiler

Önceki ders dört kurulumun kaç etiket istediğini saydı. Üçü etiket için ödeme yaptı, dördüncüsü etiketi ziyaretle kazandı. Hiçbiri şunu sormadı: etiket veriden türetilebilir mi. Okuma tablosunda kimsenin etiketlemediği bir yapı vardır — her abonenin dönemler boyunca bıraktığı iz. Bir dönemin okumasını kapatıp onu kalanlardan kestirmek etiket istemez, çünkü cevap zaten tablodadır.

Bu ders o kurulumu kurar ve iki ayrı görevin iki ayrı taban çizgisi olduğunu gösterir.

  • MK14. Kendi kendine denetimli öğrenme (self-supervised learning): etiket dışarıdan verilmez, verinin kendisinden türetilir. Yordam denetimli çalışır, ama denetimi veri sağlar.
  • MK15. Vekil görev (pretext task): cevabı zaten veride bulunan bir görev. Amaç o görevi çözmek değil, çözerken bir şey öğrenmektir.
  • MK16. Gösterim (representation): vekil görevin ürettiği ve asıl göreve öznitelik olarak taşınan sayılar. Bu derste üç sayı taşınır.
  • MK17. Vekil görevin kendi taban çizgisi vardır ve o taban da bir gösterim üretir. İki gösterim aynı yerde karşılaştırılmadan vekil görevin katkısı ölçülmüş sayılmaz.
  • MK18. Vekil görev sayısal bir değeri kestirir; bu tür göreve bağlanım (regression) denir. Terim, İstatistiksel Analiz kursunda değişkenler arası ilişkiyi modellemek için kullanılan regresyondan ayrı tutulur: burada amaç ilişkiyi açıklamak değil, görülmemiş bir değeri kestirmektir.
  • MK19. Bağlanımın ölçüsü ortalama mutlak hata, sınıflandırmanınki doğruluktur. Bu ders iki ölçü kullanır ve her birinin tabanını ayrı seçer.

Kurgu Kümenin Yeniden Kurulması

# kurulum.py — 01. dersin kurgu kumesi ayni tohumla yeniden kurulur: okuma
# tablosu, abone ozeti, kurgu etiket, egitim / ayrilmis ayrimi ve agac ogrenici.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26),
         ("bati", 0.14, 14), ("merkez", 0.18, 23)]
OZNITELIK = ["ortalama", "kisi_basi", "dusus", "sifir_okuma", "okuma_sayisi",
             "memnuniyet", "hane_kisi", "en_yuksek", "en_dusuk"]


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


_ab, _el, _seri = [], [], {}
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    k = {"abone_no": 10001 + i, "bolge": b[0], "taban": b[2],
         "hane_kisi": ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]),
         "memnuniyet": ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) + 1}
    (_el if r() < 0.046 else _ab).append(k)
_gecerli = {a["abone_no"] for a in _ab}
for k in _ab + _el:
    r = uretec(TOHUM + 7000 + k["abone_no"])
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        t = 0.0 if r() < 0.038 else math.floor(k["taban"] * math.exp(
            (r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100
        if k["abone_no"] in _gecerli:
            _seri.setdefault(k["abone_no"], []).append(t)
        r()

ABONE = []
for k in _ab:
    t = _seri.get(k["abone_no"])
    if not t:
        continue
    ort = sum(t) / len(t)
    a = {"abone_no": k["abone_no"], "bolge": k["bolge"], "seri": t,
         "hane_kisi": k["hane_kisi"], "memnuniyet": k["memnuniyet"],
         "okuma_sayisi": len(t), "ortalama": ort, "en_yuksek": max(t),
         "en_dusuk": min(t), "sifir_okuma": sum(1 for v in t if v == 0),
         "kisi_basi": ort / max(1, k["hane_kisi"]),
         "dusus": (t[0] - t[-1]) / t[0] if len(t) > 1 and t[0] > 0 else 0.0}
    r = uretec(TOHUM + 31000 + a["abone_no"])
    a["suphe"] = 1 if (1.30 * a["sifir_okuma"] + 1.25 * (a["dusus"] > 0.45)
                       + 1.05 * (a["kisi_basi"] > 12.0) + 0.65 * (a["okuma_sayisi"] < 3)
                       + 0.45 * (a["memnuniyet"] <= 2) - 1.55
                       + (r() + r() - 1.0) * 1.1) > 0 else 0
    ABONE.append(a)

r = uretec(TOHUM + 90001)
EGITIM, AYRILMIS = [], []
for a in ABONE:
    (EGITIM if r() < 0.70 else AYRILMIS).append(a)
poz = lambda k: sum(a["suphe"] for a in k)
dogruluk = lambda f, k: sum(1 for a in k if f(a) == a["suphe"]) / len(k)
_saf = lambda k: 2 * (poz(k) / len(k)) * (1 - poz(k) / len(k)) if k else 0.0


def ogren(k, derinlik=3, en_az=40):
    """01. dersin acgozlu karar agaci: bolme olcutu ve durma kurali orada."""
    en, secim = _saf(k) * len(k), None
    if derinlik and len(k) >= en_az:
        for oz in OZNITELIK:
            for e in sorted({a[oz] for a in k})[1:]:
                sol = [a for a in k if a[oz] < e]
                sag = [a for a in k if a[oz] >= e]
                m = _saf(sol) * len(sol) + _saf(sag) * len(sag)
                if m < en - 1e-9:
                    en, secim = m, (oz, e, sol, sag)
    if secim is None:
        return 1 if 2 * poz(k) > len(k) else 0
    s, g = ogren(secim[2], derinlik - 1, en_az), ogren(secim[3], derinlik - 1, en_az)
    return s if s == g else (secim[0], secim[1], s, g)


def uygula(d, a):
    while isinstance(d, tuple):
        d = d[2] if a[d[0]] < d[1] else d[3]
    return d


print(f"kurgu kume (tohum {TOHUM}): {len(ABONE)} abone, {len(EGITIM)} egitim, "
      f"{len(AYRILMIS)} ayrilmis, {poz(ABONE)} supheli")
kurgu kume (tohum 20260218): 1260 abone, 883 egitim, 377 ayrilmis, 327 supheli

Vekil Görev ve Kendi Taban Çizgisi

Vekil görev şudur: her abonenin son okuması gizlenir ve önceki okumalardan, okuma sayısından ve kayıt bilgilerinden kestirilir. Bu görev bir kapı ziyareti gerektirmez; cevabı zaten tabloda duruyor, yalnız modele gösterilmiyor.

Görev sayısal bir değeri kestirdiği için tabanı da sayısal olmalıdır. Öğrenmeyen yordam burada “herkese kümenin genel ortalamasını söylemek”tir; sınıflandırmadaki en sık sınıfın bağlanımdaki karşılığı budur. Model tarafında en küçük kareler kullanılır ve normal denklemler eleme ile çözülür.

# vekil.py — etiketsiz bir gorev: her abonenin son okumasi gizlenir ve onceki
# okumalardan kestirilir. Cevap zaten tablodadir, hicbir etiket harcanmaz.
import statistics
from collections import Counter


def coz(A, b):
    """Dogrusal denklem takimi: kismi pivotlamali eleme."""
    n = len(b)
    M = [A[i][:] + [b[i]] for i in range(n)]
    for i in range(n):
        p = max(range(i, n), key=lambda s: abs(M[s][i]))
        M[i], M[p] = M[p], M[i]
        if abs(M[i][i]) < 1e-12:  # tekil sutun: katsayi sifir birakilir
            continue
        for s in range(n):
            if s != i and M[s][i]:
                f = M[s][i] / M[i][i]
                for c in range(i, n + 1):
                    M[s][c] -= f * M[i][c]
    return [M[i][n] / M[i][i] if abs(M[i][i]) > 1e-12 else 0.0 for i in range(n)]


def en_kucuk_kareler(X, y):
    k = len(X[0])
    return coz([[sum(x[i] * x[j] for x in X) for j in range(k)] for i in range(k)],
               [sum(x[i] * t for x, t in zip(X, y)) for i in range(k)])


GENEL = statistics.fmean(v for a in EGITIM for v in a["seri"])


def girdi(a):
    onceki = a["seri"][:-1]
    return [1.0, statistics.fmean(onceki) if onceki else GENEL,
            float(len(a["seri"])), float(a["hane_kisi"]), float(a["memnuniyet"])]


hedef = lambda k: [a["seri"][-1] for a in k]
AGIRLIK = en_kucuk_kareler([girdi(a) for a in EGITIM], hedef(EGITIM))
kestir = lambda a: sum(c * v for c, v in zip(AGIRLIK, girdi(a)))
hata = lambda f, k: statistics.fmean(abs(f(a) - a["seri"][-1]) for a in k)
E = [26, 12, 12]
y = lambda h: str(h[0]).ljust(E[0]) + str(h[1]).rjust(E[1]) + str(h[2]).rjust(E[2])
print("vekil gorev: son okumanin kestirimi, olcu ortalama mutlak hata (m3)")
print(y(["yordam", "egitimde", "ayrilmista"]))
print(y(["taban: hep genel ortalama", f"{hata(lambda a: GENEL, EGITIM):.4f}",
         f"{hata(lambda a: GENEL, AYRILMIS):.4f}"]))
print(y(["en kucuk kareler", f"{hata(kestir, EGITIM):.4f}",
         f"{hata(kestir, AYRILMIS):.4f}"]))
print("katsayilar", [round(v, 4) for v in AGIRLIK])
vekil gorev: son okumanin kestirimi, olcu ortalama mutlak hata (m3)
yordam                        egitimde  ayrilmista
taban: hep genel ortalama       5.9664      6.3776
en kucuk kareler                5.6979      5.9661
katsayilar [18.2859, 0.262, -1.5773, -0.0497, -0.1704]

Vekil görev kendi ölçüsünde tabanı geçiyor: ayrılmış kümede hata 6,3776 m³’ten 5,9661 m³’e iniyor, kazanç 0,4115 m³. Bu kazanç sıfır etiketle elde edilmiştir; harcanan tek şey tablonun kendisidir.

Katsayılar modelin ne öğrendiğini söylüyor. Önceki okumaların ortalamasının katsayısı 0,2620’dir: bir abonenin geçmiş tüketimi son okumasını kısmen belirler, ama zayıf biçimde. Okuma sayısının katsayısı -1,5773’tür; üç dönemi tam olan abonelerin son okuması sistematik olarak daha düşüktür, çünkü kurgu kümede her dönem bir öncekinin altına iner. Hane kişi sayısı ve memnuniyetin katsayıları sıfıra yakındır.

Gösterimin Asıl Göreve Katkısı

Vekil görevden asıl göreve taşınacak şey kestirimin kendisi değil, kestirimle gerçek arasındaki ilişkidir. Üç sayı taşınır: modelin beklediği değer, gerçekle arasındaki fark ve bu farkın beklenene oranı.

Karşılaştırma dürüst olsun diye asıl görev bu kez dar bir öznitelik kümesiyle kurulur: yalnız abone kaydından gelen üç sütun. Okuma tablosuna dokunmadan elde edilebilen tek bilgi budur; gösterimin katkısı bu darlığın üstüne eklenen fark olarak okunur.

# gosterim.py — vekil gorevin cikardigi uc sayi asil goreve oznitelik olarak
# tasinir. Gosterim sifir etiketle ogrenildi; asil gorev 883 etiket kullanir.
for a in ABONE:
    b = kestir(a)
    a["beklenen"], a["sapma"] = b, a["seri"][-1] - b
    a["bagil_sapma"] = (a["seri"][-1] - b) / (abs(b) + 1.0)
KAYIT = ["hane_kisi", "memnuniyet", "okuma_sayisi"]
GOSTERIM = ["beklenen", "sapma", "bagil_sapma"]
ELLE = OZNITELIK[:]
en_sik = Counter(a["suphe"] for a in EGITIM).most_common(1)[0][0]
TABAN_A = dogruluk(lambda a: en_sik, AYRILMIS)


def olc(ad, oz):
    global OZNITELIK
    OZNITELIK = oz
    d = ogren(EGITIM)
    ic, dis = dogruluk(lambda a: uygula(d, a), EGITIM), dogruluk(
        lambda a: uygula(d, a), AYRILMIS)
    OZNITELIK = ELLE
    print(str(ad).ljust(28) + str(len(oz)).rjust(4)
          + f"{ic:.4f}".rjust(12) + f"{dis:.4f}".rjust(12)
          + f"{dis - TABAN_A:+.4f}".rjust(13))


print("asil gorev: kacak suphesi, olcu dogruluk")
print("oznitelik kumesi".ljust(28) + "kac".rjust(4) + "egitimde".rjust(12)
      + "ayrilmista".rjust(12) + "tabana gore".rjust(13))
print("taban: hep en sik sinif".ljust(28) + "0".rjust(4)
      + f"{dogruluk(lambda a: en_sik, EGITIM):.4f}".rjust(12)
      + f"{TABAN_A:.4f}".rjust(12) + "+0.0000".rjust(13))
olc("yalniz kayit", KAYIT)
olc("kayit + gosterim", KAYIT + GOSTERIM)
olc("elle cikarilmis dokuz", ELLE)
asil gorev: kacak suphesi, olcu dogruluk
oznitelik kumesi             kac    egitimde  ayrilmista  tabana gore
taban: hep en sik sinif        0      0.7350      0.7533      +0.0000
yalniz kayit                   3      0.7939      0.7851      +0.0318
kayit + gosterim               6      0.8313      0.8037      +0.0504
elle cikarilmis dokuz          9      0.8709      0.8594      +0.1061

Üç satır üç ayrı bilgi kaynağını temsil ediyor. Yalnız abone kaydıyla tabanın 0,0318 üstüne çıkılıyor. Vekil görevin ürettiği üç sayı eklendiğinde fark 0,0504’e yükseliyor; katkı 0,0186 ve bu katkı için hiç etiket harcanmadı. Elle çıkarılmış dokuz öznitelik ise hâlâ 0,1061 vermektedir — kendi kendine denetim alan bilgisinin yerine geçmemiş, açığın altıda birini kapatmıştır.

Etiket muhasebesi de yazılır. Vekil görevin modeli yalnız eğitim kümesinin okumalarıyla kurulmuştur; ayrılmış kümedeki 377 abonenin hiçbir satırı katsayıların hesabına girmemiştir. Asıl görevde her üç satır da aynı 883 etiketi kullanır, yani satırlar arasındaki fark etiket sayısından değil yalnız öznitelik kümesinden gelir. Gösterimin bedeli sıfır etikettir ve bu, onu elle çıkarılmış dokuz öznitelikten ayıran şeydir: o dokuz sütunu yazmak için birinin tüketim serisine bakıp hangi özetin işe yarayacağına karar vermesi gerekmiştir.

Katkı Nereden Geliyor

Buraya kadar okunan tablo şunu söylüyor gibi durur: vekil görev bir şey öğrendi ve öğrendiği şey asıl göreve taşındı. Bu iddia sınanabilir, çünkü vekil görevin taban çizgisi de bir gösterim üretir. Kestirim yerine genel ortalama konur, aynı üç sayı yeniden hesaplanır ve aynı yerde ölçülür. Öğrenilmiş hiçbir şey taşımayan bu gösterim, öğrenilenin ne kadarının gerçekten öğrenmeden geldiğini gösterir.

# denetim.py — vekil gorevin taban cizgisi de bir gosterim uretir: kestirim
# yerine genel ortalama konur. Iki gosterim ayni yerde karsilastirilir.
for a in ABONE:
    a["beklenen_t"], a["sapma_t"] = GENEL, a["seri"][-1] - GENEL
    a["bagil_sapma_t"] = (a["seri"][-1] - GENEL) / (GENEL + 1.0)
TABAN_GOSTERIM = ["beklenen_t", "sapma_t", "bagil_sapma_t"]
print("oznitelik kumesi".ljust(28) + "kac".rjust(4) + "egitimde".rjust(12)
      + "ayrilmista".rjust(12) + "tabana gore".rjust(13))
olc("kayit", KAYIT)
olc("kayit + taban gosterimi", KAYIT + TABAN_GOSTERIM)
olc("kayit + ogrenilen gosterim", KAYIT + GOSTERIM)
oznitelik kumesi             kac    egitimde  ayrilmista  tabana gore
kayit                          3      0.7939      0.7851      +0.0318
kayit + taban gosterimi        6      0.8301      0.8064      +0.0531
kayit + ogrenilen gosterim     6      0.8313      0.8037      +0.0504

İddia çürüdü. Taban çizgisinden kurulan gösterim 0,8064, öğrenilen gösterim 0,8037 veriyor; öğrenilmiş kısmın katkısı 0,0027 eksidir. Asıl göreve gerçekten katkı yapan şey vekil görevin öğrendiği ilişki değil, gösterimin yanında taşıdığı ham gözlemdir. Genel ortalama sabit olduğu için ikinci satırdaki üç sütun aslında son okumanın üç ayrı yazılışıdır ve karar ağacına yeni bir sütun olarak son okumayı vermek, katkının tamamını açıklamaktadır.

Bunun sonucu müfredat düzeyindedir. Vekil görevde kazanılan 0,4115 m³, asıl görevde kazanılan sayı değildir. İki görevin iki ayrı ölçüsü, iki ayrı taban çizgisi ve iki ayrı sonucu vardır; birinde tabanı geçmek diğerinde tabanı geçmeyi getirmez. Bir vekil görevin işe yaradığını söylemek için kendi ölçüsündeki kazancı değil, asıl görevde tabanın gösterimi üzerine kattığı farkı yazmak gerekir.

Kurgu kümenin niçin böyle davrandığı da yazılabilir. Bu kümede aynı abonenin dönemleri birbirinden büyük ölçüde bağımsız üretilir; bir dönemin okuması sonrakini zayıf belirler ve önceki ortalamanın katsayısı 0,2620’de kalır. Zamanla güçlü biçimde bağlı bir kümede aynı vekil görev başka bir sayı verirdi. Ölçülen şey yöntemin kendisi değil, yöntemin bu veri üzerindeki katkısıdır.

Özet

  • Kendi kendine denetimli kurulumda etiket dışarıdan gelmez, veriden türetilir: son okuma gizlenir ve önceki okumalardan kestirilir.
  • Vekil görev kendi ölçüsünde tabanı geçiyor: ayrılmış kümede ortalama mutlak hata 6,3776 m³’ten 5,9661 m³’e iniyor, kazanç 0,4115 m³ ve harcanan etiket sıfır.
  • Vekil görevin ürettiği üç sayı asıl göreve taşındığında yalnız kayıt öznitelikleriyle ölçülen 0,7851 sayısı 0,8037’ye çıkıyor; elle çıkarılmış dokuz öznitelik ise 0,8594 veriyor.
  • Aynı gösterim vekil görevin taban çizgisinden kurulduğunda 0,8064 çıkıyor: öğrenilmiş kısmın katkısı 0,0027 eksidir ve fark taşınan ham gözlemden gelmektedir.
  • Vekil görevde tabanı geçmek asıl görevde tabanı geçmeyi getirmez; iki görevin iki ayrı ölçüsü ve iki ayrı tabanı vardır.

Sonraki Adım

Üç derste tek bir soru soruldu: bu abone şüpheli mi. Soru ikili olduğu için taban çizgisi de hep aynı kaldı — en sık sınıfı söylemek. Oysa aynı tablo başka soruları da kaldırır: bu abonenin gelecek dönem tüketimi kaç metreküp olacak, aboneler kaç doğal öbeğe ayrılıyor, sahaya bugün çıkacak ekip hangi yüz aboneyi hangi sırayla gezmeli. Sonraki ders aynı veriye dört ayrı soru sorar ve her sorunun kendi taban çizgisini ayrı ayrı seçer: sınıflandırma, bağlanım, kümeleme ve sıralama için dört ayrı öğrenmeyen yordam yazılır, seçimlerinin gerekçesi kaydedilir ve dört tabanın dört ayrı sayı verdiği gösterilir.

İ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