---
title: 'Olasılık Kalibrasyonu'
source: 'https://academia.sh/tr/kurslar/denetimli-ogrenme/olasilik-kalibrasyonu'
course: 'Denetimli Öğrenme'
language: tr
updated: '2026-08-17T18:10:19+00:00'
license: 'CC BY-SA 4.0'
---

# Olasılık Kalibrasyonu

Söylenen olasılık ile gerçekleşen oran arasındaki farkın ölçülmesi: doğrusal modelin kalibrasyon hatası 0,0242, sıralaması ona tıpatıp eşit olan keskinleştirilmiş skorunki 0,1512'dir ve iki modelin eğri altındaki alanı da 0,8058'dir. Derinlik 8 ağacın eğitim kümesindeki kalibrasyon hatası tanım gereği 0,0000, sınama kümesinde 0,1435'tir; eğitimden öğrenilen düzeltme eşlemesi birim eşlemeye yakınsar ve hiçbir şey düzeltmez. Doğrulama kümesinden öğrenilen tek değişkenli eşleme keskinleştirilmiş skorun hatasını 0,1512'den 0,0463'e indirir ve eğri altındaki alanı 0,8058'de bırakır.

Önceki dersin tamamı sıralamaya dayanıyordu. Eşik süpürüldü, iki eğri basıldı, işletme noktası
bedel hesabıyla seçildi; hiçbir adımda modelin söylediği sayının kendisinin bir karşılığı olması
gerekmedi. Skorlar kesin artan bir dönüşümden geçirilse sıralama, eğriler ve seçilen abone kümesi
değişmeden kalırdı.

Ama model bir abone için 0,80 dediğinde bu sayı bir şey iddia eder: 0,80 denen abonelerin
yaklaşık yüzde sekseni şüpheli çıkmalıdır. Bu iddia sıralamadan bağımsızdır ve ayrı ölçülür.
**Kalibrasyon**, söylenen olasılık ile gerçekleşen oran arasındaki farktır.

- **MD23.** Kalibrasyon sıralamadan bağımsız bir ölçüdür; iki model aynı sıralamayı verip ayrı
  kalibrasyon hataları üretebilir.
- **MD24.** Olasılıklar beş eşit genişlikte aralığa bölünür. Aralık sayısı bir seçimdir: sayı
  büyüdükçe her aralıktaki abone sayısı düşer ve gerçekleşen oran oynar.
- **MD25.** Kalibrasyon hatası, her aralıkta söylenen olasılıkların toplamı ile gerçekleşen
  şüpheli sayısının mutlak farkı toplanıp gözlem sayısına bölünerek hesaplanır.
- **MD26.** Keskinleştirilmiş skor kesin artan bir dönüşümdür; sıralamayı ve dolayısıyla eğri
  altındaki alanı **tam olarak** korur.
- **MD27.** Düzeltme eşlemesi modelin skorundan başka hiçbir öznitelik görmez; tek girdisi skor,
  iki parametresi eğim ve kaydırmadır. Eğim pozitif kaldığı sürece sıralama değişmez.
- **MD28.** Eşleme **doğrulama kümesinden** öğrenilir; öbür iki küme karşılaştırma için basılır.
- **MD29.** Ağacın yaprak olasılığı o yaprağa düşen eğitim satırlarındaki şüpheli oranıdır; bu
  yüzden ağacın eğitim kümesindeki kalibrasyon hatası tanım gereği sıfırdır.
- **MD30.** Taban çizgisi burada da bir sayı verir: her aboneye eğitim kümesindeki şüpheli oranını
  söyleyen yordam kalibrasyonda ölçülür ve eğri altındaki alanı 0,5000'dir.

## Söylenen ile Gerçekleşen

Kalibrasyon ölçmek için olasılıklar aralıklara bölünür, her aralıkta modelin söylediği ortalama
olasılık ile o aralıktaki abonelerin gerçekleşen şüpheli oranı yan yana yazılır. Bu tabloya
**güvenilirlik eğrisi** denir ve çizilmesi gerekmez, sayı olarak okunur.

```python
# degerlendirme.py — MODELDIR. Kurgu abone tablosu ayni tohumla yeniden uretilir.
import math

TOHUM, ADAY, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, OKUMA = [], {}
for i in range(ADAY):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r = uretec(TOHUM + 7000 + k["no"])
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        OKUMA.setdefault(k["no"], []).append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()

VERI = []
for k in ABONE:
    v = OKUMA.get(k["no"])
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]


def safsizlik(s):
    p = sum(x["supheli"] for x in s) / len(s)
    return 2 * p * (1 - p)


def agac(s, derinlik, alan, enaz=2):        # MODELDIR: karar agaci
    n = len(s)
    p = sum(x["supheli"] for x in s) / n
    en = None
    if derinlik and n >= 2 * enaz and 0.0 < p < 1.0:
        for a in alan:
            d = sorted({x[a] for x in s})
            for v in (d[1:] if len(d) < 10 else
                      [d[int(i * len(d) / 10)] for i in range(1, 10)]):
                sol = [x for x in s if x[a] < v]
                sag = [x for x in s if x[a] >= v]
                if min(len(sol), len(sag)) < enaz:
                    continue
                k = safsizlik(s) - (len(sol) * safsizlik(sol) + len(sag) * safsizlik(sag)) / n
                if en is None or k > en[0]:
                    en = (k, a, v, sol, sag)
    if en is None or en[0] <= 1e-9:
        return {"p": p}
    return {"alan": en[1], "esik": en[2], "sol": agac(en[3], derinlik - 1, alan, enaz),
            "sag": agac(en[4], derinlik - 1, alan, enaz)}


def olasilik(d, x):
    while "p" not in d:
        d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"]
    return d["p"]


def dogrusal(egt, alan, w, tur=300, adim=0.5):   # MODELDIR: egim temelli dogrusal model
    o = {a: sum(x[a] for x in egt) / len(egt) for a in alan}
    s = {a: (sum((x[a] - o[a]) ** 2 for x in egt) / len(egt)) ** 0.5 or 1.0 for a in alan}
    f = lambda x: [(x[a] - o[a]) / s[a] for a in alan]
    k, b = [0.0] * len(alan), 0.0
    X = [f(x) for x in egt]
    y = [x["supheli"] for x in egt]
    a = [(w if x["supheli"] else 1.0) for x in egt]
    n = sum(a)
    for _ in range(tur):
        gk, gb = [0.0] * len(alan), 0.0
        for i, xi in enumerate(X):
            z = b + sum(k[j] * xi[j] for j in range(len(k)))
            e = (1 / (1 + math.exp(-max(-30.0, min(30.0, z)))) - y[i]) * a[i]
            gb += e
            for j in range(len(k)):
                gk[j] += e * xi[j]
        b -= adim * gb / n
        for j in range(len(k)):
            k[j] -= adim * gk[j] / n

    def skor(x):
        v = f(x)
        z = b + sum(k[j] * v[j] for j in range(len(k)))
        return 1 / (1 + math.exp(-max(-30.0, min(30.0, z))))
    return skor


S = dogrusal(EGT, ALAN, 1.0)        # MODELDIR: olasilik ureten egim temelli dogrusal model
ARALIK = 5


def guvenilirlik(skor, veri, n=ARALIK):     # her aralikta sayim, soylenen, gerceklesen
    kova = [[0, 0.0, 0] for _ in range(n)]
    for x in veri:
        p = skor(x)
        k = kova[min(n - 1, int(p * n))]
        k[0], k[1], k[2] = k[0] + 1, k[1] + p, k[2] + x["supheli"]
    return kova


def kal_hata(skor, veri, n=ARALIK):         # aralik agirlikli ortalama mutlak fark
    return sum(abs(k[1] - k[2]) for k in guvenilirlik(skor, veri, n)) / len(veri)


def guvenilirlik_bas(ad, skor, veri):
    print(f"{ad}  (kalibrasyon hatasi {kal_hata(skor, veri):.4f})")
    for i, k in enumerate(guvenilirlik(skor, veri)):
        if k[0]:
            print(f"  {i / ARALIK:.1f}-{(i + 1) / ARALIK:.1f}  abone {k[0]:>3}  "
                  f"soylenen {k[1] / k[0]:.4f}  gerceklesen {k[2] / k[0]:.4f}  "
                  f"fark {k[1] / k[0] - k[2] / k[0]:+.4f}")


guvenilirlik_bas("dogrusal model, sinama kumesi", S, SIN)
```

```
dogrusal model, sinama kumesi  (kalibrasyon hatasi 0.0242)
  0.0-0.2  abone 152  soylenen 0.0891  gerceklesen 0.1053  fark -0.0161
  0.2-0.4  abone  53  soylenen 0.2837  gerceklesen 0.3019  fark -0.0182
  0.4-0.6  abone  23  soylenen 0.4918  gerceklesen 0.4783  fark +0.0136
  0.6-0.8  abone  16  soylenen 0.7079  gerceklesen 0.6250  fark +0.0829
  0.8-1.0  abone   8  soylenen 0.8698  gerceklesen 1.0000  fark -0.1302
```

İlk üç aralıkta fark 0,02 düzeyinin altında ve kalibrasyon hatası 0,0242. Son iki aralık daha
oynak, çünkü orada toplam 24 abone var: 0,6-0,8 aralığında model 0,7079 söylerken 0,6250
gerçekleşiyor, 0,8-1,0 aralığında 0,8698 söylerken sekiz abonenin sekizi de şüpheli çıkıyor.
Sekiz aboneden hesaplanan bir oranın 0,13 sapması ölçünün kendi oynaklığıdır; aralık sayısı
büyüdükçe bu oynaklık büyür, küçüldükçe tablo körleşir.

## Sıralaması İyi, Kalibrasyonu Kötü

Skorlar kesin artan bir dönüşümden geçirilirse hiçbir abonenin sırası değişmez. Sıralamaya
dayanan her ölçü sabit kalır; kalibrasyon kalmaz.

```python
def alan_roc(skor, veri):                   # esitlikleri ortalayan sira toplami
    p = sorted(((skor(x), x["supheli"]) for x in veri))
    P = sum(y for _, y in p)
    t, i = 0.0, 0
    while i < len(p):
        j = i
        while j < len(p) and p[j][0] == p[i][0]:
            j += 1
        t += (i + j + 1) / 2.0 * sum(y for _, y in p[i:j])
        i = j
    return (t - P * (P + 1) / 2) / (P * (len(p) - P))


def keskin(p, g=3.0):                       # kesin artan, siralamayi degistirmeyen donusum
    return p ** g / (p ** g + (1 - p) ** g)


K = lambda x: keskin(S(x))                  # MODELDIR: keskinlestirilmis skor
T8 = agac(EGT, 8, ALAN)                     # MODELDIR: derinlik 8 karar agaci
TABAN = sum(x["supheli"] for x in EGT) / len(EGT)
print(f"{'model':<20}{'ROC':>8}{'kal.hata':>10}{'ort skor':>10}{'supheli orani':>15}")
for ad, s in (("dogrusal", S), ("keskinlestirilmis", K),
              ("agac d8", lambda x: olasilik(T8, x)),
              ("taban (egitim orani)", lambda x: TABAN)):
    print(f"{ad:<20}{alan_roc(s, SIN):>8.4f}{kal_hata(s, SIN):>10.4f}"
          f"{sum(s(x) for x in SIN) / len(SIN):>10.4f}"
          f"{sum(x['supheli'] for x in SIN) / len(SIN):>15.4f}")
print()
guvenilirlik_bas("keskinlestirilmis skor, sinama kumesi", K, SIN)
```

```
model                    ROC  kal.hata  ort skor  supheli orani
dogrusal              0.8058    0.0242    0.2309         0.2421
keskinlestirilmis     0.8058    0.1512    0.1504         0.2421
agac d8               0.7391    0.1435    0.2586         0.2421
taban (egitim orani)  0.5000    0.0198    0.2222         0.2421

keskinlestirilmis skor, sinama kumesi  (kalibrasyon hatasi 0.1512)
  0.0-0.2  abone 204  soylenen 0.0199  gerceklesen 0.1569  fark -0.1369
  0.2-0.4  abone  10  soylenen 0.3033  gerceklesen 0.3000  fark +0.0033
  0.4-0.6  abone   7  soylenen 0.4756  gerceklesen 0.8571  fark -0.3816
  0.6-0.8  abone   8  soylenen 0.7001  gerceklesen 0.3750  fark +0.3251
  0.8-1.0  abone  23  soylenen 0.9509  gerceklesen 0.7391  fark +0.2117
```

İlk tablonun ilk iki satırı iddianın kanıtı: iki modelin eğri altındaki alanı aynı, 0,8058, çünkü
ikisi 252 aboneyi tıpatıp aynı sırada diziyor. Kalibrasyon hatası ise 0,0242'den 0,1512'ye, altı
katından fazlasına çıkıyor.

Üçüncü satır ayrı bir uyarı taşıyor. Derinlik 8 ağacının ortalama skoru 0,2586, sınama kümesindeki
gerçek şüpheli oranı 0,2421 — aradaki fark yalnız 0,0165. Toplamda doğru görünen bir model aralık
düzeyinde 0,1435 hata veriyor. Ortalamanın tutması kalibrasyon değildir; birbirini götüren aşırı
ve eksik güvenleri gizler.

Dördüncü satır kalibrasyonun tek başına neyi ölçmediğini söylüyor. Her aboneye eğitim kümesinin
şüpheli oranını, 0,2222'yi söyleyen taban çizgisinin kalibrasyon hatası 0,0198 ile tablodaki en
küçük sayıdır; eğri altındaki alanı ise 0,5000, yani sıralaması rastgeleyle aynıdır. Hiçbir şey
öğrenmemiş bir yordam kalibrasyonda birinci olabilir. İki ölçü ayrı sorulara yanıt verir ve
ikisinin de yazılması gerekir.

İkinci tablo keskinleştirilmiş skorun nerede bozulduğunu gösteriyor. En kalabalık aralıkta model
0,0199 söylüyor, gerçekleşen 0,1569 — yedi katından fazla. Üst uçta ise 0,9509 söyleyip 0,7391
gerçekleştiriyor. Model bir yandan aşırı çekingen, bir yandan aşırı güvenli; iki hata ortalamada
bir ölçüde birbirini götürür, aralık düzeyinde ikisi de durur.

## Düzeltme: Tek Değişkenli Bir Eşleme

Bozulma sıralamada değil, skorun sayı değerinde. Düzeltmenin de sıralamaya dokunmaması gerekir:
skoru girdi alan, kesin artan, iki parametreli bir eşleme yeter.

```python
def logit(p, e=1e-6):
    p = min(1 - e, max(e, p))
    return math.log(p / (1 - p))


def esleme(skor, veri, tur=600, adim=0.5):  # MODELDIR: tek degiskenli duzeltme eslemesi
    z = [logit(skor(x)) for x in veri]
    y = [x["supheli"] for x in veri]
    a, b = 1.0, 0.0
    for _ in range(tur):
        ga = gb = 0.0
        for i, zi in enumerate(z):
            e = 1 / (1 + math.exp(-max(-30.0, min(30.0, a * zi + b)))) - y[i]
            ga, gb = ga + e * zi, gb + e
        a, b = a - adim * ga / len(z), b - adim * gb / len(z)
    return lambda x: 1 / (1 + math.exp(-max(-30.0, min(30.0, a * logit(skor(x)) + b)))), a, b


print(f"{'eslemenin ogrenildigi kume':<28}{'a':>8}{'b':>9}{'ROC':>8}{'kal.hata':>10}")
print(f"{'duzeltme yok':<28}{'-':>8}{'-':>9}{alan_roc(K, SIN):>8.4f}"
      f"{kal_hata(K, SIN):>10.4f}")
for ad, kume in (("egitim", EGT), ("dogrulama", DOG), ("sinama", SIN)):
    d, a, b = esleme(K, kume)
    print(f"{ad:<28}{a:>8.4f}{b:>9.4f}{alan_roc(d, SIN):>8.4f}{kal_hata(d, SIN):>10.4f}")
A8 = lambda x: olasilik(T8, x)
d8, a8, b8 = esleme(A8, EGT)
print(f"\nagac d8 kalibrasyon hatasi: egitim {kal_hata(A8, EGT):.4f}, "
      f"dogrulama {kal_hata(A8, DOG):.4f}, sinama {kal_hata(A8, SIN):.4f}")
print(f"egitimden ogrenilen esleme a {a8:.4f} b {b8:.4f}, sinamada kal.hata "
      f"{kal_hata(d8, SIN):.4f}")
```

```
eslemenin ogrenildigi kume         a        b     ROC  kal.hata
duzeltme yok                       -        -  0.8058    0.1512
egitim                        0.3340   0.0015  0.8058    0.0244
dogrulama                     0.3013  -0.3695  0.8058    0.0463
sinama                        0.3038  -0.0043  0.8058    0.0208

agac d8 kalibrasyon hatasi: egitim 0.0000, dogrulama 0.1624, sinama 0.1435
egitimden ogrenilen esleme a 1.0002 b 0.0001, sinamada kal.hata 0.1435
```

Eşlemenin eğimi üç kümede de 0,30 dolayında: keskinleştirme skorları ne kadar uçlara ittiyse,
eşleme o kadarını geri alıyor. Eğri altındaki alan dört satırda da 0,8058 — eğim pozitif olduğu
sürece sıralama değişmez ve düzeltme hiçbir aboneyi yerinden oynatmaz. Kalibrasyon hatası ise
0,1512'den doğrulama kümesiyle 0,0463'e iniyor, yani üçte birine.

Sınama kümesinden öğrenilen eşleme 0,0208 veriyor; bu sayı bir başarım değil, düzeltmenin
ölçüldüğü kümeden öğrenilmiş olmasının sonucudur ve 0,0463 ile arasındaki 0,0255 fark bir kestirim
değil bir iyimserliktir.

Eğitim satırı bu kümede iyi çıkıyor, 0,0244; doğrusal model eğitim kümesine sıkı uymadığı için
oradaki olasılıkları da aşırı güvenli değil. Kuralın gerekçesi son iki satırda. Derinlik 8
ağacının eğitim kümesindeki kalibrasyon hatası 0,0000, sınama kümesinde 0,1435 — ağacın yaprak
olasılığı o yaprağın eğitim oranıdır, dolayısıyla eğitim kümesinde söylenen ile gerçekleşen tanım
gereği eşittir. Eğitimden öğrenilen eşleme eğimi 1,0002, kaydırması 0,0001 buluyor ve sınamadaki
hatayı 0,1435'ten 0,1435'e taşıyor: düzeltilecek bir şey görmemiştir, çünkü baktığı kümede
düzeltilecek bir şey yoktur.

## Özet

- Kalibrasyon, söylenen olasılık ile gerçekleşen oran arasındaki farktır ve olasılıklar aralıklara
  bölünerek ölçülür; doğrusal modelin sınama kümesindeki kalibrasyon hatası 0,0242'dir.
- Kesin artan bir dönüşüm sıralamayı korur: keskinleştirilmiş skorun eğri altındaki alanı da
  0,8058'dir, kalibrasyon hatası ise 0,1512, altı katından fazla.
- Ortalama skorun gerçek orana yakın olması yetmez: derinlik 8 ağacının ortalaması 0,2586, gerçek
  oran 0,2421, aralık düzeyindeki hatası 0,1435. Sabit 0,2222 söyleyen taban çizgisi ise
  kalibrasyonda 0,0198 ile en iyi, eğri altındaki alanda 0,5000 ile en kötüdür.
- Doğrulamadan öğrenilen tek değişkenli eşleme kalibrasyon hatasını 0,1512'den 0,0463'e indirir ve
  eğri altındaki alanı 0,8058'de bırakır; eğim pozitif olduğu için hiçbir sıra değişmez.
- Ağacın eğitim kümesindeki kalibrasyon hatası tanım gereği 0,0000'dır; oradan öğrenilen eşleme
  birim eşlemeye yakınsar ve sınamadaki 0,1435 hatayı olduğu gibi bırakır.

## Sonraki Adım

Dört derste ölçütün her biri sınıflandırma içindi ve hepsi tek bir işlemden çıktı: **sayma**.
Karışıklık matrisi dört sayım, kesinlik ile duyarlılık iki oran, eğriler eşik başına birer sayım
çifti, kalibrasyon aralık başına bir sayım karşılaştırmasıydı. Hedef bir sınıf olduğu için doğru
ile yanlış ayrık iki kutuydu. Aynı kurgu kümede hedef dönem 3 ortalama tüketimi olduğunda
sayılacak bir kutu kalmaz: model 22,40 der, gerçek 26,15'tir ve bu tahmin ne doğru ne yanlıştır.
Sonraki ders ölçüyü **uzaklığa** çevirir ve taban çizgisini eğitim ortalaması olarak yeniden
kurar.
