İçeriğe geç
academia.sh

Ders 03 / 13

Başarım İzleme

Gerçek etiketin tahminle aynı anda gelmediği bir üretim kurulumunda başarımın ne zaman bilinebildiğinin ölçülmesi: bir dönemin isabeti ancak iki dönem sonra hesaplanabildiği için kavram kaymasının 2026-09'da düşürdüğü isabet ilk kez 2026-11'de görülebiliyor ve bu boşlukta 400 tahmin ölçülmeden üretiliyor. 2026-09'da gerçek isabet 0,8150 iken elde olan en yeni ölçü 2026-07'nin 0,9700'ü oluyor, yani gösterge yanlış değil eski. Gecikme süpürmesi bedeli doğrusal veriyor: 0 dönem gecikmede bozulma aynı dönemde görülüyor ve ölçülmeden üretilen tahmin 0, 1 dönemde 200, 2 dönemde 400, 3 dönemde 600, 4 dönemde bozulma izleme penceresi içinde hiç görülmüyor; etiket hiç toplanmadığında ölçülebilen dönem sayısı 0 ve bozulma hiçbir zaman görülmüyor.

İçindekiler

İki derste ortaya çıkan sonuç şuydu: kavram kaymasını gören tek gösterge isabettir. Girdi özeti kuralın kaydığından habersizdir, tahmin payı zararsız kaymada ateşleyip zararlı kaymada susar, isabet ise 0,9700’den 0,8150’ye düşerek bozulmayı adıyla gösterir.

Bu bulgunun sessizce yaptığı bir varsayım var. İsabet hesaplanabilmesi için satırın gerçekten yüksek olup olmadığının bilinmesi gerekir ve önceki iki derste bu bilgi hep elde varmış gibi davranıldı. Üretimde öyle değildir: tahmin dönem başında üretilir, gerçek etiket ise sayaç okunduktan, itiraz süresi geçtikten ve kayıt kapandıktan sonra gelir. Bu ders o gecikmeyi kurulumun içine koyar ve tek bir soruyu ölçer: hangi dönemin isabeti hangi dönemde bilinebiliyor.

  • MI16. Kaynak, hat, model ve kavram kayması kurgudur; gerçek bir öğrenme kitaplığı, izleme ürünü ya da bulut servisi çağrılmaz. Tohum 20260218.
  • MI17. Gecikmeli etiket (delayed label) gerçek etiketin tahminden sonra gelmesidir. Burada gecikme GECIKME = 2 dönemdir: bir dönemin isabeti ancak iki dönem sonra hesaplanabilir. Süre ham birimle değil, dönem olarak yazılır.
  • MI18. Yakalama gecikmesi (detection delay) bozulmanın olduğu dönem ile ilk kez görülebildiği dönem arasındaki farktır. Bir göstergenin kaç dönem sonra gösterdiği ölçüsü Veri Hatları ve Orkestrasyon kursunda kuruldu; burada tekrarlanmaz, girdi olarak alınır.
  • MI19. Bozulma kaynağı önceki dersin kavram kaymasıdır: 2026-09‘dan sonra yüksek sayılma eşiği 30’dan 27’ye iner. Girdi tarafında değişen değer yoktur.
  • MI20. İzleme dönemleri 2026-07…2026-12, dönem başına 200 satır, toplam 1200. İzleme dönemlerinde taban sınıf oranı 0,5342; küme dengelidir.
  • MI21. Uyarı bandı 0,05’tir ve taban 2026-07’nin isabeti olan 0,9700’dür. Bant iki yönlüdür.
  • MI22. Taban çizgisi izlemesiz kurulumdur: etiket hiç toplanmaz, ölçülebilen dönem 0, bozulma görülmez.
  • MI23. Çözünürlük: dönem isabetinin adımı 1/200 = 0,0050; kavram kaymasının düşürdüğü 0,1550, yani otuz bir adım ve bandın çok üstünde. Gecikme dönem olarak sayılır ve bir dönem 200 tahmin demektir.

Etiket İki Dönem Sonra

İlk blok önceki iki dersin kurulumunu kurar ve üstüne tek bir şey ekler: gorulen_donem. Bu işlev bir dönemin isabetinin verili anda hesaplanabilir olup olmadığını söyler; hesabın kendisi değişmez, yalnız ne zaman yapılabildiği değişir.

# KURGUDUR. Olcum aginin sayac okumalari, hattin modele bakan ilk uc asamasi,
# esik tabanli model, kavram kaymasi ve etiket gecikmesi ders icinde tanimlanir;
# gercek bir ogrenme kitapligi, izleme urunu ya da bulut servisi cagrilmaz.
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 kaynak_uret():
    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, "birim": "m3"})
    return kayit


def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    """Donem farkindan tuketim. Onceki donem yoksa satir hesaplanamaz."""
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        cikti.append(dict(k, m3=int(k["endeks"]) - int(onceki["endeks"])))
    return cikti, dusen


def satirlar():
    v, _ = a1_ayikla(kaynak_uret())
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    return v


def oznitelikler(kayitlar, basamak=4):
    """Oznitelik agirliktan bagimsizdir; tam gecmisten BIR KEZ hesaplanir."""
    sirali = sorted(kayitlar, key=lambda k: DONEM.index(k["donem"]))
    ab, bo = {}, {}
    for k in sirali:
        ab.setdefault(k["abone"], []).append((DONEM.index(k["donem"]), k["m3"]))
        bo.setdefault(k["bolge"], []).append((DONEM.index(k["donem"]), k["m3"]))

    def ortalama(dizi, i):
        secili = [v for d, v in dizi if d < i]
        return round(sum(secili) / len(secili), basamak) if secili else 0.0

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


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)]


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


KURAL_ESIK = 30
KURAL_ISYERI = 6


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


IZLEME = DONEM[6:]                    # 2026-07 .. 2026-12 : uretimde izlenen donemler
KARAR_IZGARA = (18, 22, 26, 30, 34)   # karar esigi ETIKET esiginden AYRI bir ayardir


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


def dengeli_isabet(kume, oz, w, karar, kural=None):
    c = {(0, 0): 0, (0, 1): 0, (1, 0): 0, (1, 1): 0}
    for k in kume:
        o_k = oz[(k["abone"], k["donem"])]
        c[(tahmin(o_k, w, karar), kural(k, o_k) if kural else etiket(o_k))] += 1
    du = c[(1, 1)] / max(c[(1, 1)] + c[(0, 1)], 1)      # duyarlilik
    oz_ = c[(0, 0)] / max(c[(0, 0)] + c[(1, 0)], 1)     # ozgulluk
    return {"isabet": (c[(1, 1)] + c[(0, 0)]) / len(kume), "duyarlilik": du, "ozgulluk": oz_,
            "dengeli": (du + oz_) / 2, "agirlik": w, "karar": karar}


def egit(kayitlar, oz, donemler=None, kural=None):
    """Egitim = agirlik ucLUsu ILE karar esigini birlikte aramak: 27 x 5 = 135 aday."""
    kume = [k for k in kayitlar if k["donem"] in (donemler or DONEM[1:9])]
    return max((dengeli_isabet(kume, oz, w, karar, kural)
                for w in IZGARA for karar in KARAR_IZGARA), key=lambda o: o["dengeli"])


def isabet(kayitlar, model, oz, donem, etiketler=None):
    """etiketler=None -> kural degismemis demektir."""
    kume = [k for k in kayitlar if k["donem"] == donem]
    d = 0
    for k in kume:
        o_k = oz[(k["abone"], k["donem"])]
        g = etiketler[(k["abone"], k["donem"])] if etiketler else etiket(o_k)
        d += tahmin(o_k, model["agirlik"], model["karar"]) == g
    return round(d / len(kume), 4)


# ---- KURGU kavram kaymasi (onceki ders): GIRDI AYNI KALIR , kural degisir.
def kavram_kaydir(kayitlar, oz, baslangic="2026-09", yeni_esik=27):
    b = DONEM.index(baslangic)
    return {(k["abone"], k["donem"]):
            etiket(oz[(k["abone"], k["donem"])],
                   yeni_esik if DONEM.index(k["donem"]) >= b else KURAL_ESIK)
            for k in kayitlar}


GECIKME = 2                  # bir donemin etiketi kac donem sonra eline geciyor


def gorulen_donem(donem, simdi, gecikme=GECIKME):
    """Bir donemin isabeti ancak `gecikme` donem sonra hesaplanabilir."""
    return DONEM.index(donem) + gecikme <= DONEM.index(simdi)


S = satirlar()
OZ = oznitelikler(S)
MODEL = egit(S, OZ)
YENI = kavram_kaydir(S, OZ)
IZL = [k for k in S if k["donem"] in IZLEME]
dag = {0: 0, 1: 0}
for k in IZL:
    dag[etiket(OZ[(k["abone"], k["donem"])])] += 1
GERCEK = {d: isabet(S, MODEL, OZ, d, YENI) for d in IZLEME}
print("izleme satiri:", len(IZL), " donem basina:", len(IZL) // len(IZLEME),
      " taban sinif orani:", round(dag[0] / len(IZL), 4), " gecikme:", GECIKME, "donem")
print("gercek isabet:", [f"{GERCEK[d]:.4f}" for d in IZLEME])
izleme satiri: 1200  donem basina: 200  taban sinif orani: 0.5342  gecikme: 2 donem
gercek isabet: ['0.9700', '0.9700', '0.8150', '0.8700', '0.8650', '0.8500']

GERCEK sözlüğü, sonradan bakan birinin görebileceği isabet dizisidir. Üretimde duran biri bu dizinin tamamını hiçbir zaman elinde tutmaz; her dönemde onun yalnız bir önekini görür.

Hangi Dönemin İsabeti Hangi Dönemde Bilinir

İkinci blok her dönem için üretimdeki tabloyu kurar: o anda ölçülebilen en yeni dönem, o dönemin isabeti, o andaki gerçek isabet ve elde olup henüz ölçülmemiş tahmin sayısı. Üçüncü sütun bir gözlemcinin değil, sonradan bakanın bilgisidir; üretimde duran kişi ikinci sütuna bakar.

BANT, TABAN = 0.05, GERCEK[IZLEME[0]]
print(f"{'simdi':<10}{'olculebilen son donem':>22}{'o donemin isabeti':>19}"
      f"{'simdiki gercek isabet':>23}{'olculmemis tahmin':>19}")
for simdi in IZLEME:
    olculen = [d for d in IZLEME if gorulen_donem(d, simdi)]
    uretilen = IZLEME[: IZLEME.index(simdi) + 1]
    son = olculen[-1] if olculen else None
    print(f"{simdi:<10}{(son or '-'):>22}"
          f"{(f'{GERCEK[son]:.4f}' if son else '-'):>19}{GERCEK[simdi]:>23.4f}"
          f"{(len(uretilen) - len(olculen)) * 200:>19}")

BOZULAN = next(d for d in IZLEME if abs(GERCEK[d] - TABAN) / TABAN > BANT)
GORULEN = next(s for s in IZLEME
               if any(gorulen_donem(d, s) and abs(GERCEK[d] - TABAN) / TABAN > BANT
                      for d in IZLEME))
print("\nbozulmanin oldugu donem:", BOZULAN, " uyarinin atesleyebildigi donem:", GORULEN,
      " gorulme gecikmesi:", DONEM.index(GORULEN) - DONEM.index(BOZULAN), "donem")
BOSLUK = IZLEME[IZLEME.index(BOZULAN):IZLEME.index(GORULEN)]
print("bu boslukta olculmeden uretilen tahmin:", len(BOSLUK) * 200,
      " bosluktaki donemler:", BOSLUK)
print("bunlarin sonradan yanlis oldugu anlasilan sayisi:",
      sum(round((1 - GERCEK[d]) * 200) for d in BOSLUK),
      " kural degismeseydi olacak sayi:",
      sum(round((1 - isabet(S, MODEL, OZ, d)) * 200) for d in BOSLUK))
simdi      olculebilen son donem  o donemin isabeti  simdiki gercek isabet  olculmemis tahmin
2026-07                        -                  -                 0.9700                200
2026-08                        -                  -                 0.9700                400
2026-09                  2026-07             0.9700                 0.8150                400
2026-10                  2026-08             0.9700                 0.8700                400
2026-11                  2026-09             0.8150                 0.8650                400
2026-12                  2026-10             0.8700                 0.8500                400

bozulmanin oldugu donem: 2026-09  uyarinin atesleyebildigi donem: 2026-11  gorulme gecikmesi: 2 donem
bu boslukta olculmeden uretilen tahmin: 400  bosluktaki donemler: ['2026-09', '2026-10']
bunlarin sonradan yanlis oldugu anlasilan sayisi: 63  kural degismeseydi olacak sayi: 7

Bozulmanın olduğu dönem 2026-09‘dur ve o dönemde ekranda duran sayı 0,9700‘dür. Bu sayı yanlış değildir; 2026-07‘nin isabeti gerçekten 0,9700’dü. Sayı yalnızca eskidir ve eskiliği hiçbir yerde yazmıyorsa yanlıştan ayırt edilemez. Bir sonraki dönemde de aynı şey olur: gerçek isabet 0,8700’e inmişken elde olan en yeni ölçü hâlâ 0,9700’dür.

Uyarının ateşleyebildiği ilk dönem 2026-11’dir, çünkü 2026-09‘un etiketleri ancak o zaman tamamlanır. Yakalama gecikmesi iki dönemdir ve bu boşlukta 400 tahmin ölçülmeden üretilmiştir. Bu 400 tahminin **63’ünün** yanlış olduğu sonradan anlaşılır; kural değişmeseydi aynı iki dönemde yanlış sayısı 7 olacaktı. Aradaki 56 tahmin, bozulmanın görülmediği süre boyunca üretilip kullanılmış olanlardır ve geriye dönüp düzeltilemezler, çünkü karar zaten verilmiştir.

Dikkat edilecek ikinci şey son sütundur: boşluk kapandıktan sonra da her dönemde 400 tahmin ölçülmemiş durumda kalır. Gecikme geçici bir başlangıç sorunu değil, sürekli taşınan bir borçtur; üretimdeki gösterge hiçbir zaman şimdiyi göstermez, her zaman iki dönem öncesini gösterir.

Gecikmenin Bedeli

Üçüncü blok gecikmeyi süpürür. Kurulumun geri kalanı sabittir; değişen tek şey etiketin kaç dönem sonra geldiğidir. Son satır izlemesiz taban çizgisidir: etiket hiç toplanmaz.

SON = len(IZLEME) - IZLEME.index(BOZULAN)     # bozulmadan sonraki donem sayisi
print(f"{'gecikme':<12}{'bozulma gorulur':>18}{'gorulme gecikmesi':>19}"
      f"{'olculebilen donem':>19}{'olculmeden uretilen':>21}")
for g in (0, 1, 2, 3, 4):
    gor = next((s for s in IZLEME
                if any(gorulen_donem(d, s, g) and abs(GERCEK[d] - TABAN) / TABAN > BANT
                       for d in IZLEME)), None)
    gec = DONEM.index(gor) - DONEM.index(BOZULAN) if gor else SON
    print(f"{g:<12}{(gor or 'gorulmedi'):>18}{(gec if gor else '-'):>19}"
          f"{sum(1 for d in IZLEME if gorulen_donem(d, IZLEME[-1], g)):>19}{gec * 200:>21}")
print(f"{'etiket yok':<12}{'gorulmedi':>18}{'-':>19}{0:>19}{SON * 200:>21}")
gecikme        bozulma gorulur  gorulme gecikmesi  olculebilen donem  olculmeden uretilen
0                      2026-09                  0                  6                    0
1                      2026-10                  1                  5                  200
2                      2026-11                  2                  4                  400
3                      2026-12                  3                  3                  600
4                    gorulmedi                  -                  2                  800
etiket yok           gorulmedi                  -                  0                  800

Bedel doğrusaldır ve birimi bellidir: her dönemlik gecikme 200 ölçülmemiş tahmin demektir. Dördüncü satırda gecikme, izleme penceresinin sonuna dayanır; bozulma 2026-09’da olmuştur ama etiketi 2027-01’de geleceği için pencere içinde hiç görülmez. Bu satır önemlidir, çünkü gecikme yeterince büyüdüğünde ölçü var olmayı sürdürür ama işe yaramaz.

Son satır izlemesiz taban çizgisidir ve gecikme 4 ile aynı sonucu verir: bozulma görülmez, 800 tahmin ölçülmeden üretilir. Aradaki tek fark ölçülebilen dönem sayısındadır, 2’ye karşı 0. Kursun kuralı burada da geçerlidir: bir gösterge ancak ateşleyebildiği zaman ölçülmüş sayılır ve ateşlemesi pencere dışına düşen bir gösterge ölçülmemiş bir güvence verir.

Özet

  • İsabet, girdi özeti ile tahmin payından farklı olarak gerçek etiket ister; etiket üretimde tahminle aynı anda gelmez ve bu kurulumda iki dönem sonra gelir.
  • Bozulma 2026-09’da olur, ama uyarının ateşleyebildiği ilk dönem 2026-11‘dir: görülme gecikmesi iki dönem ve bu boşlukta 400 tahmin ölçülmeden üretilmiştir; bunların **63’ünün** yanlış olduğu sonradan anlaşılır, kural değişmeseydi sayı 7 olacaktı.
  • 2026-09‘da ekrandaki sayı 0,9700’dür ve yanlış değildir, yalnızca iki dönem eskidir; eskiliği yazılmayan bir gösterge yanlış bir göstergeden ayırt edilemez.
  • Boşluk kapandıktan sonra da her dönemde 400 tahmin ölçülmemiş kalır: gecikme geçici değil, sürekli taşınan bir borçtur.
  • Süpürme bedeli doğrusal verir: gecikme 0’da 0, 1’de 200, 2’de 400, 3’te 600 ölçülmemiş tahmin; 4’te bozulma izleme penceresi içinde hiç görülmez ve izlemesiz taban çizgisinde ölçülebilen dönem sayısı 0’dır.

Sonraki Adım

Üç derste bozulmanın görülmesi ölçüldü ve son ölçü bir boşluk bıraktı: bozulma olduktan sonra iki dönem boyunca tek gören ölçü suskundur ve o boşlukta 400 tahmin ölçülmeden üretilir. Bu boşlukta elde ne olduğu ise hiç sorulmadı. Girdi özeti ve tahmin payı oradadır, etiket beklemeden hesaplanırlar ve önceki derste ikisinin de yanıltabildiği görüldü. Sonraki ders bunları vekil ölçüt olarak ele alır ve tek tek ne gördüklerini sayar: hangi vekil kavram kaymasını görebiliyor, hangisi zararsız kaymada ateşliyor ve girdi eksiksizliği gibi üçüncü bir vekil eklendiğinde tablo değişiyor mu.

İ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