ML Temelleri · Modül 2 · 31 dakika

Lojistik regresyon

Regresyon (regression) modellerinin çıktısı bir sayıdır, örneğin kira, sıcaklık ya da fiyat. Bir e-postanın spam olup olmadığını ya da bir öğrencinin sınavı geçip geçmeyeceğini tahmin etmek sınıflandırma (classification) işidir. Sınıflandırmada çıktı bir sayı değil, bir sınıftır.

Bu derste şunları yapacaksın:

  • Modelin skorunu, her sayıyı 0 ile 1 arasına sıkıştıran sigmoidsigmoid: Her gerçek sayıyı 0 ile 1 arasına sıkıştıran S biçimli fonksiyon; lojistik regresyonda ham skoru olasılığa çevirir. fonksiyonuyla olasılığa çevireceksin.
  • Olasılığı bir sınıfa dönüştüren eşiği (threshold) ve karar sınırını (decision boundary)karar sınırı (decision boundary): Modelin iki sınıf arasında kararsız kaldığı noktaların kümesi; lojistik regresyonda ham skorun 0 olduğu doğru ya da düzlem. öğreneceksin.
  • Ortalama kare hatanın (mean squared error, MSE)ortalama kare hata (mean squared error, MSE): Tahminlerle hedef değerler arasındaki farkların karelerinin ortalaması. Büyük hataları küçüklerden daha ağır cezalandırır. bu iş için neden yetmediğini göreceksin.
  • Yerine çapraz entropiyi (cross-entropy)çapraz entropi (cross-entropy): Modelin doğru sınıfa verdiği olasılığın eksi logaritması; emin olup yanılan tahminleri çok ağır cezalandıran bir sınıflandırma kaybı. kuracaksın.
  • Doğruluğun (accuracy) neden yanıltabildiğini göreceksin.
  • Kesinlik (precision)kesinlik (precision): Modelin pozitif dediği örneklerin kaçının gerçekten pozitif olduğunu gösteren oran. ile duyarlılığın (recall)duyarlılık (recall): Gerçekte pozitif olan örneklerin kaçının model tarafından yakalandığını gösteren oran. neyi ölçtüğünü öğreneceksin.

Skordan karara

Doğrusal bir skor, sigmoid ile olasılığa, eşikle de sınıfa dönüşür.

Bir öğrencinin sınavı geçip geçmediğini, o hafta çalıştığı saate bakarak tahmin edelim. Çalışılan saat, modelin tek özniteliği (feature)öznitelik (feature): Bir örneği tanımlayan ve modele girdi olarak verilen ölçülebilir değerlerden biri. olsun. Etiket (label) y=1y = 1 geçti, y=0y = 0 kaldı demek.

Doğrusal skor

Doğrusal regresyondaki gibi bir skor hesaplarız: z=wx+bz = wx + b. Burada ww ağırlık (weight)ağırlık (weight): Bir girdiyle çarpılarak onun çıktıya ne kadar katkıda bulunacağını belirleyen parametre. Doğrusal modelde her özniteliğin kendi ağırlığı vardır., bb ise sapma (bias)sapma (bias): Girdilerle çarpılmadan çıktıya eklenen parametre. Doğrusal modelde bütün öznitelikler 0 iken modelin verdiği tahmindir..

w=1,5w = 1{,}5 ve b=−4,5b = -4{,}5 ile skor şöyle çıkar:

  • 4 saat çalışan biri için z=1,5z = 1{,}5.
  • 2 saat çalışan biri için z=−1,5z = -1{,}5.
  • 10 saat çalışan biri için z=10,5z = 10{,}5.

Aynı hesabı NumPy ile yap:

import numpy as npw, b = 1.5, -4.5hours = np.array([2, 4, 10])z = w * hours + bprint(z)                      # → [-1.5  1.5 10.5]

Sigmoid

Skor 0 ile 1 arasında kalmadığı için olasılık gibi okunamaz. Her skoru 0 ile 1 arasına taşıyan düzgün bir fonksiyon isteriz. Bu işi sigmoid görür:

σ(z)=11+e−z\sigma(z) = \frac{1}{1 + e^{-z}}

Sigmoid şöyle davranır:

  • zz çok büyükse e−ze^{-z} sıfıra yaklaşır ve σ(z)\sigma(z) 1’e yaklaşır.
  • zz çok negatifse e−ze^{-z} çok büyür ve σ(z)\sigma(z) 0’a yaklaşır.
  • z=0z = 0 ise e0=1e^0 = 1 olur ve sonuç tam 0,50{,}5‘tir.

Öğrenci örneğinde şu değerleri elde edersin:

Saat (xx)Skor (z=1,5x−4,5z = 1{,}5x - 4{,}5)Olasılık (σ(z)\sigma(z))
1−30,05
2−1,50,18
300,50
41,50,82
530,95

Skor arttıkça olasılık da artar. Tablo simetriktir, çünkü σ(−z)=1−σ(z)\sigma(-z) = 1 - \sigma(z). Örneğin 2 ve 4 saatin olasılıkları 0,18+0,82=10{,}18 + 0{,}82 = 1 eder.

Tabloyu ve simetriyi kodda yeniden üret:

def sigmoid(z):    return 1 / (1 + np.exp(-z))hours = np.array([1, 2, 3, 4, 5])p = sigmoid(w * hours + b)print(np.round(p, 2))                   # → [0.05 0.18 0.5  0.82 0.95]print(sigmoid(-1.5) + sigmoid(1.5))     # → 1.0

Matematikte çıktı hiçbir zaman tam 0 ya da 1 olmaz. Bilgisayarda olabilir; bunu “Sayılar taşınca” bölümünde göreceksin.

Çıktıyı olasılık gibi okuruz ve ona p^\hat{p} deriz. p^\hat{p}, modelin “label 1” diye verdiği olasılıktır. Label’ın 0 olma olasılığı 1−p^1 - \hat{p} olur.

Birden çok feature

Birden çok feature olduğunda skor, doğrusal regresyondaki tahminin aynısıdır. Sigmoid her örneğe ayrı ayrı uygulanır:

z=Xw+b,p^=σ(z)\mathbf{z} = X\mathbf{w} + b, \qquad \hat{\mathbf{p}} = \sigma(\mathbf{z})

İki feature’lı bir örnek kuralım. x1x_1 çalışılan saat, x2x_2 çözülen deneme sınavı sayısı olsun.

w1=1w_1 = 1, w2=2w_2 = 2 ve b=−6b = -6 seçelim. Skor z=x1+2x2−6z = x_1 + 2x_2 - 6 olur.

Üç öğrenci X’in satırları olsun: 4 saat ve 2 deneme, 1 saat ve 1 deneme, 2 saat ve 2 deneme. X @ w her satır için x1w1+x2w2x_1 w_1 + x_2 w_2 hesaplar:

X = np.array([[4, 2],              [1, 1],              [2, 2]])w = np.array([1.0, 2.0])b = -6.0z = X @ w + bp = sigmoid(z)print(z)                      # → [ 2. -3.  0.]print(np.round(p, 2))         # → [0.88 0.05 0.5 ]

Ham skorlar (logits)

Sigmoid’e girmeden önceki z\mathbf{z} değerlerine ham skorlar (logits)ham skorlar (logits): Bir sınıflandırma modelinin sigmoid ya da softmax uygulanmadan önceki çıktıları; lojistik regresyonda doğrusal kısmın verdiği skor. denir. Doğrusal kısım logit’i verir, sigmoid onu olasılığa çevirir. Sigmoid’in tersi şudur:

z=ln⁡p^1−p^z = \ln\frac{\hat{p}}{1 - \hat{p}}

Yani logit, p^\hat{p} ile 1−p^1 - \hat{p} oranının logaritmasıdır. Logits adı buradan gelir.

Üç öğrencinin olasılıklarından logit’lere geri dön:

print(np.round(np.log(p / (1 - p)), 2))   # → [ 2. -3.  0.]

Lojistik regresyon modeli

Doğrusal bir logit’i sigmoid’den geçirerek kurulan modele lojistik regresyon (logistic regression) denir. Modelin tamamı iki satırdır:

# önceki bloktaki w = [1, 2] ve b = -6 iledef predict_proba(X, w, b):    return sigmoid(X @ w + b)         # logit, sonra sigmoidx_new = np.array([[3, 1]])           # 3 saat, 1 denemeprint(np.round(predict_proba(x_new, w, b), 2))   # → [0.27]

Adındaki regresyon yanıltmasın. Model bir olasılık, yani sürekli bir sayı tahmin eder. Sınıfı bu olasılıktan çıkarırız.

Eşik

Olasılık bir karara dönüşmelidir. Bunun için bir eşik seçersin; en yaygını 0,50{,}5‘tir. p^≥0,5\hat{p} \geq 0{,}5 ise model sınıf 1, değilse sınıf 0 tahmin eder.

Sigmoid z=0z = 0‘da 0,50{,}5 verir ve hep artar. Bu yüzden kural, logit’in işaretine bakmakla aynıdır:

p^≥0,5  ⟺  z≥0\hat{p} \geq 0{,}5 \iff z \geq 0

Öğrenci örneğinde iki kural aynı sınıfları verir:

w, b = 1.5, -4.5hours = np.array([1, 2, 3, 4, 5])z = w * hours + bp = sigmoid(z)print((p >= 0.5).astype(int))             # → [0 0 1 1 1]print(np.array_equal(p >= 0.5, z >= 0))   # → True

Karar sınırı

Öğrenci örneğinde 1,5x−4,5=01{,}5x - 4{,}5 = 0 denkleminden x=3x = 3 saat çıkar. 3 saat ve daha fazla çalışan geçer, daha azı kalır. Logit’in tam 0 olduğu noktalar iki sınıfı ayırır ve decision boundary adını alır.

Tek feature’da decision boundary bir noktadır. Sınırı −b/w-b / w ile bulursun:

w, b = 1.5, -4.5boundary = -b / w             # logit'in 0 olduğu noktaprint(boundary)               # → 3.0

Aynı w=1,5w = 1{,}5 ve b=−4,5b = -4{,}5 ile 14 öğrenciye bakalım. Her öğrencinin çalışma saati ve sonucu (1 geçti, 0 kaldı) bellidir. Sınır 3 saat olduğundan model 3 saat ve üstüne “geçer” der.

hours = np.array([0.7, 1.4, 2.0, 2.5, 3.2, 3.9, 5.0, 2.8, 3.6, 4.3, 4.8, 5.6, 6.4, 7.3])passed = np.array([0] * 7 + [1] * 7)pred = (1.5 * hours - 4.5 >= 0).astype(int)print(pred)                       # → [0 0 0 0 1 1 1 0 1 1 1 1 1 1]print(np.sum(pred == passed))     # → 10

14 öğrencinin 10’u doğru sınıflanır. Yanlış olanlar 3,2, 3,9 ve 5,0 saat çalışıp kalanlar ile 2,8 saat çalışıp geçendir. Veri bir doğruyla tam ayrılmaz.

Aşağıda sigmoid eğrisini sürükle: orta noktası decision boundary’yi, öbür tutamaç ww‘yi değiştirir.

sigmoid_fit
00,51012345678çalışılan saatp̂y = 1 · geçtiy = 0 · kaldısınır −b/w = 3,0 saat

p̂ = σ(1,5·x − 4,5)

Doğruluk10 / 14
İkili çapraz entropi (BCE)0,544
Karar sınırı −b/w3,0 saat

doğruluk 0,71 · BCE 0,544

İki feature’da decision boundary

İki feature’da decision boundary bir doğrudur. Önceki örnekte logit z=x1+2x2−6z = x_1 + 2x_2 - 6 idi.

Sınır ise x1+2x2=6x_1 + 2x_2 = 6 doğrusudur. Üç öğrenciye bakalım:

  • 4 saat ve 2 deneme: z=2z = 2 ve p^≈0,88\hat{p} \approx 0{,}88. Öğrenci geçer.
  • 1 saat ve 1 deneme: z=−3z = -3 ve p^≈0,05\hat{p} \approx 0{,}05. Öğrenci kalır.
  • 2 saat ve 2 deneme: z=0z = 0. Öğrenci tam sınırdadır.

Kodda sınıfları bul. Sonra sınırdaki noktaları kur: her x2x_2 için x1=6−2x2x_1 = 6 - 2x_2 alırsan logit 0 çıkar.

X = np.array([[4, 2], [1, 1], [2, 2]])w = np.array([1.0, 2.0])b = -6.0print((X @ w + b >= 0).astype(int))     # → [1 0 1]x2 = np.array([0.0, 1.0, 2.0, 3.0])X_edge = np.stack([6 - 2 * x2, x2], axis=1)   # iki sütunu yan yana koyprint(X_edge @ w + b)                   # → [0. 0. 0. 0.]print(sigmoid(X_edge @ w + b))          # → [0.5 0.5 0.5 0.5]

Sınır her zaman düzdür

Sınır her zaman düzdür, çünkü x⋅w+b=0\mathbf{x}\cdot\mathbf{w} + b = 0 denklemi x\mathbf{x}‘in doğrusal bir ifadesidir. Feature sayısına göre sınır şöyle olur:

  • Üç feature’da sınır bir düzlemdir.
  • Daha fazla feature’da sınır bir hiperdüzlemdir (hyperplane).

0,5 eşiğiyle lojistik regresyon, logit’in işaretine bakan doğrusal bir sınıflandırıcıdır. Sigmoid o logit’e bir olasılık anlamı verir.

Düz bir sınır her veriyi ayıramaz. İç içe iki halka gibi bir dağılımı hiçbir doğru ikiye bölemez.

Çare bu modelleri üst üste koymaktır. Nöronlar ve aktivasyonlar dersinde bir nöronun (neuron) tam olarak bu model olduğunu göreceksin.

Eşiği değiştirmek

Eşiği 0,50{,}5‘ten başka bir değere çekmek sınırı kendine paralel kaydırır. Bunu son bölümde kullanacaksın.

Eşik 0,80{,}8 ise sınır, σ(z)=0,8\sigma(z) = 0{,}8 olan noktaya kayar. Orada logit ln⁡(0,8/0,2)\ln(0{,}8 / 0{,}2) değerine eşittir. Öğrenci örneğinde sınır 3 saatten yaklaşık 3,923{,}92 saate geçer:

w, b = 1.5, -4.5hours = np.array([1, 2, 3, 4, 5])p = sigmoid(w * hours + b)threshold = 0.8z_edge = np.log(threshold / (1 - threshold))   # yeni sınırda logitprint(round(z_edge, 3))                  # → 1.386print(round((z_edge - b) / w, 2))        # → 3.92print((p >= threshold).astype(int))      # → [0 0 0 1 1]
Kısa soruTek feature'lı bir lojistik regresyonda weight 2, bias −6 ve eşik 0,5. Decision boundary hangi x değerindedir?

Cevabı göster

x = 3. Sınır, logit'in sıfır olduğu yerdir. Logit 2 çarpı x eksi 6'dır; sıfıra eşitlersen x = 3 çıkar. Orada sigmoid tam 0,5 verir.

Hangi kayıp?

Modeli eğitmek için bir kayıp (loss) gerekir, ama ilk akla gelen MSE bu iş için yetmez.

MSE ve MAE neden yetmez

Doğrusal regresyondaki MSE, label ile p^\hat{p} arasındaki farkın karesidir. Label’ı y=1y = 1 olan bir örneğe bakalım:

  • Model p^=0,1\hat{p} = 0{,}1 derse hata 0,90{,}9, kare hata 0,810{,}81 olur.
  • Model p^=0,01\hat{p} = 0{,}01 derse doğru sınıfa verdiği olasılık on kat küçülür. Kare hata yalnızca 0,980{,}98 olur.

Ortalama mutlak hata (mean absolute error, MAE) de aynı yerde takılır. p^=0,1\hat{p} = 0{,}1 için 0,90{,}9, p^=0,01\hat{p} = 0{,}01 için 0,990{,}99 çıkar. İkisinin cezası da 1’de tavan yapar, çünkü p^\hat{p} ile yy arasındaki fark en çok 1 olabilir.

MSE ve MAE, yanlışta emin olmayı yeterince cezalandırmaz. Oysa p^=0,01\hat{p} = 0{,}01, “neredeyse kesin olarak sınıf 0” demektir. Modelin bunun bedelini ağır ödemesini isteriz.

Eksi logaritma

İstediğimiz ceza, doğru sınıfa verilen olasılık 0’a yaklaşırken sınırsız büyümelidir. Eksi logaritma bunu yapar. −ln⁡1=0-\ln 1 = 0 olur ve −ln⁡p^-\ln\hat{p} olasılık küçüldükçe büyür.

Aşağıdaki tabloda label’ı 1 olan bir örnek için üç loss yan yana durur. Tek örnekte MSE, kare hatanın kendisidir.

p^\hat{p}MSEMAE−ln⁡p^-\ln\hat{p}
0,90,010,10,105
0,50,250,50,693
0,10,810,92,303
0,010,9800,994,605

p^\hat{p} on kat küçüldükçe −ln⁡p^-\ln\hat{p} her seferinde ln⁡10≈2,3\ln 10 \approx 2{,}3 artar. Eğri 0’a yaklaşırken sonsuza gider. MSE ile MAE ise 1’de kalır.

Tabloyu kodda üret. Son satır, p^\hat{p} on kat küçüldükçe artışın hep ln⁡10\ln 10 olduğunu gösterir:

p = np.array([0.9, 0.5, 0.1, 0.01])        # y = 1 iken doğru sınıfın olasılığıprint(np.round((p - 1) ** 2, 3))           # → [0.01 0.25 0.81 0.98]print(np.round(np.abs(p - 1), 2))          # → [0.1  0.5  0.9  0.99]print(np.round(-np.log(p), 3))             # → [0.105 0.693 2.303 4.605]print(np.round(np.diff(-np.log([0.1, 0.01, 0.001])), 3))   # → [2.303 2.303]  (np.diff: komşu farklar)

İkili çapraz entropi

Bunu iki label’ı birden kapsayan tek bir formüle çevirelim:

L=−[ yln⁡p^+(1−y)ln⁡(1−p^) ]L = -\bigl[\,y \ln\hat{p} + (1 - y)\ln(1 - \hat{p})\,\bigr]

Formül, label’a göre bir terimi eler:

  • y=1y = 1 iken ikinci terim 0 ile çarpılıp yok olur ve −ln⁡p^-\ln\hat{p} kalır.
  • y=0y = 0 iken ilk terim yok olur ve −ln⁡(1−p^)-\ln(1 - \hat{p}) kalır.

Yani formül, doğru sınıfa verilen olasılığın eksi logaritmasıdır. Bu loss’a ikili çapraz entropi (binary cross-entropy) denir. NN örnekte, MSE’de olduğu gibi, örnek başına loss’ların ortalamasını alırsın:

L=−1N∑i=1N[ yiln⁡p^i+(1−yi)ln⁡(1−p^i) ]L = -\frac{1}{N}\sum_{i=1}^{N}\Bigl[\,y_i \ln\hat{p}_i + (1 - y_i)\ln(1 - \hat{p}_i)\,\Bigr]

Formül her örneğin loss’unu hesaplar ve ortalamasını alır. Modelin doğru label’lara verdiği olasılıklar yükseldikçe ortalama düşer.

Dört örnekle dene: ikisinin label’ı 1, ikisinin 0. Son örnek yanlış ve oldukça emin:

y = np.array([1, 1, 0, 0])p = np.array([0.9, 0.6, 0.2, 0.7])per_sample = -(y * np.log(p) + (1 - y) * np.log(1 - p))print(np.round(per_sample, 3))       # → [0.105 0.511 0.223 1.204]print(round(per_sample.mean(), 3))   # → 0.511

Üç kaybı karşılaştır

Aşağıdaki grafikte üç loss’u kaydırıcıyla karşılaştır. Şunları dene:

loss_compare

Kayıp karşılaştırması · loss comparison · MSE, MAE ve ikili çapraz entropi

00,250,50,75101234p̂kayıpMSEMAE−ln p̂

y = 1 · p̂ = 0,80 · MSE = 0,040 · MAE = 0,200 · ikili çapraz entropi = 0,223

  • y=1y = 1 ile başla ve p^\hat{p} kaydırıcısını 1’den 0’a doğru çek. MSE ve MAE 1’de dururken binary cross-entropy fırlar.
  • y=0y = 0‘a geç. Bu kez yanlış olan uç p^=1\hat{p} = 1 olur.

İpucu

  1. Kaydırıcıyı p^=0,5\hat{p} = 0{,}5‘e getir. Üç loss da y=1y = 1 ve y=0y = 0 için aynı değeri verir, çünkü model hangi sınıfı seçeceğini bilmiyor.
  2. Oradan iki yana çek. Doğru tarafta üçü de sıfıra iner. Yanlış tarafta binary cross-entropy ötekilerden ayrılır.

MSE’nin ikinci, daha ciddi bir sorunu gradyandadır. Bunu “Gradyan ve eğitim” bölümünde hesaplayacaksın.

Kısa soruLabel'ı 0 olan bir örnekte model, label'ın 1 olma olasılığını 0,99 olarak tahmin ediyor. Binary cross-entropy bu örnek için yaklaşık kaç çıkar?

Cevabı göster

Yaklaşık 4,6. Doğru sınıf 0'dır ve ona verilen olasılık 1 eksi 0,99, yani 0,01'dir. Bunun eksi logaritması yaklaşık 4,6 çıkar.

Sayılar taşınca

Formüller doğrudur, ama bilgisayar sayıları sonlu bir aralıkta tutar ve bu aralık iki yerde işi bozar.

Sigmoid’de taşma

Birincisi sigmoid’deki e−ze^{-z}‘dir. z=−1000z = -1000 olursa bilgisayar e1000e^{1000} hesaplar.

Bu sayı float64’ün tutabildiği en büyük değeri (yaklaşık 1,8×103081{,}8 \times 10^{308}) aşar. Sonuç inf olur. Buna taşma (overflow) denir.

NumPy bu bloklarda bir RuntimeWarning basar ama hesaba devam eder.

print(np.finfo(np.float64).max)   # float64'ün sınırları; → 1.7976931348623157e+308print(np.exp(709.0))              # → 8.218407461554972e+307print(np.exp(710.0))              # → infz = -1000.0print(1 / (1 + np.exp(-z)))       # → 0.0

Burada 1/(1+∞)=01 / (1 + \infty) = 0 çıkar. Sonuç doğrudur, ama ara adımda bir inf oluşur. Bu formülde inf zararsız kalır; aynı fonksiyonun başka bir yazılışında kalmaz.

Sigmoid’in ikinci yazılışı

Pay ve paydayı eze^{z} ile çarparsan sigmoid’i başka biçimde yazarsın:

σ(z)=11+e−z=ez1+ez\sigma(z) = \frac{1}{1 + e^{-z}} = \frac{e^{z}}{1 + e^{z}}

İki biçim matematikte aynı sayıyı verir. Farkı, exp’e büyük bir sayı verdikleri yerdedir:

  • İlki zz büyük ve negatifken exp’e büyük bir sayı verir. Sonuç yine de 0 çıkar.
  • İkincisi zz büyük ve pozitifken exp’e büyük bir sayı verir. Pay ve payda birden inf olur ve inf / inf = nan çıkar.

İkinci biçimi z=1000z = 1000 ile dene:

z = 1000.0print(np.exp(z) / (1 + np.exp(z)))   # → nan

Kararlı sigmoid

Sayısal kararlılık (numerical stability), aynı matematiği bilgisayarın tuttuğu sayı aralığında kalacak biçimde yazmaktır. Sigmoid için yol, exp’e hiçbir zaman büyük pozitif bir sayı vermemektir.

İki biçimden zz‘nin işaretine göre uygun olanı seç:

  • z≥0z \geq 0 ise ilk biçimi kullan. Üs −z-z negatiftir ve e−ze^{-z} küçülür.
  • z<0z < 0 ise ikinci biçimi kullan. Üs zz negatiftir ve eze^{z} küçülür.

Kodda iki biçim de exp(-abs(z)) değerini kullanır. Bu değer hiçbir zaman taşmaz. np.where iki dalı da hesaplar; ortak e her ikisinde güvenli olduğu için hiçbir dal taşmaz.

def sigmoid(z):                  # öncekinin yerini alır    e = np.exp(-np.abs(z))       # üs hiçbir zaman pozitif olmaz    return np.where(z >= 0, 1 / (1 + e), e / (1 + e))z = np.array([-1000.0, -2.0, 0.0, 2.0, 1000.0])print(sigmoid(z))   # → [0.         0.11920292 0.5        0.88079708 1.        ]

Dikkat

Tek bir nan yeter. Bir örneğin p^\hat{p} değeri nan ise şunlar olur:

  • Gradyanın her bileşeni nan olur.
  • Tek bir güncellemede bütün weight’ler nan’a döner.

Eğitim hata vermeden sessizce bozulur.

Logaritma ve kırpma

İkinci tuzak logaritmada. Aşırı bir logit, sigmoid’in çıktısını tam 1’e ya da tam 0’a yuvarlayabilir:

  • 1 tarafında z=40z = 40 yeterlidir. e−40e^{-40} o kadar küçüktür ki 1+e−401 + e^{-40} bilgisayarda tam 1 olur.
  • Sıfır tarafında float64 çok daha küçük sayıları tutabilir. Tam 0, ancak z≈−746z \approx -746 gibi çok daha uç bir logit’te çıkar.
print(1 + np.exp(-40.0) == 1.0)      # → Truefor z in [40.0, -745.0, -746.0]:    print(z, sigmoid(z))# → 40.0 1.0# → -745.0 5e-324# → -746.0 0.0

Kararlı bir sigmoid bu tuzağı kaldırmaz. O da yeterince uç logit’lerde tam 0 ya da tam 1 verir.

Bu yuvarlama loss’u iki biçimde bozar:

  • y=1y = 1 iken p^=0\hat{p} = 0 olursa loss −ln⁡0=∞-\ln 0 = \infty çıkar.
  • Daha sinsisi y=1y = 1 iken p^=1\hat{p} = 1 olmasıdır. Loss 0 olmalı, ama formülün ikinci terimi 0⋅ln⁡00 \cdot \ln 0 olur ve sonuç nan çıkar. Model doğru ve emin olduğu hâlde bu olur.
def raw_loss(p, y):                    # kırpmasız formül    return -(y * np.log(p) + (1 - y) * np.log(1 - p))y = np.array([1])print(raw_loss(np.array([0.0]), y))    # → [inf]print(raw_loss(np.array([1.0]), y))    # → [nan]

Çare, olasılığı [ϵ,1−ϵ][\epsilon, 1 - \epsilon] aralığına kırpmaktır (clipping):

p^←min⁡(max⁡(p^,ϵ), 1−ϵ)\hat{p} \leftarrow \min\bigl(\max(\hat{p}, \epsilon),\ 1 - \epsilon\bigr)

ϵ\epsilon, 10−1210^{-12} gibi küçük bir sabittir. Kırpma iki şey yapar:

  • p^\hat{p}‘nın hiçbir zaman tam 0 ya da 1 olmasına izin vermez.
  • En kötü loss’u −ln⁡ϵ≈27,6-\ln\epsilon \approx 27{,}6 ile sınırlar.

Kırpmalı binary cross-entropy şöyle yazılır:

def binary_cross_entropy(p, y, eps=1e-12):    p = np.clip(p, eps, 1 - eps)         # p tam 0 ya da 1 olamaz    return float(-np.mean(y * np.log(p) + (1 - y) * np.log(1 - p)))y = np.array([1])print(round(binary_cross_entropy(np.array([0.0]), y), 1))   # → 27.6print(f"{binary_cross_entropy(np.array([1.0]), y):.1e}")    # → 1.0e-12

ϵ\epsilon‘u çok küçük seçersen (10−2010^{-20} gibi) 1−ϵ1 - \epsilon bilgisayarda yine tam 1 olur. Kırpma üst uçta işe yaramaz:

print(1 - 1e-20 == 1.0)               # → True

Yukarıdaki grafikte y=1y = 1 seç ve kaydırıcıyı en sola, p^=0,01\hat{p} = 0{,}01‘e çek. Binary cross-entropy 4,64{,}6 okunur; bu, tablodaki değerdir. Kaydırıcı burada durur. Daha küçük p^\hat{p}‘de eğri sınırsız tırmanırdı; kırpma onu −ln⁡ϵ≈27,6-\ln\epsilon \approx 27{,}6‘da keser.

Kısa soruz = 800 için sigmoid'i exp(z) / (1 + exp(z)) biçiminde hesaplıyorsun. Ne çıkar?

Cevabı göster

nan çıkar. exp(800) float64'ün sınırını aşar ve inf olur. Pay da payda da inf olduğundan inf bölü inf, yani nan çıkar.

Gradyan ve eğitim

Sigmoid ve logaritma araya girer, ama gradyan yine doğrusal regresyondaki biçime çöker.

Zincir kuralı

Doğrusal regresyon dersinde MSE’nin gradyanı şu çıkmıştı:

2NX⊤(y^−y)\frac{2}{N}X^\top(\hat{\mathbf{y}} - \mathbf{y})

Tek bir örnekle hesaplayalım. Şunları tanımlayalım:

z=x⋅w+b,p^=σ(z),L=−[yln⁡p^+(1−y)ln⁡(1−p^)]z = \mathbf{x}\cdot\mathbf{w} + b, \qquad \hat{p} = \sigma(z), \qquad L = -\bigl[y \ln\hat{p} + (1 - y)\ln(1 - \hat{p})\bigr]

Zincir şöyledir:

  • LL, p^\hat{p}‘ya bağlıdır.
  • p^\hat{p}, zz‘ye bağlıdır.
  • zz, w\mathbf{w} ve bb‘ye bağlıdır.

Böyle iç içe geçmiş bir zincirde türev, her halkanın türevlerinin çarpımıdır. Buna zincir kuralı (chain rule) denir. Geri yayılım dersi bunu ayrıca işler.

Loss’un türevi

Önce loss’un p^\hat{p}‘ya göre türevini al:

∂L∂p^=−yp^+1−y1−p^=p^−yp^(1−p^)\frac{\partial L}{\partial \hat{p}} = -\frac{y}{\hat{p}} + \frac{1 - y}{1 - \hat{p}} = \frac{\hat{p} - y}{\hat{p}(1 - \hat{p})}

Son eşitlik, iki kesri ortak paydada toplamaktan gelir:

  • Payda p^(1−p^)\hat{p}(1 - \hat{p}) olur.
  • Pay −y(1−p^)+(1−y)p^=p^−y-y(1 - \hat{p}) + (1 - y)\hat{p} = \hat{p} - y kalır.

Formülü merkezi farkla (central difference) kontrol et. Bu yöntemi Gradyan inişi dersinde görmüştün:

def loss(p, y):    return -(y * np.log(p) + (1 - y) * np.log(1 - p))p, y, h = 0.1, 1.0, 1e-6numeric = (loss(p + h, y) - loss(p - h, y)) / (2 * h)formula = (p - y) / (p * (1 - p))print(round(numeric, 4), round(formula, 4))   # → -10.0 -10.0

Sigmoid’in türevi

Sonra sigmoid’in türevini al:

dp^dz=e−z(1+e−z)2=11+e−z⋅e−z1+e−z=p^ (1−p^)\frac{d\hat{p}}{dz} = \frac{e^{-z}}{(1 + e^{-z})^2} = \frac{1}{1 + e^{-z}} \cdot \frac{e^{-z}}{1 + e^{-z}} = \hat{p}\,(1 - \hat{p})

Son adımda şunu kullandık:

1−p^=e−z1+e−z1 - \hat{p} = \frac{e^{-z}}{1 + e^{-z}}

Sigmoid’in eğimi, p^\hat{p} ile 1−p^1 - \hat{p} çarpımına eşittir:

  • p^=0,5\hat{p} = 0{,}5‘te en büyüktür (0,250{,}25).
  • p^\hat{p} 0’a ya da 1’e yaklaştıkça sıfıra iner.

Kodda z=0z = 0 noktasında kontrol et:

# önceki bloktaki sigmoid ilez, h = 0.0, 1e-6numeric = (sigmoid(z + h) - sigmoid(z - h)) / (2 * h)p = sigmoid(z)print(round(numeric, 4), p * (1 - p))     # → 0.25 0.25

Türevleri çarpmak

İki türevi çarpınca paydadaki çarpan gider:

∂L∂z=p^−yp^(1−p^)⋅p^(1−p^)=p^−y\frac{\partial L}{\partial z} = \frac{\hat{p} - y}{\hat{p}(1 - \hat{p})} \cdot \hat{p}(1 - \hat{p}) = \hat{p} - y

Sayıyla kontrol et. y=1y = 1 ve p^=0,1\hat{p} = 0{,}1 olsun:

  1. Loss’un türevini al: ∂L/∂p^=−1/0,1=−10\partial L / \partial \hat{p} = -1 / 0{,}1 = -10.
  2. Sigmoid’in eğimini al: 0,1⋅0,9=0,090{,}1 \cdot 0{,}9 = 0{,}09.
  3. İkisini çarp: −0,9-0{,}9 çıkar. Bu, p^−y=0,1−1\hat{p} - y = 0{,}1 - 1 ile tam olarak aynıdır.
y, p = 1.0, 0.1dL_dp = -y / p + (1 - y) / (1 - p)      # loss'un türevidp_dz = p * (1 - p)                     # sigmoid'in eğimiprint(round(dL_dp, 4), round(dp_dz, 4), round(dL_dp * dp_dz, 4))   # → -10.0 0.09 -0.9print(round(p - y, 4))                  # → -0.9

Parametrelerin gradyanı

Geriye zz‘nin parametrelere göre türevi kalır. ∂z/∂w=x\partial z / \partial \mathbf{w} = \mathbf{x} ve ∂z/∂b=1\partial z / \partial b = 1 olur.

Bir örnek için gradyan (p^−y) x(\hat{p} - y)\,\mathbf{x} ve p^−y\hat{p} - y olur. NN örnekte ortalamasını alırsın:

∇wL=1NX⊤(p^−y),∂L∂b=1N∑i=1N(p^i−yi)\nabla_{\mathbf{w}} L = \frac{1}{N} X^\top(\hat{\mathbf{p}} - \mathbf{y}), \qquad \frac{\partial L}{\partial b} = \frac{1}{N}\sum_{i=1}^{N}(\hat{p}_i - y_i)

Formülü şöyle oku:

  • w\mathbf{w} için her örneğin hatasını p^i−yi\hat{p}_i - y_i o örneğin feature’larıyla çarpıp ortalarsın.
  • bb için çarpan yoktur; hataları doğrudan ortalarsın.

Bu, doğrusal regresyondaki gradyanla aynı biçimdir: tahmin eksi label, çarpı feature. Fark iki şeydedir:

  • Tahmin p^=σ(Xw+b)\hat{\mathbf{p}} = \sigma(X\mathbf{w} + b) olur.
  • 2 çarpanı kalkar.

Bu sadeleşme sigmoid ve binary cross-entropy birlikte seçildiği için olur: sigmoid’in türevi ile loss türevinin paydası birbirini götürür.

Formülü bir fonksiyona dök ve üç öğrencili örnekte dene. Label’lar 1,0,11, 0, 1 olsun:

def gradient(X, y, w, b):    p = sigmoid(X @ w + b)    error = p - y                     # tahmin eksi label    grad_w = X.T @ error / len(y)    grad_b = np.mean(error)    return grad_w, grad_bX = np.array([[4, 2], [1, 1], [2, 2]])y = np.array([1, 0, 1])w, b = np.array([1.0, 2.0]), -6.0grad_w, grad_b = gradient(X, y, w, b)print(np.round(grad_w, 3), round(grad_b, 3))   # → [-0.476 -0.397] -0.191

Bir gradyan adımı

Dört örnekle bir adım atalım. x=1,2,3,4x = 1, 2, 3, 4 ve label’lar 0,0,1,10, 0, 1, 1 olsun:

  1. w=0w = 0 ve b=0b = 0 ile başla.
  2. Her logit 0 olur, bu yüzden her örnekte p^=0,5\hat{p} = 0{,}5 çıkar.
  3. Hataları p^−y\hat{p} - y ile hesapla: 0,5; 0,5; −0,5; −0,50{,}5;\ 0{,}5;\ -0{,}5;\ -0{,}5.

Bu tek katmanlı modelde sıfırdan başlamak sorun çıkarmaz. Sinir ağlarında çıkarır; bunu ileride göreceksin.

Gradyan:

∂L∂w=14(1⋅0,5+2⋅0,5+3⋅(−0,5)+4⋅(−0,5))=−0,5,∂L∂b=14(0,5+0,5−0,5−0,5)=0\frac{\partial L}{\partial w} = \tfrac{1}{4}\bigl(1 \cdot 0{,}5 + 2 \cdot 0{,}5 + 3 \cdot (-0{,}5) + 4 \cdot (-0{,}5)\bigr) = -0{,}5, \qquad \frac{\partial L}{\partial b} = \tfrac{1}{4}(0{,}5 + 0{,}5 - 0{,}5 - 0{,}5) = 0

Öğrenme oranı (learning rate)öğrenme oranı (learning rate): Gradyan inişinde atılan adımın büyüklüğü. Çok küçükse eğitim yavaşlar, çok büyükse kayıp büyür. η=0,5\eta = 0{,}5 ile w←0−0,5⋅(−0,5)=0,25w \leftarrow 0 - 0{,}5 \cdot (-0{,}5) = 0{,}25 olur. bb yerinde kalır. Adımın sonucu şöyledir:

  • Yeni olasılıklar yaklaşık 0,56; 0,62; 0,68; 0,730{,}56;\ 0{,}62;\ 0{,}68;\ 0{,}73 olur.
  • Loss 0,6930{,}693‘ten 0,6250{,}625‘e iner.
  • Label’ı 0 olan ilk iki örneğin p^\hat{p} değeri 0,50{,}5‘ten 0,560{,}56 ve 0,620{,}62‘ye çıktı, yani biraz kötüleşti. Loss’u label’ı 1 olan örnekler düşürdü. Decision boundary hâlâ x=0x = 0‘dadır, çünkü bb ilk adımda kıpırdamadı.

Sonraki adımda ∂L/∂b\partial L / \partial b pozitif çıkar ve bb‘yi negatife çeker.

Aynı adımı gradient ile at:

X = np.array([[1.0], [2.0], [3.0], [4.0]])y = np.array([0, 0, 1, 1])w, b, lr = np.zeros(1), 0.0, 0.5grad_w, grad_b = gradient(X, y, w, b)print(grad_w, grad_b)                  # → [-0.5] 0.0print(round(binary_cross_entropy(sigmoid(X @ w + b), y), 3))   # → 0.693w = w - lr * grad_wb = b - lr * grad_bp = sigmoid(X @ w + b)print(w, b)                            # → [0.25] 0.0print(np.round(p, 2))                  # → [0.56 0.62 0.68 0.73]print(round(binary_cross_entropy(p, y), 3))   # → 0.625

Eğitim döngüsü

Geri kalan, gradyan inişiyle (gradient descent)gradyan inişi (gradient descent): Kaybı azaltmak için parametreleri gradyanın tersine küçük adımlarla güncelleyen yöntem. doğrusal regresyonda yaptığının aynısıdır:

  1. Tahmin et.
  2. Gradyanı hesapla.
  3. w\mathbf{w} ve bb‘yi η\eta ile güncelle.
  4. Bunu epoch’lar, yani veri kümesi (dataset)veri kümesi (dataset): Her biri öznitelikler ve bir hedef değerden oluşan örneklerin tamamı. üzerinden turlar boyunca tekrarla.

Mini yığınlar (mini-batch) ve öznitelik ölçekleme (feature scaling) de aynı biçimde geçerlidir. Ölçeksiz feature’lar burada da loss yüzeyini uzatır. Eğitimden sonra sınıfı p^≥0,5\hat{p} \geq 0{,}5 eşiğiyle tahmin edersin.

Döngünün tamamı bir fonksiyondur. Fonksiyon eğitim kümesiyle w\mathbf{w} ve bb‘yi öğrenir, sonra X_test için sınıfları döndürür:

def train(X, y, X_test, lr, epochs):    n, d = X.shape    w = np.zeros(d)    b = 0.0    for _ in range(epochs):        p = sigmoid(X @ w + b)               # 1. tahmin et        w = w - lr * (X.T @ (p - y)) / n     # 2. gradyan, 3. güncelle        b = b - lr * np.mean(p - y)    p_test = sigmoid(X_test @ w + b)    return (p_test >= 0.5).astype(int)       # eşik: 0,5X = np.array([[1.0], [2.0], [3.0], [4.0]])y = np.array([0, 0, 1, 1])X_test = np.array([[1.5], [2.4], [2.6], [3.5]])print(train(X, y, X_test, lr=0.5, epochs=1000))   # → [0 0 1 1]print(train(X, y, X_test, lr=0.5, epochs=0))      # → [1 1 1 1]

İki çağrının sonucu şöyle okunur:

  • İlk çağrıda veri 2,5 etrafında simetriktir ve sınır 2,5’e yakın bir yere oturur. 2,4 sınıf 0, 2,6 sınıf 1 çıkar.
  • epochs=0 iken her olasılık tam 0,50{,}5 kalır. Eşikte sınıf 1 seçildiği için bütün tahminler 1 çıkar.

MSE ile gradyan

Aynı zinciri MSE ile kuralım. L=(p^−y)2L = (\hat{p} - y)^2 için ∂L/∂p^=2(p^−y)\partial L / \partial \hat{p} = 2(\hat{p} - y) olur. Sigmoid’in eğimiyle çarpılınca sadeleşecek bir şey kalmaz:

∂L∂z=2(p^−y) p^(1−p^)\frac{\partial L}{\partial z} = 2(\hat{p} - y)\,\hat{p}(1 - \hat{p})

p^(1−p^)\hat{p}(1 - \hat{p}) çarpanı, p^\hat{p} 0’a ya da 1’e yaklaşırken sıfıra gider. Label’ı 1 olan bir örnekte zz negatife indikçe iki gradyana bakalım:

zzp^\hat{p}MSE gradyanıBinary cross-entropy gradyanı
00,5−0,25−0,5
−20,119−0,185−0,881
−40,018−0,035−0,982
−60,0025−0,005−0,998

Model ne kadar emin ve yanlışsa MSE’nin gradyanı o kadar küçülür. z=−4z = -4‘te gradyan, z=0z = 0‘dakinin yaklaşık yedide biridir. Binary cross-entropy’de gradyan hata büyüdükçe büyür ve −1-1‘e yaklaşır.

Yani MSE’de en çok yanılan örnek en az düzeltilir. MAE’nin gradyanı da aynı p^(1−p^)\hat{p}(1 - \hat{p}) çarpanını taşır. O da aynı yerde takılır.

Tabloyu kodda üret:

# önceki bloktaki sigmoid ilez = np.array([0.0, -2.0, -4.0, -6.0])p = sigmoid(z)y = 1.0grad_mse = 2 * (p - y) * p * (1 - p)     # sigmoid eğimi gradyanı küçültürgrad_bce = p - y                         # sadeleşmiş gradyanprint(np.round(p, 4))                    # → [0.5    0.1192 0.018  0.0025]print(np.round(grad_mse, 3))             # → [-0.25  -0.185 -0.035 -0.005]print(np.round(grad_bce, 3))             # → [-0.5   -0.881 -0.982 -0.998]print(round(grad_mse[0] / grad_mse[2], 1))   # → 7.2
Kısa soruLabel'ı 0 olan bir örnekte model, label'ın 1 olma olasılığını 0,8 olarak tahmin ediyor. Binary cross-entropy'nin logit'e göre gradyanı kaçtır?

Cevabı göster

0,8. Gradyan tahmin eksi label'dır: 0,8 eksi 0 eşittir 0,8. Model ne kadar emin ve yanlışsa gradyan o kadar büyük olur.

Doğruluk yetmediğinde

Accuracy tek başına yetmez; modelin nerede yanıldığını görmek için hataları türlerine göre saymak gerekir.

Accuracy ve dengesiz sınıflar

Eğitilmiş bir modelin ne kadar iyi olduğunu söylemenin en doğal yolu accuracy’dir. Accuracy, doğru tahminlerin tüm örneklere oranıdır.

100 kişilik bir hastalık taramasında 5 kişinin hasta olduğunu düşün. Herkese “sağlam” diyen bir model 95 kişiyi doğru bilir ve %95 accuracy alır. Ama tek bir hastayı bile bulamaz.

Sorun, sınıfların dengesiz olmasıdır (imbalanced classes). Bir sınıf ötekinden çok daha sık görülünce, çoğunluk sınıfını söylemek bile yüksek accuracy verir.

y = np.array([1] * 5 + [0] * 95)    # 5 hasta, 95 sağlamy_hat = np.zeros(100, dtype=int)    # herkese "sağlam" deprint(np.mean(y_hat == y))          # → 0.95

Karışıklık matrisi

Hata sayımlarının 2×2’lik tablosuna karışıklık matrisi (confusion matrix) denir. Hastaları pozitif sınıf (label 1) sayalım. Dört sayım vardır:

  • doğru pozitif (true positive, TP): model hasta dedi, gerçekte hasta.
  • yanlış pozitif (false positive, FP): model hasta dedi, gerçekte sağlam; yanlış alarm.
  • yanlış negatif (false negative, FN): model sağlam dedi, gerçekte hasta; kaçırılan hasta.
  • doğru negatif (true negative, TN): model sağlam dedi, gerçekte sağlam.

Bir model 20 kişiyi taradı. 7 kişi hasta, 13 kişi sağlam. Model her kişiye bir skor verir ve eşik 0,500{,}50‘dir. Skorlar:

  • hastalar: 0,93; 0,86; 0,78; 0,67; 0,49; 0,41; 0,31;
  • sağlamlar: 0,72; 0,58; 0,46; 0,39; 0,36; 0,33; 0,27; 0,22; 0,17; 0,12; 0,09; 0,05; 0,02.

Sonuç şu tabloda:

Tahmin: hasta (1)Tahmin: sağlam (0)
Gerçekte hasta (1)4 (TP)3 (FN)
Gerçekte sağlam (0)2 (FP)11 (TN)

Accuracy şu çıkar:

TP+TNN=4+1120=0,75\frac{TP + TN}{N} = \frac{4 + 11}{20} = 0{,}75

Herkese “sağlam” diyen modelin accuracy’si 13/20=0,6513/20 = 0{,}65‘tir. Bu model ondan iyi görünür, ama 7 hastanın 3’ünü kaçırdı. İki ayrı ölçüt gerekir.

Kodda skorları kur ve dört sayımı boolean koşullarla say:

y = np.array([1] * 7 + [0] * 13)       # 7 hasta, 13 sağlamscores = np.array([    0.93, 0.86, 0.78, 0.67, 0.49, 0.41, 0.31,                                        # hastalar    0.72, 0.58, 0.46, 0.39, 0.36, 0.33, 0.27, 0.22, 0.17, 0.12, 0.09, 0.05, 0.02,    # sağlamlar])y_hat = (scores >= 0.5).astype(int)tp = np.sum((y_hat == 1) & (y == 1))fp = np.sum((y_hat == 1) & (y == 0))fn = np.sum((y_hat == 0) & (y == 1))tn = np.sum((y_hat == 0) & (y == 0))print(tp, fp, fn, tn)          # → 4 2 3 11print((tp + tn) / len(y))      # → 0.75

Precision ve recall

İki ölçüt şunlardır:

precision=TPTP+FP,recall=TPTP+FN\text{precision} = \frac{TP}{TP + FP}, \qquad \text{recall} = \frac{TP}{TP + FN}

Precisionkesinlik (precision): Modelin pozitif dediği örneklerin kaçının gerçekten pozitif olduğunu gösteren oran. ve recallduyarlılık (recall): Gerçekte pozitif olan örneklerin kaçının model tarafından yakalandığını gösteren oran. şu soruları yanıtlar:

ÖlçütSorduğu soruÖrnekte
PrecisionModelin pozitif dediği örneklerin kaçı gerçekten pozitif?4/6≈0,674/6 \approx 0{,}67
RecallGerçek pozitiflerin kaçı yakalandı?4/7≈0,574/7 \approx 0{,}57

Paydanın 0 olduğu uç durumlar vardır:

  • Hiç pozitif tahmin yoksa precision’ın paydası 0 olur.
  • Hiç gerçek pozitif yoksa recall’un paydası 0 olur.

Bu durumlarda ilgili değer genellikle 0 sayılır.

Fonksiyon sayımları ve iki oranı tek yerde toplar. Herkese “sağlam” diyen model için precision’ın paydası 0 olur:

# önceki bloktaki y ve y_hat iledef precision_recall(y, y_hat):    tp = np.sum((y_hat == 1) & (y == 1))    fp = np.sum((y_hat == 1) & (y == 0))    fn = np.sum((y_hat == 0) & (y == 1))    precision = tp / (tp + fp) if tp + fp > 0 else 0.0   # payda 0 ise 0    recall = tp / (tp + fn) if tp + fn > 0 else 0.0    return float(precision), float(recall)print(precision_recall(y, y_hat))                      # → (0.6666666666666666, 0.5714285714285714)print(precision_recall(y, np.zeros(20, dtype=int)))    # → (0.0, 0.0)

Eşik ve denge

İkisi arasında bir denge var ve onu eşik ayarlar. Eşiği düşürürsen model daha az emin olduğunda bile “hasta” der. Daha çok hasta yakalarsın, ama daha çok yanlış alarm verirsin.

Aynı 20 kişi için üç eşiğe bakalım:

EşikTPFPFNTNPrecisionRecall
0,8205131,000,29
0,5423110,670,57
0,376070,541,00

Tablo iki uçtaki eşiği gösterir:

  • 0,8 eşiğinde model yalnızca çok emin olduğunda hasta der. Hiç yanlış alarm yoktur (precision 1), ama 7 hastadan 5’i kaçar (recall 0,29).
  • 0,3 eşiğinde hiçbir hasta kaçmaz (recall 1), ama 13 “hasta” tahmininin yalnızca 7’si doğrudur.

Aynı skorlarla eşiği üç değere çek:

for threshold in [0.8, 0.5, 0.3]:    y_hat = (scores >= threshold).astype(int)    precision, recall = precision_recall(y, y_hat)    print(threshold, round(precision, 2), round(recall, 2))# → 0.8 1.0 0.29# → 0.5 0.67 0.57# → 0.3 0.54 1.0

Aşağıda eşiği 0’dan 1’e sürükle ve karışıklık matrisiyle precision ve recall’a bak.

threshold_explorer

20 hasta · modelin hasta olasılığı p̂ · p̂ ≥ eşik ise "hasta" der

model: sağlammodel: hasta00,20,40,60,81model skoru p̂ (hasta olasılığı)hasta(pozitif)sağlam(negatif)eşik 0,50
Karışıklık matrisi
Gerçek sınıfTahmin: hastaTahmin: sağlam
Gerçekte hasta4TP3FN
Gerçekte sağlam2FP11TN
Kesinlik (precision)0,67
TP / (TP + FP) = 4 / 6
Duyarlılık (recall)0,57
TP / (TP + FN) = 4 / 7

eşik 0,50 · 6 / 20 kişiye "hasta" dendi · doğruluk 0,75 2 yanlış alarm (FP) · 3 kaçırılan hasta (FN)

Hangisinin önemli olduğu probleme bağlıdır:

  • Hastalık taramasında bir hastayı kaçırmak pahalıdır. Bu yüzden recall yüksek tutulur.
  • Spam filtresinde önemli bir e-postayı spam diye silmek pahalıdır. Bu yüzden precision yüksek tutulur.

Tek bir accuracy sayısı bu seçimi saklar.

Kısa soruBir spam filtresi 20 e-postaya spam dedi; bunların 15'i gerçekten spam. Gelen kutusunda toplam 30 spam vardı. Filtrenin precision ve recall değerleri nedir?

Cevabı göster

Precision 0,75 ve recall 0,5. Precision, spam denilenlerin içinde gerçekten spam olanların oranıdır: 15 bölü 20. Recall, gerçek spam e-postalardan yakalananların oranıdır: 15 bölü 30.

Özet

  • Lojistik regresyon, doğrusal bir logit’i (z=Xw+b\mathbf{z} = X\mathbf{w} + b) sigmoid ile olasılığa çevirir. Eşik (genellikle 0,5) olasılığı sınıfa dönüştürür, decision boundary ise logit’in 0 olduğu doğru ya da düzlemdir.
  • MSE ve MAE, yanlışta emin olmanın cezasını 1’de keser ve sigmoid yüzünden gradyanı sıfıra yaklaştırır. Binary cross-entropy bedeli sınırsız büyütür ve gradyanı p^−y\hat{p} - y olur.
  • Gradyan doğrusal regresyondakiyle aynı biçimdedir: w\mathbf{w} için X⊤(p^−y)X^\top(\hat{\mathbf{p}} - \mathbf{y}) çarpımının 1/N1/N katı, bb için hataların ortalaması. Eğitim döngüsü de aynı kalır, yalnızca tahmin sigmoid’den geçer.
  • Bilgisayarda e−ze^{-z} taşabilir ve ln⁡0\ln 0 sonsuzdur. Sigmoid’i zz‘nin işaretine göre uygun biçimde hesaplamak ve olasılığı ϵ\epsilon ile kırpmak numerical stability sağlar.
  • Accuracy dengesiz sınıflarda yanıltır. Confusion matrix’ten okunan precision (pozitif dediklerinin kaçı doğru) ve recall (gerçek pozitiflerin kaçı yakalandı) hatanın türünü gösterir. Eşik ikisi arasındaki dengeyi ayarlar.

Terimler

TürkçeEnglish
regresyonregression
ağırlıkweight
sapmabias
öznitelikfeature
öğrenme oranılearning rate
gradyan inişigradient descent
veri kümesidataset
mini yığınmini-batch
öznitelik ölçeklemefeature scaling
zincir kuralıchain rule
epochepoch
olasılıkprobability
sınıflandırmaclassification
sigmoidsigmoid
ham skorlarlogits
lojistik regresyonlogistic regression
eşikthreshold
karar sınırıdecision boundary
hiperdüzlemhyperplane
etiketlabel
ortalama kare hatamean squared error, MSE
ortalama mutlak hatamean absolute error, MAE
kayıploss
çapraz entropicross-entropy
ikili çapraz entropibinary cross-entropy
taşmaoverflow
sayısal kararlılıknumerical stability
kırpmaclipping
doğrulukaccuracy
dengesiz sınıflarimbalanced classes
karışıklık matrisiconfusion matrix
doğru pozitiftrue positive (TP)
yanlış pozitiffalse positive (FP)
yanlış negatiffalse negative (FN)
doğru negatiftrue negative (TN)
kesinlikprecision
duyarlılıkrecall

Şimdi sıra sende

  1. Kararlı sigmoidZorluk: KolayBaşla →
  2. İkili çapraz entropiZorluk: OrtaBaşla →
  3. Lojistik regresyon eğitZorluk: ZorBaşla →
  4. Kesinlik ve duyarlılıkZorluk: OrtaBaşla →
İlk problem: Kararlı sigmoid →

Notların

Metinden bir bölüm seçip Not al'a basarak da ekleyebilirsin.

Geri bildirim

Tür