İkili çapraz entropi
Zorluk: Orta Çözüldükayıp fonksiyonları
Bu problemde iki sınıflı bir sınıflandırmanın (classification) kaybını hesaplarsın. Model, her örnek (sample) için etiketin (label) 1 olma olasılığını tahmin eder. Bu tahminlerin (prediction) ne kadar iyi olduğunu ölçen kayıp fonksiyonu (loss function), ikili çapraz entropidir (binary cross-entropy).
binary_cross_entropy(p, y, eps=1e-12) fonksiyonunu yaz. Girdiler şunlardır:
p: modelin tahmin ettiği olasılıklar ().y: gerçek label’lar (0 ya da 1).
p ve y, şekli (shape) (n,) olan birer dizidir (array). Ortalama loss’u bir float olarak döndür:
Köşeli parantezde şunlar kalır:
- Label 1 ise yalnızca .
- Label 0 ise yalnızca .
Yani loss, doğru sınıfa verilen olasılığın negatif logaritmasıdır. Model doğru sınıfa ne kadar yüksek olasılık verirse loss o kadar küçük olur.
Sorun, tam ya da olduğunda çıkar. olur ve çarpan olsa bile nan verir. Yani kesin ve doğru bir tahmin bile loss’u bozar.
Sayısal kararlılık (numerical stability) için p’yi önce [eps, 1 - eps] aralığına kırp (clip). Böylece logaritmaya hiçbir zaman girmez.
Örnekler
Girdi: p = [0.9, 0.2, 0.8, 0.4], y = [1, 0, 1, 0]
Çıktı: 0.2656183105130591
Girdi: p = [0.0, 1.0, 0.5], y = [1, 0, 1]
Çıktı: 18.651737178127284
Girdi: p = [0.999, 0.001, 0.5, 0.95], y = [1, 1, 0, 0]
Çıktı: 2.649408808357414
İpucu 1
np.clip(p, eps, 1 - eps) iki uçta kırpar:
eps’ten küçük değerlerieps’e çeker.1 - eps’ten büyük değerleri1 - eps’e çeker.
Bu işlem p’yi değiştirmez, yeni bir array döndürür. Sonucu bir değişkene ata ve hem hem için onu kullan.
İpucu 2
İki terim şunu yapar:
y * np.log(p)yalnızca label’ı 1 olan örnekleri sayar.(1 - y) * np.log(1 - p)yalnızca label’ı 0 olanları sayar.
Çünkü her örnekte iki çarpandan biri ‘dır. İkisini topla.
İpucu 3
Logaritmalar negatif ya da sıfırdır. Bu yüzden terimlerin toplamı da öyledir. Şunları yap:
- Başına eksi koy.
np.meanile ortalamayı al.- Sonucu
float(...)ile sade bir Pythonfloat’una çevir.
Gereksinimler
pveyaynı(n,)shape’inde array’lerdir ve en az bir örnek içerir.p’nin değerleri aralığındadır (uçlar dahil).y’nin değerleri 0 ya da 1’dir.- Dönüş değeri tek bir
float: array ya da liste değil. np.mean’in verdiğinp.float64de kabul edilir.float(...)ile çevirmek zorunda değilsin.- Kırpmayı iki uçta da yap,
epsparametresiyle:p’yi[eps, 1 - eps]aralığına çek. ya da iken sonuç sonlu olmalı (nanya dainfdeğil). - Doğal logaritma (
np.log) kullan. Toplamı değil, ortalamayı döndür. p’yi vey’yi değiştirme. Fonksiyon bittiğinde onu çağıran kodun array’leri aynı kalmalı.
Binary cross-entropy, modelin emin olduğu hataları ağır cezalandırır. Label 1 iken loss şöyle değişir:
| Loss | |
|---|---|
| 0,9 | |
| 0,5 | |
| 0,01 |
giderken loss sonsuza büyür. Aynı hatanın ortalama kare hata (mean squared error, MSE) karşılığı en fazla ‘dir.
Kırpma, sonsuz loss’u sınırlı bir sayıya çevirir. Label 1 iken ise loss olur. için bu yaklaşık ‘dır.
Küçük bir gerçekçi olasılıklarda sonucu neredeyse hiç değiştirmez. Çünkü modeller bu kadar uç olasılıkları nadiren verir.
Olasılıklar sigmoid’den (her sayıyı 0 ile 1 arasına sıkıştıran fonksiyon) geliyorsa binary cross-entropy’nin gradyanı (gradient) çok sade çıkar. Loss’un ham skora (logit) göre türevi olur.
Model emin ama yanlışken iki loss farklı davranır:
| Loss (sigmoid ile) | Emin ama yanlışken gradyan |
|---|---|
| Binary cross-entropy | büyüktür, yani güncelleme de büyük olur. |
| MSE | Sıfıra yaklaşır. |
Daha fazlası için Lojistik regresyon dersine bak.
Çözüm üç adımdır:
- Olasılıkları
[eps, 1 - eps]aralığına kırp. - İki terimi topla.
- Toplamın negatif ortalamasını al.
Kodda bu adımlar şöyle görünür:
import numpy as npdef binary_cross_entropy(p: np.ndarray, y: np.ndarray, eps: float = 1e-12) -> float: p = np.clip(p, eps, 1 - eps) return float(-np.mean(y * np.log(p) + (1 - y) * np.log(1 - p)))
Sık yapılan hata, kırpmayı yalnızca bir uçta yapmaktır: np.clip(p, eps, 1).
Bu ‘ı düzeltir. Ama iken np.log(1 - p) yine verir ve loss inf ya da nan olur.
Kırpmayı np.log(p + eps) gibi bir toplamla değiştirmek de aynı sonucu vermez. Toplam değerleri ‘in üstüne taşırır ve kırpmanın tanımladığı sınırı tutmaz.
Bu problemde bir sorun mu var?