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

# Kavram Kayması

Girdi hiç değişmeden girdi ile etiket arasındaki kuralın değişmesinin ölçülmesi: yüksek sayılma eşiği 30'dan 27'ye indiğinde girdi tarafında değişen tek bir değer olmamasına karşın 1200 izleme satırının 132'sinin etiketi değişiyor ve modelin isabeti 0,9700'den 0,8150'ye, yani otuz bir çözünürlük adımı düşüyor. Aynı üç gösterge iki kayma türünde yan yana okunduğunda vekil ölçütlerin neyi görüp neyi kaçırdığı sayıya dönüyor: girdi özeti iki senaryoda da hiçbir bantta ateşlemiyor, tahmin payı 0,05 bandında ikisinde de üç dönem ateşleyerek zararsızı zararlıdan ayıramıyor ve 0,10 bandında zararsız kaymada iki dönem ateşlerken zararlı kaymada hiç ateşlemiyor, isabet ise zararsız kaymada susup zararlı kaymada dört dönem ateşleyerek tek ayırt eden ölçü olarak kalıyor.

Önceki derste kayan şey **girdiydi**: girdi özeti 25,9220'den 27,0472'ye çıktı, tahmin payı üç
dönem uyarı ateşledi ve isabet 0,9700'den 0,9800'e giderek hiç düşmedi. Kural yerinde durduğu için
model doğru kalabildi ve ateşleyen uyarıların üçü de yanlış alarm sayıldı.

Bu ders tam tersini kurar. Girdi tarafında **tek bir değer bile değişmez**; değişen, girdi ile
etiket arasındaki **kuralın kendisidir**. Aynı abonenin aynı geçmişi artık başka bir etiket
üretmeye başlar, çünkü "yüksek sayılma" ölçütü kaymıştır. Model hiç dokunulmadan yerinde durur ve
ölçülecek soru şudur: önceki dersin üç göstergesi bu durumda ne der.

- **MI8.** Kaynak, hat, model ve kayma senaryoları **kurgudur**; gerçek bir öğrenme kitaplığı,
  izleme ürünü ya da bulut servisi çağrılmaz. Tohum **20260218**.
- **MI9.** **Kavram kayması (concept drift)** girdi ile etiket arasındaki ilişkinin değişmesidir.
  **Veri kayması** girdi dağılımını, kavram kayması **kuralı** oynatır. Kaymanın ölçüm yordamı
  Model Değerlendirme, Yorumlanabilirlik ve Etik kursunda kuruldu ve **tekrarlanmaz**; buradaki ek
  yalnız **üretimdeki ömürdür**.
- **MI10.** Bu kursun etiketi `abone_ort + 6 x isyeri > 30` kuralıdır ve **kural KAVRAM'dır**.
  Kurgu kavram kayması `2026-09`'dan sonra eşiği **30'dan 27'ye** indirir; kayıtlara dokunmaz,
  yalnız etiket üretir.
- **MI11.** İ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.
- **MI12.** Üç gösterge: **girdi özeti** (özniteliğin dönem ortalaması), **tahmin payı** (modelin
  yüksek dediği satırların oranı) ve **isabet**. İlk ikisi etiket istemez, üçüncüsü ister.
- **MI13.** Taban çizgisi **izlemesiz kurulumdur**: gösterge yok, uyarı yok; bozulma **görülmez**.
- **MI14.** **Uyarı eşiği** iki yönlü bir **bant**tır: ölçü tabandan pay kadar saparsa ateşler.
  Taban dönem `2026-08`, yani kaymanın başladığı dönemden önceki son dönem.
- **MI15.** Çözünürlük: dönem isabetinin adımı **1/200 = 0,0050**. Bu derste düşüş **0,1550**, yani
  **otuz bir adım** ve bandın çok üstünde; önceki dersin oynaması dört adımdı.

## Değişmeyen Girdi, Değişen Kural

İlk blok önceki dersin kurulumunu aynen kurar: kaynak, hattın modele bakan üç aşaması,
öznitelikler, karar eşiği ayrı aranan model ve üç gösterge. Model **bu derste hiç yeniden
eğitilmez**; ölçülen şey, sabit bir modelin altından kuralın çekilmesidir.

```python
# KURGUDUR. Olcum aginin sayac okumalari, hattin modele bakan ilk uc asamasi,
# esik tabanli model ve kayma senaryolari 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"]


# Etiket, ozniteliklerin GORDUGU bir kurala baglidir. KURAL = KAVRAM.
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 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)


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)


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)


S = satirlar()
OZ = oznitelikler(S)
MODEL = egit(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
print("izleme satiri:", len(IZL), " donem basina:", len(IZL) // len(IZLEME),
      " taban sinif orani:", round(dag[0] / len(IZL), 4))
print("model:", MODEL["agirlik"], "/ karar esigi", MODEL["karar"],
      " dengeli isabet:", round(MODEL["dengeli"], 4))
```

```
izleme satiri: 1200  donem basina: 200  taban sinif orani: 0.5342
model: (0.6, 0.0, 4) / karar esigi 18  dengeli isabet: 0.9864
```

## Kavram Kaydığında Ne Görünüyor

İkinci blok kavram kaymasını uygular. `kavram_kaydir` işlevi **kayıtlara dokunmaz**; yalnız
`2026-09`'dan başlayarak yüksek sayılma eşiğini 27'ye indirilmiş biçimde etiket üretir. Tabloda son
iki sütun önemlidir: **kural değişmeseydi** o dönemde alınacak isabet ve o dönemde **etiketi
değişen** satır sayısı.

```python
# ---- KURGU kavram kaymasi: GIRDI AYNI KALIR , kural degisir.
# 2026-09'dan sonra "yuksek sayilma" esigi 30'dan 27'ye iniyor.
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}


YENI = kavram_kaydir(S, OZ)
print(f"{'donem':<10}{'girdi ozeti':>13}{'tahmin payi':>13}{'isabet':>9}"
      f"{'kural degismeseydi':>20}{'etiketi degisen':>17}")
for d in IZLEME:
    kume = [k for k in S if k["donem"] == d]
    ceviren = sum(1 for k in kume
                  if YENI[(k["abone"], d)] != etiket(OZ[(k["abone"], d)]))
    print(f"{d:<10}{girdi_ozeti(S, d, OZ):>13.4f}{tahmin_payi(S, MODEL, OZ, d):>13.4f}"
          f"{isabet(S, MODEL, OZ, d, YENI):>9.4f}{isabet(S, MODEL, OZ, d):>20.4f}"
          f"{ceviren:>17}")
```

```
donem       girdi ozeti  tahmin payi   isabet  kural degismeseydi  etiketi degisen
2026-07         25.9220       0.4550   0.9700              0.9700                0
2026-08         26.0517       0.4700   0.9700              0.9700                0
2026-09         25.9800       0.4550   0.8150              0.9900               39
2026-10         26.3525       0.5100   0.8700              0.9750               31
2026-11         26.3261       0.5100   0.8650              0.9850               30
2026-12         26.5325       0.5150   0.8500              0.9900               32
```

İsabet `2026-09`'da **0,9700'den 0,8150'ye** düşüyor. Düşüş **0,1550**, yani çözünürlüğün **otuz
bir adımı**; önceki dersin bütün oynaması dört adımdı. Modelde değişen tek bir sayı yoktur ve
girdi tarafında da yoktur: son sütun kaymanın nereden geldiğini söyler, `2026-09`'da **39**
satırın etiketi değişmiştir. Değişen etiketlerin hepsi hataya dönüşmez, çünkü modelin karar eşiği
bazı satırlarda yeni kuralla zaten uyumludur; sonraki dönemlerde isabet 0,8700 dolayında
tutunur ama **eski düzeyine hiç dönmez**.

İlk iki sütun tam olarak beklendiği gibi davranır. Girdi özeti 25,9220'den 26,5325'e, tahmin payı
0,4550'den 0,5150'ye gider. Bu iki seri, kavram kayması **hiç olmasaydı** da birebir aynı olurdu,
çünkü ikisi de yalnız girdiye ve modele bakar; kuralın nereye kaydığından haberleri yoktur.

## Zararsız Kaymada Ateşleyen, Zararlı Kaymada Susan

Üçüncü blok önceki dersin veri kayması senaryosunu geri getirir ve iki senaryoyu **aynı üç
göstergeyle, aynı üç bantla** yan yana koyar. Tabloda okunacak şey tek tek sayılar değil,
**satırların birbirine göre durumudur**.

```python
# ---- KURGU veri kaymasi (onceki ders): GIRDI kayar , KURAL AYNI KALIR.
def kaydir(kayitlar, baslangic="2026-09", egim=0.06):
    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 uyari(dizi, taban, pay):
    return [d for d, v in dizi if abs(v - taban) / max(abs(taban), 1e-9) > pay]


KAYAN = kaydir(S)
OZK = oznitelikler(KAYAN)
print(f"{'senaryo':<16}{'olcu':<14}{'taban':>10}{'en buyuk sapma':>16}"
      f"{'0,05':>7}{'0,10':>7}{'0,20':>7}")
for ad, (kay, oz, et) in (("veri kaymasi", (KAYAN, OZK, None)),
                          ("kavram kaymasi", (S, OZ, YENI))):
    for olcu_ad, dizi in (("girdi ozeti", [(d, girdi_ozeti(kay, d, oz)) for d in IZLEME]),
                          ("tahmin payi", [(d, tahmin_payi(kay, MODEL, oz, d)) for d in IZLEME]),
                          ("isabet", [(d, isabet(kay, MODEL, oz, d, et)) for d in IZLEME])):
        taban = dict(dizi)[IZLEME[1]]
        print(f"{ad:<16}{olcu_ad:<14}{taban:>10.4f}"
              f"{max(abs(v - taban) / taban for _, v in dizi):>16.4f}"
              + "".join(f"{len(uyari(dizi, taban, p)):>7}" for p in (0.05, 0.10, 0.20)))

print("\nkavram kaymasinda degisen satir sayisi:",
      sum(1 for k in IZL if YENI[(k["abone"], k["donem"])] != etiket(OZ[(k["abone"], k["donem"])])),
      "/", len(IZL), " girdi tarafinda degisen deger: 0")
DUSUS = isabet(S, MODEL, OZ, IZLEME[0], YENI) - isabet(S, MODEL, OZ, IZLEME[2], YENI)
print("isabetin dustugu:", f"{DUSUS:.4f}", " donem isabetinin adimi:", f"{1 / 200:.4f}",
      " yani", round(DUSUS * 200), "adim")
```

```
senaryo         olcu               taban  en buyuk sapma   0,05   0,10   0,20
veri kaymasi    girdi ozeti      26.0517          0.0382      0      0      0
veri kaymasi    tahmin payi       0.4700          0.1596      3      2      0
veri kaymasi    isabet            0.9700          0.0206      0      0      0
kavram kaymasi  girdi ozeti      26.0517          0.0185      0      0      0
kavram kaymasi  tahmin payi       0.4700          0.0957      3      0      0
kavram kaymasi  isabet            0.9700          0.1598      4      4      0

kavram kaymasinda degisen satir sayisi: 132 / 1200  girdi tarafinda degisen deger: 0
isabetin dustugu: 0.1550  donem isabetinin adimi: 0.0050  yani 31 adim
```

Girdi özeti iki senaryoda da hiçbir bantta ateşlemez. Kavram kaymasında bunun başka türlüsü de
mümkün değildir: girdi tarafında değişen **sıfır** değer vardır ve gösterge yalnız girdiye bakar.

Tahmin payı iki kez ateşler ve her ikisinde de yanıltır. 0,05 bandında **her iki senaryoda da üç
dönem** ateşliyor, yani zararsız kaymayı zararlı kaymadan **ayırt edemiyor**. 0,10 bandında ise
tam ters çalışıyor: zararsız kaymada **iki dönem** ateşliyor, zararlı kaymada **hiç**. Kavram
kaymasındaki 0,0957'lik sapmanın kaymayla ilgisi de yoktur; o seri, kural hiç değişmeseydi de
aynıydı. Bir gösterge ateşlediğinde tek başına ne bozulmayı ne de nedenini gösterir.

İsabet tek ayırt eden ölçüdür. Zararsız kaymada sapması **0,0206** ve hiçbir bantta ateşlemiyor;
zararlı kaymada sapması **0,1598** ve hem 0,05 hem 0,10 bandında **dört dönem** ateşliyor. Bu
kursun kuralı burada iki yönlü okunur: bir göstergenin ateşlemesi bozulmanın kanıtı olmadığı gibi,
**susması da sağlamlığın kanıtı değildir**; ateşlemesi ile bozulması ayrı ayrı gösterilmeyen
gösterge ölçülmemiş sayılır. İzlemesiz taban çizgisinde ise 132 satırın etiketi değişmiş, isabet
otuz bir adım düşmüş ve hiçbir şey haber vermemiştir.

## Özet

- Kavram kayması girdi ile etiket arasındaki **kuralın** değişmesidir; veri kaymasının aksine
  girdi tarafında değişen tek bir değer yoktur.
- Eşik 30'dan 27'ye indiğinde 1200 izleme satırının **132'sinin** etiketi değişir ve isabet
  **0,9700'den 0,8150'ye** düşer: **0,1550**, yani **otuz bir çözünürlük adımı**. Model hiç
  değişmemiştir.
- Girdi özeti iki senaryoda da hiçbir bantta ateşlemez; kavram kaymasında ateşlemesi zaten
  olanaksızdır, çünkü baktığı yerde değişen bir şey yoktur.
- Tahmin payı 0,05 bandında iki senaryoda da **üç dönem** ateşleyerek ikisini ayırt edemez, 0,10
  bandında ise zararsız kaymada iki dönem ateşleyip zararlı kaymada **hiç** ateşlemez.
- İsabet tek ayırt eden ölçüdür: zararsız kaymada sapması 0,0206 ve susar, zararlı kaymada 0,1598
  ve 0,05 ile 0,10 bantlarında dört dönem ateşler.

## Sonraki Adım

İki derste ortaya çıkan sonuç şudur: bozulmayı gören tek gösterge **isabettir**. Fakat isabet
öbür ikisinden farklı bir şey ister, gerçek etiketi. Girdi özeti ile tahmin payı, tahmin
üretildiği anda hesaplanabilir; isabet ise satırın gerçekten yüksek olup olmadığı bilinene kadar
hesaplanamaz ve o bilgi üretimde tahminle aynı anda gelmez. Bu derste etiket, hesaplama sırasında
elde varmış gibi kullanıldı. Sonraki ders bu varsayımı kaldırır: etiket **iki dönem sonra**
geldiğinde bir dönemin isabetinin hangi dönemde bilinebildiğini, bozulmanın olduğu an ile
görüldüğü an arasındaki boşluğu ve o boşlukta kaç tahminin **ölçülmeden** üretildiğini sayar.
