İçeriğe geç
academia.sh

Ders 10 / 13

Model Denetlenebilirliği

Üretilmiş tek bir tahminin nedenine aylar sonra ulaşılabilmesinin karar kaydı varken ve yokken ayrı ayrı sayılması: karar kaydıyla bir tahminin modeli, karar eşiği, öznitelik değerleri ve puanı tek satırda okunur ve tahmin başına 1,00 satır düşer. Kayıt olmadığında aynı iki yüz tahmin için 84.740 satır okunur, tahmin başına 423,70 eder ve buna karşın 189 tahminin hangi modelden geldiği belirlenemez, çünkü kanarya döneminde iki model tahminlerin 189'unda aynı şeyi söyler. Kaydın bedeli altı dönem için 12.000 saklanan alandır ve kaynak okumalarının 0,8333 katıdır.

İçindekiler

Üç derste model gölgede ölçüldü, kanaryaya verildi, deneyle karşılaştırıldı ve yeniden eğitildi. Her adımda ortaya yeni bir ağırlık, yeni bir karar eşiği ve yeni bir eğitim penceresi çıktı. Sorulmayan tek şey, 2026-12 döneminde tek bir aboneye verilmiş tek bir tahminin aylar sonra kime sorulacağıdır: hangi model üretti, hangi öznitelik değerleriyle, hangi karar eşiğiyle.

Bu soru modelin yorumlanabilirliğinden ayrıdır. Bir modelin kararını hangi özniteliğin sürüklediği, alt gruplarda nasıl davrandığı ve nasıl açıklanacağı Model Değerlendirme, Yorumlanabilirlik ve Etik kursunda ölçüldü ve burada tekrarlanmaz. Buradaki soru üretimin sorusudur: hangi modelin koştuğu. Yorumlanabilirlik elde model varken çalışır; denetim izi (audit trail) ise modelin hangisi olduğunu söyleyen kaydın kendisidir. Bu ders o kaydı kurar, olmadığında yapılan aramayı sayar ve kaydın bedelini yazar.

  • MY31. Kaynak, hat, model ve yayın kurgudur; hiçbir model kayıt defteri, izleme ürünü ya da dağıtım aracı çağrılmaz. Tohum 20260218.
  • MY32. Etiket abone_ort + 6 x isyeri > 30 kuralına bağlıdır, karar eşiği ayrı bir ayardır. İzleme dönemlerinde taban sınıf oranı 0,5342, dönem başına 200 satır, isabetin adımı 0,0050.
  • MY33. Denetlenen dönem 2026-12’dir ve o dönemde iki model açıktır: eski model ile kanarya payı 0,10 ile yayılan aday.
  • MY34. Karar kaydı her tahmin için tek satırdır ve on alan taşır: dönem, abone, model, ağırlık, karar eşiği, üç öznitelik değeri, puan ve tahmin.
  • MY35. Arama bedeli okunan satır olarak sayılır; ham süre yazılmaz. Kayıtsız arama yayın kaydından 2 satır, ardından özniteliği yeniden hesaplamak için ham satırları okur.
  • MY36. Saklama bedeli alan olarak sayılır: kayıt sayısı çarpı alan sayısı.

Karar Kaydı Neyi Taşır

İlk blok kurulumu kurar, 2026-12 yayınını kanarya payı 0,10 ile koşturur ve her tahmin için bir karar kaydı üretir.

# KURGUDUR. Olcum aginin sayac okumalari , hattin tuketim asamasi , oznitelik
# yolu ve uc agirlikli esik modeli ders icinde uretilir; hicbir ogrenme
# kitapligi , dagitim araci , deney platformu ya da izleme urunu cagrilmaz.
# Tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def satirlar():
    """Kaynak okumalari ve donem farkindan tuketim: hattin ilk uc asamasi."""
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e})
    t = {(k["abone"], k["donem"]): k["endeks"] for k in kayit}
    return [dict(k, m3=k["endeks"] - t[(k["abone"], DONEM[DONEM.index(k["donem"]) - 1])])
            for k in kayit if DONEM.index(k["donem"])]


def oznitelikler(kayitlar):
    """Agirliktan bagimsizdir ve BIR KEZ hesaplanir; tam gecmisi gorur."""
    ab, bo = {}, {}
    for k in sorted(kayitlar, key=lambda k: DONEM.index(k["donem"])):
        ab.setdefault(k["abone"], []).append((DONEM.index(k["donem"]), k["m3"]))
        bo.setdefault(k["bolge"], []).append((DONEM.index(k["donem"]), k["m3"]))

    def ort(dizi, i):
        s = [v for d, v in dizi if d < i]
        return round(sum(s) / len(s), 4) if s else 0.0

    return {(k["abone"], k["donem"]): {
        "abone_ort": ort(ab[k["abone"]], DONEM.index(k["donem"])),
        "bolge_ort": ort(bo[k["bolge"]], DONEM.index(k["donem"])),
        "isyeri": 1 if k["tip"] == "isyeri" else 0} for k in kayitlar}


KURAL_ESIK, KURAL_ISYERI = 30, 6          # etiketi ureten KURAL , yani kavram
IZLEME = DONEM[6:]                        # uretimde izlenen alti donem
IZGARA = [(a, b, c) for a in (0.6, 0.8, 1.0) for b in (0.0, 0.2, 0.4) for c in (0, 4, 8)]
KARAR_IZGARA = (18, 22, 26, 30, 34)       # karar esigi AYRI bir ayardir


def etiket(o, esik=KURAL_ESIK):
    return 1 if o["abone_ort"] + KURAL_ISYERI * o["isyeri"] > esik else 0


def puan(o, w):
    return w[0] * o["abone_ort"] + w[1] * o["bolge_ort"] + w[2] * o["isyeri"]


def tahmin(o, w, karar):
    return 1 if puan(o, w) > karar else 0


def dengeli_isabet(kume, oz, w, karar):
    """Egitim olcutu: duyarlilik ile ozgullugun ortalamasi."""
    dp = dn = yp = yn = 0
    for k in kume:
        o = oz[(k["abone"], k["donem"])]
        t, g = tahmin(o, w, karar), etiket(o)
        if t and g:
            dp += 1
        elif t:
            yp += 1
        elif g:
            yn += 1
        else:
            dn += 1
    du = dp / (dp + yn) if dp + yn else 0.0
    oz_ = dn / (dn + yp) if dn + yp else 0.0
    return (du + oz_) / 2, round(du, 4), round(oz_, 4)


def egit(kayitlar, oz, donemler):
    """Agirlik ve karar esigi birlikte aranir: 27 x 5 = 135 aday."""
    kume = [k for k in kayitlar if k["donem"] in donemler]
    sirali = sorted(((dengeli_isabet(kume, oz, w, kr)[0], w, kr)
                     for w in IZGARA for kr in KARAR_IZGARA), key=lambda a: -a[0])
    en = sirali[0]
    return {"agirlik": en[1], "karar": en[2], "dengeli": round(en[0], 4),
            "sirali": sirali, "satir": len(kume)}


def kaydir(kayitlar, baslangic="2026-09", egim=0.06):
    """KURGU veri kaymasi: isyeri tuketimi her donem `egim` kadar buyuyor."""
    b = DONEM.index(baslangic)
    return [dict(k, m3=round(k["m3"] * (1.0 + egim * (DONEM.index(k["donem"]) - b + 1)), 4))
            if DONEM.index(k["donem"]) >= b and k["tip"] == "isyeri" else dict(k)
            for k in kayitlar]


TUM = satirlar()
OZ = oznitelikler(TUM)
TABAN = egit(TUM, OZ, DONEM[1:9])
URETIM = kaydir(TUM)                      # uretimde girdi kaymis durumda
OZU = oznitelikler(URETIM)
d, du, oz_ = dengeli_isabet([k for k in TUM if k["donem"] in DONEM[1:9]], OZ,
                            TABAN["agirlik"], TABAN["karar"])
izl = [k for k in TUM if k["donem"] in IZLEME]
e = [etiket(OZ[(k["abone"], k["donem"])]) for k in izl]
print(f"taban model {TABAN['agirlik']} karar esigi {TABAN['karar']}"
      f" dengeli isabet {TABAN['dengeli']} duyarlilik {du:.4f} ozgulluk {oz_:.4f}")
print(f"izleme {len(izl)} satir , taban sinif orani {round(1 - sum(e) / len(e), 4)}"
      f" , donem basina 200 satir , isabetin adimi 0.0050")


# Bu blok ilk bloktaki TUM , OZ , URETIM , OZU , TABAN , IZLEME , DONEM ,
# ABONE , etiket , puan ve tahmin tanimlarini surdurur.
ADAY = {"ad": "aday", "agirlik": (0.8, 0.4, 4), "karar": 34}
ESKI = dict(TABAN, ad="eski")
PAY, SON = 0.10, "2026-12"
son = [k for k in URETIM if k["donem"] == SON]
N_KAN = int(len(son) * PAY)
ALAN = ("donem", "abone", "model", "agirlik", "karar_esigi", "abone_ort",
        "bolge_ort", "isyeri", "puan", "tahmin")


def karar_kaydi(kume, oz, n_kanarya):
    """Her tahmin icin tek satir: hangi model , hangi oznitelik , hangi esik."""
    kayit = {}
    for j, k in enumerate(kume):
        o = oz[(k["abone"], k["donem"])]
        m = ADAY if j < n_kanarya else ESKI
        kayit[(k["abone"], k["donem"])] = dict(
            zip(ALAN, (k["donem"], k["abone"], m["ad"], m["agirlik"], m["karar"],
                       o["abone_ort"], o["bolge_ort"], o["isyeri"],
                       round(puan(o, m["agirlik"]), 4),
                       tahmin(o, m["agirlik"], m["karar"]))))
    return kayit


KAYIT = karar_kaydi(son, OZU, N_KAN)
ayrisan = [k["abone"] for k in son
           if tahmin(OZU[(k["abone"], SON)], ESKI["agirlik"], ESKI["karar"])
           != tahmin(OZU[(k["abone"], SON)], ADAY["agirlik"], ADAY["karar"])]
print(f"{SON} yayini: eski {ESKI['agirlik']}/{ESKI['karar']} ,"
      f" aday {ADAY['agirlik']}/{ADAY['karar']} , kanarya payi {PAY}")
print(f"istek {len(son)} , kanaryaya giden {N_KAN} ,"
      f" iki modelin ayristigi tahmin {len(ayrisan)}")
print("karar kaydi alanlari:", " ".join(ALAN))
print("ornek:", " ".join(str(v) for v in KAYIT[("A001", SON)].values()))
taban model (0.6, 0.0, 4) karar esigi 18 dengeli isabet 0.9864 duyarlilik 1.0000 ozgulluk 0.9728
izleme 1200 satir , taban sinif orani 0.5342 , donem basina 200 satir , isabetin adimi 0.0050
2026-12 yayini: eski (0.6, 0.0, 4)/18 , aday (0.8, 0.4, 4)/34 , kanarya payi 0.1
istek 200 , kanaryaya giden 20 , iki modelin ayristigi tahmin 11
karar kaydi alanlari: donem abone model agirlik karar_esigi abone_ort bolge_ort isyeri puan tahmin
ornek: 2026-12 A001 aday (0.8, 0.4, 4) 34 35.502 27.6233 1 43.4509 1

Örnek satır tek başına bir açıklamadır: A001 abonesinin 2026-12 tahmini aday model tarafından, (0.8, 0.4, 4) ağırlığı ve 34 karar eşiğiyle üretilmiştir; abone ortalaması 35,502, bölge ortalaması 27,6233, abone tipi işyeri ve puan 43,4509’dur. Puan eşiği aştığı için tahmin 1’dir. Kayıt hiçbir yeniden hesap gerektirmez ve hangi modelin koştuğunu söyler.

Kayıt Olmadan Yapılan Arama

İkinci blok aynı iki yüz tahmini kayıtsız durumda arar: yayın kaydından o dönemde açık olan iki model bulunur, öznitelikler ham satırlardan yeniden hesaplanır ve gözlenen tahminle hangi modellerin uyuştuğu sayılır.

# Bu blok ikinci bloktaki KAYIT , ALAN , ESKI , ADAY , son , SON , N_KAN ,
# URETIM , OZU , ABONE ve DONEM tanimlarini surdurur.
def arama_kayitsiz(abone, donem, kayitlar, tahmini):
    """Kayit yoksa: yayin kaydindan modeller , ham satirlardan oznitelikler."""
    i, b = DONEM.index(donem), ABONE[abone]["bolge"]
    ab = [k["m3"] for k in kayitlar if k["abone"] == abone and DONEM.index(k["donem"]) < i]
    bo = [k["m3"] for k in kayitlar if k["bolge"] == b and DONEM.index(k["donem"]) < i]
    o = {"abone_ort": round(sum(ab) / len(ab), 4), "bolge_ort": round(sum(bo) / len(bo), 4),
         "isyeri": 1 if ABONE[abone]["tip"] == "isyeri" else 0}
    uyan = [m["ad"] for m in (ESKI, ADAY) if tahmin(o, m["agirlik"], m["karar"]) == tahmini]
    return 2 + len(ab) + len(bo), uyan          # 2 satir yayin kaydi + ham satirlar


ok_k = ok_s = tek_k = tek_s = 0
for k in son:
    kd = KAYIT[(k["abone"], SON)]
    ok_k, tek_k = ok_k + 1, tek_k + 1           # kayitli arama: tek satir , tek model
    o, uyan = arama_kayitsiz(k["abone"], SON, URETIM, kd["tahmin"])
    ok_s, tek_s = ok_s + o, tek_s + (len(uyan) == 1)
print("arama                okunan satir  tahmin basina  modeli belirlenen  belirlenemeyen")
for ad, ok, tek in (("karar kaydi ile", ok_k, tek_k), ("karar kaydi olmadan", ok_s, tek_s)):
    print(f"{ad:<20} {ok:>12}  {ok / len(son):>13.2f}  {tek:>17}  {len(son) - tek:>14}")

esik_asan = sum(1 for c, kd in KAYIT.items() if kd["tahmin"] == 1)
isyeri_belirleyici = sum(1 for c, kd in KAYIT.items() if kd["tahmin"] == 1
                         and kd["puan"] - kd["agirlik"][2] * kd["isyeri"] <= kd["karar_esigi"])
print(f"\nkarar kaydindan okunan neden: esigi asan tahmin {esik_asan} , bunlarin"
      f" {isyeri_belirleyici} tanesinde abone tipi tek basina belirleyici")
kayit_sayisi = len(IZLEME) * len(son)
kaynak_alan = len(ABONE) * len(DONEM) * 6
print(f"alti izleme donemi kaydedilseydi: {kayit_sayisi} kayit x {len(ALAN)} alan ="
      f" {kayit_sayisi * len(ALAN)} saklanan alan")
print(f"    kaynak okumasi {len(ABONE) * len(DONEM)} satir x 6 alan = {kaynak_alan} alan")
print(f"    karar kaydinin kaynaga orani {kayit_sayisi * len(ALAN) / kaynak_alan:.4f}")
arama                okunan satir  tahmin basina  modeli belirlenen  belirlenemeyen
karar kaydi ile               200           1.00                200               0
karar kaydi olmadan         84740         423.70                 11             189

karar kaydindan okunan neden: esigi asan tahmin 109 , bunlarin 57 tanesinde abone tipi tek basina belirleyici
alti izleme donemi kaydedilseydi: 1200 kayit x 10 alan = 12000 saklanan alan
    kaynak okumasi 2400 satir x 6 alan = 14400 alan
    karar kaydinin kaynaga orani 0.8333

Okunan satır sütunu beklenen farkı verir: karar kaydıyla tahmin başına 1,00, kayıt olmadan 423,70 satır. Aradaki dört yüz kat, öznitelik yolunun kapsamından gelir; bolge_ort tek bir abone için hesaplanamaz, bölgedeki bütün abonelerin geçmişini ister. Bu kadarı bir maliyet farkıdır ve yeterince veri okunursa kapanır.

Son iki sütun kapanmayanı gösterir. Karar kaydıyla 200 tahminin 200’ü tek bir modele bağlanır. Kayıtsız aramada bu sayı 11‘e düşer ve 189 tahminin hangi modelden geldiği belirlenemez. Nedeni tabloda yazılıdır: kanarya döneminde iki model 200 tahminin **189’unda aynı şeyi söyler**, dolayısıyla gözlenen çıktı ikisiyle de uyuşur. Yeniden hesap özniteliği geri getirir ama hangi modelin koştuğu bilgisini geri getirmez; o bilgi ölçülebilir bir izin değil, yazılmış bir kaydın ürünüdür.

Buradaki ters durum kayda değer. Kayıtsız aramanın çözebildiği tek grup, iki modelin ayrıştığı 11 tahmindir — yani denetimin kendiliğinden çalıştığı yer, adayın eski modelden gerçekten ayrıldığı yerdir. Kanaryanın küçük payları tam da bu ayrışmayı azaltmak için seçilir. Riski küçülten aynı seçim, geriye dönük denetlenebilirliği de küçültür; ilk derste ölçünün çözünürlüğüyle yaşanan takas burada denetimle yeniden karşımıza çıkar.

Bu iki tahminin açıklaması aynı değildir. Aynı çıktıyı veren iki model farklı ağırlık, farklı karar eşiği ve farklı puan taşır; hangisinin geçerli olduğu seçilemediğinde ortada bir açıklama değil, iki uyumsuz aday açıklama vardır. Bir itiraz geldiğinde verilecek yanıt bu ikisinden biri olamaz.

Kaydın kendisi bedavaya gelmez. Altı izleme döneminin tamamı kaydedilseydi 1200 kayıt ve 12.000 saklanan alan eder; kaynak okumalarının 0,8333 katı, yani hattın taşıdığı ham verinin neredeyse tamamı kadar bir yük. Karşılığında kayıt yalnız modeli değil nedeni de tek geçişte verir: eşiği aşan 109 tahminin 57’sinde abone tipi tek başına belirleyicidir, yani puandan işyeri katkısı çıkarıldığında eşik aşılmaz. Bu sayı kayıttaki puan ile isyeri alanlarından okunur; kayıtsız durumda aynı sayı için 84.740 satır yeniden okunması gerekir ve sonucun 189 tahminde hangi modele ait olduğu yine bilinemez.

Özet

  • Karar kaydı bir tahmini on alanda bağlar: model, ağırlık, karar eşiği, üç öznitelik değeri, puan ve tahmin. Tahmin başına okunan satır 1,00.
  • Kayıtsız arama aynı iki yüz tahmin için 84.740 satır okur, tahmin başına 423,70 eder ve buna karşın 189 tahminin modeli belirlenemez; belirlenebilen 11 tahmin, iki modelin ayrıştığı tahminlerdir.
  • Yeniden hesap özniteliği geri getirir, hangi modelin koştuğunu getirmez. Yorumlanabilirlik elde model varken çalışır; denetim izi modelin hangisi olduğunu söyleyen yazılmış kayıttır ve kaydedilmemişse üretilemez.
  • Kanaryanın küçük payı ayrışmayı azalttığı için riski küçülten seçim geriye dönük denetlenebilirliği de küçültür; aynı çıktıyı veren iki model farklı puan ve farklı eşik taşır, dolayısıyla belirlenemeyen tahminin bir değil iki uyumsuz açıklaması vardır.
  • Kaydın bedeli altı dönem için 12.000 saklanan alandır ve kaynak okumalarının 0,8333 katıdır. Karşılığında neden tek geçişte okunur: eşiği aşan 109 tahminin 57’sinde abone tipi tek başına belirleyicidir. Taban sınıf oranı 0,5342 ve isabetin adımı 0,0050.

Sonraki Adım

Dört derste model yayına alındı, karşılaştırıldı, yeniden eğitildi ve ürettiği her tahmin kaydedildi. Bütün bu ölçüler içeriye dönüktür: ekibin kendi kararını verebilmesi için tutulmuştur. Sorulmayan şey, aynı düzeneğin dışarıya karşı ne borçlu olduğudur — bir kararın gerekçesinin istenmesi, bir tahmine itiraz edilmesi, bir kaydın belirli bir süre saklanmasının beklenmesi. Sonraki ders bu beklentileri sınıflarıyla sayar ve her sınıfın mühendislik karşılığını yazar: kaç ek alan, kaç saklanan kayıt ve hangilerinin bu derste kurulan karar kaydıyla zaten karşılandığı.

İ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