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

# Uyarı ve Eşikler

Uyarı bandının daraldıkça ne kazandırıp ne kaybettirdiğinin sayılması: 0,05 bandında üç ölçü ve üç senaryo boyunca 13 dönem ateşliyor, bunların 6'sı yanlış alarm; 0,10'da 6 ateşleme ve 2 yanlış alarm; 0,20'de hiç yanlış alarm yok ama gerçek bozulmanın dördü de kaçıyor, çünkü 0,20'lik göreli bant 0,9700 tabanında isabetin 0,7760'ın altına inmesini ister ve en dip değer 0,8150'dir. Tahmin payı 0,05 bandında hem sağlam kurulumda hem kavram kaymalı kurulumda tam üç dönem ateşliyor; aynı ateşleme bir yerde saf yanlış alarm, öbür yerde yakalama sayılıyor, bu yüzden ölçülmemiş sayılır. Yalnız isabet iki zararsız senaryoda hiç ateşlemeyip zararlı senaryoda dört dönem ateşliyor ve yakalama gecikmesi iki dönem.

Bir önceki ders üç vekilin sapmasını saydı ve son sütunda tek bir sayı bıraktı: `2026-08` tabanına
göre en büyük göreli sapma. O sayı tek başına bir karar vermez. Karar, sapmanın bir **bantla**
karşılaştırılmasıyla doğar; bandın adı **uyarı eşiğidir (alert threshold)** ve bir ölçünün değil,
**bir seçimin** parçasıdır.

Seçim ucuz görünür ve değildir. Bant daraldıkça daha çok dönem ateşler; ateşleyen dönemlerin kaçının
gerçekten bozulmuş olduğu ise bandın bilmediği bir şeydir. Bu ders bandı 0,05, 0,10 ve 0,20'de
sabitler, üç ölçüyü üç senaryoda koşturur ve iki sayıyı ayrı ayrı yazar: **ateşleyen dönem** ile
**bunların kaçının gerçek bozulmaya karşılık geldiği**.

- **MI47.** Kaynak, hat, kurgu model ve iki kayma türü **kurgudur** ve ders içinde üretilir. Hiçbir
  izleme ürünü, gösterge servisi, bulut servisi ya da öğrenme kitaplığı çağrılmaz. Tohum 20260218.
- **MI48. Uyarı eşiği**, bir ölçünün `2026-08` tabanından **göreli** sapmasının aşmaması gereken
  paydır. Üç bant sınanır: 0,05, 0,10 ve 0,20. Taban dönemi kaymaların hiçbirinin başlamadığı son
  dönemdir.
- **MI49. Gerçek bozulma** banttan bağımsız tanımlanır: bir dönemin **gerçek** isabetinin `2026-08`
  tabanından **0,0500'den fazla** düşmesi, yani on çözünürlük adımı. Bu ölçü değerlendirme içindir;
  üretimde iki dönem gecikmeyle bilinir.
- **MI50. Yanlış alarm (false positive)**, ateşleyen ama gerçek bozulma listesinde olmayan dönemdir.
  Gösterge gecikmesinin ölçümü Veri Hatları ve Orkestrasyon kursunun hat gözlemlenebilirliği
  dersinde yapıldı ve **tekrarlanmaz**. Buradaki tek ek **gecikmeli etikettir**: isabet üzerinden
  ateşleyen bir uyarının gecikmesine `GECIKME` eklenir.
- **MI51.** Model MLOps Temelleri kursundan düzeltilmiş biçimde devralınır: karar eşiği ayrı bir
  ayardır, eğitim ölçütü **dengeli isabettir**. İzleme dönemlerinde **taban sınıf oranı 0,5342**.
- **MI52.** Taban çizgisi **izlemesiz kurulumdur**: bant yok, ateşleyen dönem 0, yakalama gecikmesi
  tanımsız. Dönem isabetinin adımı **0,0050**.

## Uyarı Eşiği Bir Karşılaştırmadır

Aşağıdaki blok ortak tanımı kurar ve üzerine iki şey ekler: bir ölçü dizisini tabanla karşılaştıran
`uyari`, ve bir dönemin isabetinin hangi dönemde bilinebildiğini söyleyen `gorulen_donem`.

```python
# KURGUDUR. Olcum aginin sayac okumalari , bes asamali hat , kurgu model ve iki kayma
# turu ders icinde uretilir; hicbir izleme urunu , gosterge servisi , bulut servisi ya
# da ogrenme kitapligi 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 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 not in gor:
            gor.add(ad)
            tut.append(k)
    return tut, len(kayit) - len(tut)


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


def satirlar(kaynak=None):
    v, _ = a1_ayikla(kaynak_uret() if kaynak is None else kaynak)
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    return v


def oznitelikler(kayitlar, pencere=None, basamak=4):
    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 and (pencere is None or d >= i - pencere))]
        return round(sum(secili) / len(secili), basamak) if secili else 0.0

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


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 , egitimde aranir
IZLEME = DONEM[6:]                      # 2026-07 .. 2026-12 : uretimde izlenen donemler
GECIKME = 2                             # etiket kac donem sonra geliyor
KURAL_ESIK, KURAL_ISYERI = 30, 6        # KAVRAM: abone_ort + 6 x isyeri > 30


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


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


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


def dengeli_isabet(kume, oz, w, karar):
    dp = dn = yp = yn = 0
    for k in kume:
        o_k = oz[(k["abone"], k["donem"])]
        t, g = tahmin(o_k, w, karar), etiket(o_k)
        dp, yp = dp + (t and g), yp + (t and not g)
        yn, dn = yn + (g and not t), dn + (not t and not g)
    duyarlilik = dp / (dp + yn) if dp + yn else 0.0
    ozgulluk = dn / (dn + yp) if dn + yp else 0.0
    return (duyarlilik + ozgulluk) / 2, round(duyarlilik, 4), round(ozgulluk, 4)


def egit(kayitlar, oz, donemler=None):
    """Egitim olcutu DENGELI ISABETTIR: duyarlilik ile ozgullugun ortalamasi."""
    kume = [k for k in kayitlar if k["donem"] in (donemler or DONEM[1:9])]
    en = (-1.0, None, None, 0.0, 0.0)
    for w in IZGARA:
        for karar in KARAR_IZGARA:
            o, du, oz_ = dengeli_isabet(kume, oz, w, karar)
            if o > en[0]:
                en = (o, w, karar, du, oz_)
    return {"agirlik": en[1], "karar": en[2], "dengeli": round(en[0], 4),
            "duyarlilik": en[3], "ozgulluk": en[4], "egitim_satiri": len(kume)}


def kaydir(kayitlar, baslangic="2026-09", egim=0.06):
    """VERI KAYMASI: baslangictan sonra 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]


def kavram_kaydir(kayitlar, oz, baslangic="2026-09", yeni_esik=27):
    """KAVRAM KAYMASI: girdi AYNI , kural degisiyor. Esik 30'dan yeni_esik'e iniyor."""
    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}


def girdi_ozeti(kayitlar, donem, oz):
    d = [oz[(k["abone"], k["donem"])]["abone_ort"] for k in kayitlar if k["donem"] == donem]
    return round(sum(d) / len(d), 4) if d else 0.0


def tahmin_payi(kayitlar, model, oz, donem):
    d = [tahmin(oz[(k["abone"], k["donem"])], model["agirlik"], model["karar"])
         for k in kayitlar if k["donem"] == donem]
    return round(sum(d) / len(d), 4) if d else 0.0


def isabet(kayitlar, model, oz, donem, etiketler=None):
    kume = [k for k in kayitlar if k["donem"] == donem]
    d = sum(1 for k in kume
            if tahmin(oz[(k["abone"], k["donem"])], model["agirlik"], model["karar"])
            == (etiketler[(k["abone"], k["donem"])] if etiketler
                else etiket(oz[(k["abone"], k["donem"])])))
    return round(d / len(kume), 4) if kume else None


def uyari(dizi, taban, pay):
    """Bir olcu tabandan `pay` kadar saparsa o donem ates eder."""
    return [d for d, v in dizi if abs(v - taban) / max(abs(taban), 1e-9) > pay]


def gorulen_donem(donem, simdi):
    """Gecikmeli etiket: bir donemin isabeti ancak GECIKME donem sonra bilinir."""
    return DONEM.index(donem) + GECIKME <= DONEM.index(simdi)


SATIR = satirlar()
OZ = oznitelikler(SATIR)                  # oznitelik BIR KEZ hesaplanir
MODEL = egit(SATIR, OZ)
IZL = [k for k in SATIR if k["donem"] in IZLEME]
buyuk = max(sum(1 for k in IZL if etiket(OZ[(k["abone"], k["donem"])]) == s) for s in (0, 1))
print(f"model {MODEL['agirlik']} karar esigi {MODEL['karar']} , dengeli isabet"
      f" {MODEL['dengeli']} , {len(IZL)} satir , taban sinif orani {buyuk / len(IZL):.4f} ,"
      f" adim {1 / 200:.4f} , 2026-09'un isabeti"
      f" {[d for d in DONEM if gorulen_donem('2026-09', d)][0]} doneminde bilinir")
```

```
model (0.6, 0.0, 4) karar esigi 18 , dengeli isabet 0.9864 , 1200 satir , taban sinif orani 0.5342 , adim 0.0050 , 2026-09'un isabeti 2026-11 doneminde bilinir
```

Son alan bandın ölçemediği şeyi baştan söyler: `2026-09`'da bir şey bozulsa bile o dönemin isabeti
`2026-11`'de bilinir. İsabet üzerine kurulan bir uyarı, bandı ne kadar dar olursa olsun **iki dönem
sonra** konuşur. Bandın oynatabildiği tek şey, gecikmesiz vekillerin kaç kez konuşacağıdır.

## Bant Daraldıkça

Aşağıdaki blok üç ölçüyü üç senaryoda üç bantla karşılaştırır. Her hücre iki sayı taşır: **ateşleyen
dönem** ve bunların kaçının **yanlış alarm** olduğu. `bozulan` sütunu banttan bağımsızdır; o
senaryoda gerçekten bozulmuş dönem sayısını verir.

```python
# Bu blok ilk bloktaki tanimlari surdurur. Her senaryonun oznitelikleri BIR KEZ hesaplanir.
BANT = (0.05, 0.10, 0.20)
DUSUS = 0.0500        # GERCEK BOZULMA: isabetin tabandan bu kadardan fazla dusmesi
KAYAN = kaydir(SATIR)
OZ_K = oznitelikler(KAYAN)
KAVRAM = kavram_kaydir(SATIR, OZ)
SENARYO = (("saglam", SATIR, OZ, None), ("veri kaymali", KAYAN, OZ_K, None),
           ("kavram kaymali", SATIR, OZ, KAVRAM))
OLCU = (("girdi ozeti", lambda kay, oz, et, d: girdi_ozeti(kay, d, oz)),
        ("tahmin payi", lambda kay, oz, et, d: tahmin_payi(kay, MODEL, oz, d)),
        ("isabet", lambda kay, oz, et, d: isabet(kay, MODEL, oz, d, et)))
ATES, GERCEK = {}, {}
for sad, kay, oz, et in SENARYO:
    isb = [(d, isabet(kay, MODEL, oz, d, et)) for d in IZLEME]
    GERCEK[sad] = set(d for d, v in isb[2:] if dict(isb)["2026-08"] - v > DUSUS)
    for ad, f in OLCU:
        dizi = [(d, f(kay, oz, et, d)) for d in IZLEME]
        for b in BANT:
            ATES[(sad, ad, b)] = set(uyari(dizi[2:], dict(dizi)["2026-08"], b))

print(f"gercek bozulma: isabetin 2026-08 tabanindan {DUSUS:.4f} uzerinde dusmesi")
print("hucre: atesleyen donem / yanlis alarm\n")
print("olcu         senaryo         bozulan " + "".join(f"{b:>12.2f}" for b in BANT))
for ad, _ in OLCU:
    for sad, *_ in SENARYO:
        h = [f"{len(ATES[(sad, ad, b)])} / {len(ATES[(sad, ad, b)] - GERCEK[sad])}"
             for b in BANT]
        print(f"{ad:<12} {sad:<14} {len(GERCEK[sad]):>7} " + "".join(f"{x:>12}" for x in h))

print("\nbant  toplam ates  yanlis alarm  yakalanan  gecikme: tahmin payi  isabet")
for b in BANT:
    t = [sum(len(ATES[(s, a, b)]) for s, *_ in SENARYO for a, _ in OLCU),
         sum(len(ATES[(s, a, b)] - GERCEK[s]) for s, *_ in SENARYO for a, _ in OLCU),
         sum(len(ATES[(s, a, b)] & GERCEK[s]) for s, *_ in SENARYO for a, _ in OLCU)]
    g = []
    for ad, ek in (("tahmin payi", 0), ("isabet", GECIKME)):
        a = sorted(ATES[("kavram kaymali", ad, b)])
        g.append(str(DONEM.index(a[0]) - DONEM.index("2026-09") + ek) if a else "tanimsiz")
    print(f"{b:<5.2f} {t[0]:>11} {t[1]:>13} {t[2]:>10} {g[0]:>21} {g[1]:>7}")
```

```
gercek bozulma: isabetin 2026-08 tabanindan 0.0500 uzerinde dusmesi
hucre: atesleyen donem / yanlis alarm

olcu         senaryo         bozulan         0.05        0.10        0.20
girdi ozeti  saglam               0        0 / 0       0 / 0       0 / 0
girdi ozeti  veri kaymali         0        0 / 0       0 / 0       0 / 0
girdi ozeti  kavram kaymali       4        0 / 0       0 / 0       0 / 0
tahmin payi  saglam               0        3 / 3       0 / 0       0 / 0
tahmin payi  veri kaymali         0        3 / 3       2 / 2       0 / 0
tahmin payi  kavram kaymali       4        3 / 0       0 / 0       0 / 0
isabet       saglam               0        0 / 0       0 / 0       0 / 0
isabet       veri kaymali         0        0 / 0       0 / 0       0 / 0
isabet       kavram kaymali       4        4 / 0       4 / 0       0 / 0

bant  toplam ates  yanlis alarm  yakalanan  gecikme: tahmin payi  isabet
0.05           13             6          7                     1       2
0.10            6             2          4              tanimsiz       2
0.20            0             0          0              tanimsiz tanimsiz
```

## Yakalama Sayısının Geçersiz Olduğu Yer

Alt tablonun ilk satırı bandı savunuyor görünür: 0,05'te 13 ateşleme, 7'si gerçek bozulmaya
denk geliyor. Bu sayı geçersizdir ve gerekçesi üst tablodadır. `tahmin payi` satırlarına bakın:
**sağlam** kurulumda 3 dönem ateşliyor, **kavram kaymalı** kurulumda yine tam 3 dönem. Aynı ölçü,
aynı bant, aynı ateşleme sayısı; tek fark, ikinci durumda o dönemlerin bozulmuş olması. Ateşleme
bozulmadan gelmiyor, bozulmayla **aynı zamana denk düşüyor**. Sağlam satır bunu kanıtlar: hiçbir şey
bozuk değilken de aynı üç dönem konuşuyor.

Bu kursun kuralının tam tanımıdır: ateşlemesi ile bozulması ayrı ayrı gösterilmeyen bir gösterge
ölçülmemiş sayılır. Sağlam satır olmasaydı 0,05 bandındaki tahmin payı kusursuz bir gösterge gibi
okunurdu — 3 ateşleme, 0 yanlış alarm. Sağlam satırla birlikte 7 yakalamanın 3'ü düşer ve geriye
**4** kalır. O dördünü tek bir ölçü verir: isabet, iki zararsız senaryoda 0,05 ve 0,10 bantlarında
**hiç** ateşlemeyip zararlı senaryoda dört dönemin dördünde ateşleyen tek satır. Bedeli son
sütundadır: yakalama gecikmesi **2 dönem**, ve bant seçilerek küçültülemez.

## Yanlış Alarm ile Körlüğün Takası

Bandı genişletmek sayıyı düzeltmez, sıfırlar. 0,05'ten 0,10'a çıkıldığında yanlış alarm 6'dan 2'ye
iner ve yakalanan 7'den 4'e — ama düşen üç yakalama zaten geçersiz olan tahmin payı yakalamalarıdır,
yani 0,10 bandı **hiçbir gerçek bilgi kaybetmeden** yanlış alarmın üçte ikisini atar. Bu, bandı
genişletmenin bedava olduğu tek adımdır.

0,20 satırı ise üç sıfırdır: yanlış alarm yok, ateşleme yok, yakalama yok. Bandın isabet üzerindeki
karşılığı hesaplanabilir: 0,9700 tabanının 0,80 katı **0,7760**'tır, yani 0,20'lik bir bant isabetin
bu değerin altına inmesini bekler. Kavram kaymasının en dip değeri **0,8150**'dir ve 0,7760'ın
0,0390 üstünde, yaklaşık sekiz çözünürlük adımı yukarıda kalır. Bant, ölçünün ulaşamayacağı bir yere
konmuştur; sessizliği bir sağlık işareti değil, **tanım gereği ölü bir göstergedir**.

Üç bandı birlikte okumak kursun ikinci iddiasını verir: izleme de bozar. Dar bant hiçbir şeyin
bozulmadığı bir üretimde altı kez uyandırır; geniş bant isabetin 0,9700'den 0,8150'ye düştüğü bir
üretimde hiç konuşmaz. Aradaki bant yalnız bu kurguda iyi bir seçimdir, çünkü hangi ateşlemenin
gerçek olduğunu **gerçek isabete bakarak** biliyoruz — üretimde o bilgi iki dönem sonra gelir ve
bant onsuz seçilir.

## Özet

- Uyarı eşiği bir ölçü değil bir seçimdir: `2026-08` tabanından göreli sapmanın aşmaması gereken
  paydır ve ateşleyen dönem sayısını doğrudan belirler.
- 0,05 bandında üç ölçü ve üç senaryo boyunca 13 dönem ateşler, 6'sı yanlış alarmdır; 0,10'da 6
  ateşleme ve 2 yanlış alarm; 0,20'de üçü de sıfırdır.
- 0,05'teki 7 yakalamanın 3'ü geçersizdir: tahmin payı **sağlam** kurulumda da tam 3 dönem ateşler.
  Ateşlemesi ile bozulması ayrı ayrı gösterilmeyen gösterge ölçülmemiş sayılır; geçerli yakalama
  **4**'tür ve hepsi isabetten gelir.
- İsabet, iki zararsız senaryoda hiç ateşlemeyip zararlı senaryoda dört dönemin dördünde ateşleyen
  tek ölçüdür; bedeli **2 dönemlik** yakalama gecikmesidir ve bant seçimiyle küçültülemez.
- 0,20 bandı isabetin 0,7760'ın altına inmesini ister; en dip değer 0,8150'dir, yani bant ölçünün
  ulaşamayacağı yerdedir ve sessizliği bir sağlık işareti değildir.

## Sonraki Adım

Bu dersin geçerli tek göstergesi isabetti ve isabet **etiket** ister. Şimdiye kadar etiket kurgunun
bir armağanıydı: her satırın gerçek sınıfı biliniyordu, yalnız iki dönem geç geliyordu. Üretimde
öyle değildir — etiket toplanır ve toplanan şey **bütün tahminler için gelmez**. Sonraki ders
etiketin nereden geldiğini sorar: toplama yordamı tahminlerin ancak bir kısmını kapsadığında ölçülen
isabetin gerçek isabetten ne kadar saptığını ve hangi toplama biçiminin kapsamı büyütürken yanlılığı
da büyüttüğünü sayar.
