---
title: 'Eşik Seçimi ve Eğriler'
source: 'https://academia.sh/tr/kurslar/denetimli-ogrenme/esik-secimi-ve-egriler'
course: 'Denetimli Öğrenme'
language: tr
updated: '2026-08-17T18:10:20+00:00'
license: 'CC BY-SA 4.0'
---

# Eşik Seçimi ve Eğriler

Eşiğin oynattığı iki sayının ve eğri altındaki alanın ayrılması: eşik 0,10'dan 0,90'a çıkarken kesinlik 0,3608'den 1,0000'e yükselir, duyarlılık 0,9344'ten 0,0328'e iner ve bedel 182'den 356'ya çıkar. Doksan dokuz eşik adayı arasından doğrulama kümesiyle seçilen 0,16 sınama kümesinde 181 bedel verir, varsayılan 0,50 eşiğinden 86 birim ucuzdur ve sınamadan okunsaydı 7 birim daha iyi görünürdü. Şüpheli oranı 0,2421'den 0,0354'e indirilince işlem karakteristiği eğrisinin altındaki alan 0,8058'den 0,8624'e çıkarken kesinlik–duyarlılık eğrisininki 0,6212'den 0,4124'e iner.

Önceki dersin dört ölçütü de karar eşiği 0,5'te okundu. O eşik modelden gelmez: model bir olasılık
üretir, eşik o olasılığı bir karara çevirir ve dışarıdan verilir. Sıfır virgül beşin tek gerekçesi
iki sınıfın ortasında durmasıdır; şüpheli oranı 0,2421 olan bir kümede bu ortanın niçin doğru yer
olduğunu söyleyen bir şey yoktur.

Bu ders eşiği süpürür: aynı model, aynı sınama kümesi, tek değişen eşik. Kesinlik ile duyarlılık
her eşikte yeniden hesaplanır, **işletme noktası** bir bedel hesabıyla seçilir, süpürmenin
ürettiği iki eğri sayı olarak basılır.

- **MD16.** Model bir olasılık üretir; eşik bu olasılığı karara çevirir ve modelden bağımsızdır.
  Doksan dokuz eşik denenir, 0,01'den 0,99'a; bu dersin ayar bütçesi budur.
- **MD17.** Bedel ilk dersinkidir: işaretlenen her abone için 1 birim saha ziyareti, kaçırılan
  her şüpheli için 6 birim. İşletme noktası **doğrulama kümesinden** seçilir; sınama kümesindeki
  sayı yalnız raporlanır.
- **MD18.** Süpürme boyunca eğitim kümesi, öznitelikler ve model sabit kalır.
- **MD19.** İşlem karakteristiği eğrisinin yatay ekseni yanlış olumlu oranı, dikey ekseni
  duyarlılıktır; kesinlik–duyarlılık eğrisinin yatay ekseni duyarlılık, dikey ekseni kesinliktir.
  Eğriler **çizilmez**, nokta olarak basılır.
- **MD20.** Eğri altındaki alan yamuk kuralıyla hesaplanır ve eşit skorlu gözlemler tek nokta
  sayılır.
- **MD21.** Seyreltilmiş küme sınama kümesindeki şüphelilerin onda birini tutarak kurulur; eğitim
  ve model değişmez. Kalan yedi şüpheliyle yapılan kestirim oynaktır ve tabanıyla okunur.
- **MD22.** Eşik seçimi olasılığın doğru olmasını değil, yalnız **sıralamanın** doğru olmasını
  gerektirir.

## Eşiği Süpürmek

Eşik yükseldikçe model daha az abone işaretler. İşaretlediklerinde daha çok haklı çıkar, ama
kaçırdığı şüpheli sayısı büyür.

```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 matris(skor, veri, esik=0.5):           # do, yo, yn, dn
    m = [0, 0, 0, 0]
    for x in veri:
        m[(0 if x["supheli"] else 1) + (0 if skor(x) >= esik else 2)] += 1
    return m


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


NS = sum(x["supheli"] for x in SIN)
S = dogrusal(EGT, ALAN, 1.0)        # MODELDIR: olasilik ureten egim temelli dogrusal model
ZIYARET, KACAK = 1.0, 6.0


def nokta(skor, veri, e):
    do, yo, yn, dn = matris(skor, veri, e)
    return {"isaretli": do + yo, "do": do, "yoo": yo / (yo + dn), "du": do / (do + yn),
            "k": do / (do + yo) if do + yo else float("nan"),
            "bedel": ZIYARET * (do + yo) + KACAK * yn}


print(f"{'esik':>5}{'isaretli':>9}{'yakalanan':>10}{'yo orani':>9}"
      f"{'duyarlilik':>11}{'kesinlik':>9}{'bedel':>7}")
for e in (0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90):
    n = nokta(S, SIN, e)
    print(f"{e:>5.2f}{n['isaretli']:>9}{n['do']:>10}{n['yoo']:>9.4f}"
          f"{n['du']:>11.4f}{n['k']:>9.4f}{n['bedel']:>7.0f}")
```

```
 esik isaretli yakalanan yo orani duyarlilik kesinlik  bedel
 0.10      158        57   0.5288     0.9344   0.3608    182
 0.20      100        45   0.2880     0.7377   0.4500    196
 0.30       66        34   0.1675     0.5574   0.5152    228
 0.40       47        29   0.0942     0.4754   0.6170    239
 0.50       33        22   0.0576     0.3607   0.6667    267
 0.60       24        18   0.0314     0.2951   0.7500    282
 0.70       17        12   0.0262     0.1967   0.7059    311
 0.80        8         8   0.0000     0.1311   1.0000    326
 0.90        2         2   0.0000     0.0328   1.0000    356
```

İki sütun ters yönde ilerliyor. Eşik 0,10'da model 158 abone işaretliyor, 61 şüphelinin 57'sini
yakalıyor, kesinliği 0,3608. Eşik 0,90'da yalnız 2 abone işaretliyor, ikisinde de haklı, ama
duyarlılık 0,0328. Kesinlik düzgün artmıyor: 0,60'ta 0,7500 iken 0,70'te 0,7059'a iniyor, çünkü
paydası da modelle birlikte küçülüyor. Duyarlılık ise eşikte azalmayan bir işlevdir, paydası
sabittir.

Son sütun kararı veren sütun: bedel 0,10 eşiğinde 182, 0,90 eşiğinde 356. Aradaki 174 birim
tamamen eşiğin ürünüdür; model, öznitelikler ve eğitim kümesi hiç değişmedi.

## İşletme Noktası Bir Bedel Hesabıyla Seçilir

Eşik bir ayar değişkenidir ve kursun kuralı burada da geçerlidir: hangi kümeden okunduğu
yazılmadan seçilmiş sayılmaz.

```python
ESIKLER = [i / 100 for i in range(1, 100)]
bd = min(ESIKLER, key=lambda e: nokta(S, DOG, e)["bedel"])
bs = min(ESIKLER, key=lambda e: nokta(S, SIN, e)["bedel"])
print(f"denenen esik adayi {len(ESIKLER)}, dogrulama kumesi {len(DOG)} abone")
print(f"{'isletme noktasi':<22}{'esik':>6}{'isaretli':>9}{'yakalanan':>10}"
      f"{'dogrulama':>11}{'sinama':>8}")
for ad, e in (("varsayilan", 0.50), ("dogrulamadan secilen", bd),
              ("sinamadan secilen", bs)):
    n = nokta(S, SIN, e)
    print(f"{ad:<22}{e:>6.2f}{n['isaretli']:>9}{n['do']:>10}"
          f"{nokta(S, DOG, e)['bedel']:>11.0f}{n['bedel']:>8.0f}")
```

```
denenen esik adayi 99, dogrulama kumesi 252 abone
isletme noktasi         esik isaretli yakalanan  dogrulama  sinama
varsayilan              0.50       33        22        205     267
dogrulamadan secilen    0.16      121        51        160     181
sinamadan secilen       0.13      138        55        173     174
```

Doğrulama kümesindeki doksan dokuz adayın en ucuzu 0,16 eşiğidir ve o kümede 160 birim tutar; aynı
eşik sınama kümesinde 181 birim veriyor. Varsayılan 0,50 eşiği ise 267 birim: eşiği seçmek 86
birim, üçte bire yakın bir kazanç sağlıyor ve bu kazanç modelden değil, çıktısının nasıl
okunduğundan geliyor.

Üçüncü satır seçimin kaynağını ölçüyor. Sınama kümesindeki en küçük bedel 0,13 eşiğinde, 174
birim. Aradaki 7 birim, seçimi sınama kümesinden okuyan birinin fazladan iyi görünen payıdır —
küçük bir sayıdır çünkü bedel eğrisi eşiğe göre yayvandır, ama işareti hep aynı yöndedir.

## İki Eğri ve Dengesizlik

Süpürme iki eğri üretir. **İşlem karakteristiği eğrisi (ROC)** yanlış olumlu oranına karşı
duyarlılığı gösterir; **kesinlik–duyarlılık eğrisi** duyarlılığa karşı kesinliği. Farkları şüpheli
oranı değiştiğinde ortaya çıkar.

```python
def egri(skor, veri):               # ROC ve kesinlik-duyarlilik noktalari
    p = sorted(((skor(x), x["supheli"]) for x in veri), key=lambda t: -t[0])
    P = sum(y for _, y in p)
    N = len(p) - P
    do = yo = i = 0
    n = [(0.0, 0.0, 1.0)]
    while i < len(p):
        j = i
        while j < len(p) and p[j][0] == p[i][0]:
            j += 1
        d = sum(y for _, y in p[i:j])
        do, yo, i = do + d, yo + (j - i) - d, j
        n.append((yo / N, do / P, do / (do + yo)))
    return n


def alan_roc(n, sinir=1.0):         # yamuk kurali; sinir yanlis olumlu oranini kirpar
    return sum((min(b[0], sinir) - a[0]) * (a[1] + b[1]) / 2
               for a, b in zip(n, n[1:]) if a[0] < sinir) / sinir


def alan_kd(n):                     # duyarlilik ekseninde basamak toplami
    return sum((b[1] - a[1]) * b[2] for a, b in zip(n, n[1:]))


SEY = [x for i, x in enumerate(SIN) if not x["supheli"] or i % 10 == 0]
sabit = lambda x: 0.5
print(f"{'sinama kumesi':<15}{'satir':>6}{'supheli':>8}{'oran':>7}{'ROC':>8}{'KD':>8}"
      f"{'sabit ROC':>10}{'sabit KD':>9}")
for ad, v in (("gercek dagilim", SIN), ("seyreltilmis", SEY)):
    n, s, ns = egri(S, v), egri(sabit, v), sum(x["supheli"] for x in v)
    print(f"{ad:<15}{len(v):>6}{ns:>8}{ns / len(v):>7.4f}{alan_roc(n):>8.4f}"
          f"{alan_kd(n):>8.4f}{alan_roc(s):>10.4f}{alan_kd(s):>9.4f}")
for h in (0.50, 0.70):
    r = [nokta(S, v, max(e for e in ESIKLER if nokta(S, v, e)["du"] >= h))["k"]
         for v in (SIN, SEY)]
    print(f"duyarlilik {h:.2f} ustunde kesinlik: gercek dagilim {r[0]:.4f}, "
          f"seyreltilmis {r[1]:.4f}")
```

```
sinama kumesi   satir supheli   oran     ROC      KD sabit ROC sabit KD
gercek dagilim    252      61 0.2421  0.8058  0.6212    0.5000   0.2421
seyreltilmis      198       7 0.0354  0.8624  0.4124    0.5000   0.0354
duyarlilik 0.50 ustunde kesinlik: gercek dagilim 0.5161, seyreltilmis 0.2500
duyarlilik 0.70 ustunde kesinlik: gercek dagilim 0.4624, seyreltilmis 0.1667
```

İki eğri ters yönde hareket ediyor. Şüpheli oranı 0,2421'den 0,0354'e inince işlem karakteristiği
eğrisinin altındaki alan 0,8058'den 0,8624'e **çıkıyor**, kesinlik–duyarlılık eğrisininki
0,6212'den 0,4124'e **iniyor**. Yükselişin bir bölümü yedi şüpheliyle yapılan kestirimin
oynaklığıdır; asıl mesele son iki sütunda. Sabit skorlu yordamın işlem karakteristiği eğrisi her
iki kümede de 0,5000 verir; bu eğrinin tabanı şüpheli oranına bakmaz. Öteki eğrinin tabanı ise
doğrudan şüpheli oranıdır.

Son iki satır bunun işletmedeki karşılığı. Duyarlılık 0,50'nin üstünde tutulduğunda kesinlik
gerçek dağılımda 0,5161, seyreltilmiş kümede 0,2500; 0,70'in üstünde tutulduğunda 0,4624'e karşı
0,1667. Alan 0,86 okurken, şüphelilerin yarısını yakalamak için işaretlenen her dört aboneden
üçü boşa gidiyor. Dengesiz kümede yanıltıcı olan eğri, tabanı dengesizlikle birlikte hareket
etmeyen eğridir.

## Tek Sayının Sakladığı

Eğri altındaki alan bütün eşikleri tek sayıda toplar ve toplarken iki şeyi düşürür: hangi eşikte
çalışıldığını ve eğrinin hangi bölgesinin işe yaradığını.

```python
T3 = agac(EGT, 3, ALAN)                    # MODELDIR: derinlik 3 karar agaci
S1 = dogrusal(EGT, ["ort_tuketim"], 1.0)   # MODELDIR: tek oznitelikli dogrusal model
print(f"{'model':<22}{'ROC':>8}{'yo<0.10':>9}{'KD':>8}{'en iyi bedel':>14}"
      f"{'farkli skor':>12}")
for ad, s in (("dogrusal, 12 alan", S), ("agac d3, 12 alan", lambda x: olasilik(T3, x)),
              ("dogrusal, ort_tuketim", S1)):
    n = egri(s, SIN)
    print(f"{ad:<22}{alan_roc(n):>8.4f}{alan_roc(n, 0.10):>9.4f}{alan_kd(n):>8.4f}"
          f"{min(nokta(s, SIN, e)['bedel'] for e in ESIKLER):>14.0f}"
          f"{len({round(s(x), 12) for x in SIN}):>12}")
```

```
model                      ROC  yo<0.10      KD  en iyi bedel farkli skor
dogrusal, 12 alan       0.8058   0.3364  0.6212           174         252
agac d3, 12 alan        0.7222   0.2553  0.4485           197           8
dogrusal, ort_tuketim   0.7138   0.3008  0.5589           213         241
```

Asıl okuma son iki satırda. İki modelin işlem karakteristiği alanı 0,7222 ile 0,7138, arada 0,0084
var — bu ölçüye göre neredeyse eşitler. Öbür üç sütun aynı fikirde değil: kesinlik–duyarlılık
alanında tek öznitelikli model 0,1104 puan önde, yanlış olumlu oranının 0,10 altında kaldığı
bölgede 0,0455 puan önde, en iyi bedelde 16 birim geride. Üç okuma, üç ayrı kazanan.

Sekiz ayrı skor üreten derinlik 3 ağacı ile 241 ayrı skor üreten tek öznitelikli model eğri
üzerinde bambaşka ilerler: biri sekiz büyük basamak, öteki yüzlerce küçük adım. Alan ikisini de
aynı sayıya sıkıştırır. Kursun kuralına burada bir madde eklenir: hangi eşikte çalışılacağı
yazılmadan eğri altındaki alan bir işletme kararına çevrilemez.

## Özet

- Eşik yükseldikçe duyarlılık azalmayan biçimde düşer ama kesinlik düzgün artmaz: 0,60 eşiğinde
  0,7500 olan kesinlik 0,70 eşiğinde 0,7059'a iner. Doksan dokuz eşik adayı bedeli 182 ile 356
  arasında oynatır; model ve eğitim kümesi hiç değişmez.
- Doğrulamadan seçilen 0,16 eşiği sınamada 181 birim verir, varsayılan 0,50 eşiğinden 86 birim
  ucuzdur; aynı seçim sınamadan okunsaydı 7 birim daha iyi görünürdü.
- Şüpheli oranı 0,2421'den 0,0354'e inince işlem karakteristiği alanı 0,8058'den 0,8624'e çıkar,
  kesinlik–duyarlılık alanı 0,6212'den 0,4124'e iner; birinci eğrinin tabanı her iki kümede
  0,5000, ikincisininki şüpheli oranının kendisidir.
- İşlem karakteristiği alanı 0,0084 farkla eşit sayılan iki model, kesinlik–duyarlılık alanında
  0,1104 ve en iyi bedelde 16 birim ayrışır.

## Sonraki Adım

Bu dersin tamamı **sıralamaya** dayandı. Eşik süpürüldü, eğriler basıldı, işletme noktası seçildi;
hiçbirinde modelin söylediği sayının kendisinin doğru olması gerekmedi. Bütün skorlar artan bir
işlevden geçirilse sıralama değişmez, iki eğri aynı kalır, işletme noktası aynı aboneleri
işaretler. Oysa model bir abone için 0,80 dediğinde bu sayının bir karşılığı olmalıdır: 0,80 denen
abonelerin yaklaşık yüzde sekseni şüpheli çıkmalıdır. Sonraki ders söylenen olasılık ile
gerçekleşen oranı aralık aralık yan yana basar, sıralaması iyi kalibrasyonu kötü bir modelin
varlığını gösterir ve düzeltmeyi yalnız doğrulama kümesinden öğrenilen tek değişkenli bir eşleme
olarak yazar.
