---
title: 'Başarım İzleme'
source: 'https://academia.sh/tr/kurslar/model-izleme/basarim-izleme'
course: 'Model İzleme ve Yönetişim'
language: tr
updated: '2026-08-17T18:08:53+00:00'
license: 'CC BY-SA 4.0'
---

# 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.

İ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.

```python
# 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.

```python
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.

```python
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.
