Kararlı softmax
Zorluk: Kolay Çözüldüaktivasyon fonksiyonları
Bir sınıflandırma (classification) modeli, her örnek (sample) için sınıfın her birine bir skor verir. Bu ham skorlar (logits) herhangi bir gerçek sayı olabilir.
Softmax, bunları toplamı olan olasılıklara (probability) çeviren fonksiyondur. Skoru büyük olan sınıfın olasılığı da büyük olur.
softmax(logits) fonksiyonunu yaz. logits, şekli (shape) (n, k) olan bir dizidir (array); her satır bir örneğin sınıf için logits’idir.
Softmax’ı her satıra ayrı uygula:
Burada logits, döndüreceğin olasılıklardır.
Formülü olduğu gibi yazarsan büyük skorlarda çöker:
- ,
float’un sınırını aşar. - Bu taşma (overflow)
infverir. inf / inf,nanolur.
Fonksiyon, skorlar çok büyük ya da çok küçük olduğunda da nan ya da inf içermeyen, doğru olasılıklar döndürmeli. Yani sayısal kararlılığı (numerical stability) korumalı.
Dönüş değeri (n, k) shape’inde bir array olmalı. Her satırın toplamı olmalı.
Örnekler
Girdi: logits = [[2.0, 1.0, 0.1], [0.5, 0.5, 0.5]]
Çıktı: array([[0.65900114, 0.24243297, 0.09856589],
[0.33333333, 0.33333333, 0.33333333]])
Girdi: logits = [[1000.0, 1001.0, 1002.0], [-1000.0, -1001.0, -1002.0], [3.0, 3.0, 3.0]]
Çıktı: array([[0.09003057, 0.24472847, 0.66524096],
[0.66524096, 0.24472847, 0.09003057],
[0.33333333, 0.33333333, 0.33333333]])
Girdi: logits = [[-1.0, 0.0, 2.5, -3.0], [4.0, -4.0, 0.0, 1.0]]
Çıktı: array([[2.70496397e-02, 7.35285442e-02, 8.95761045e-01, 3.66077066e-03],
[9.35945596e-01, 3.13974769e-04, 1.71424416e-02, 4.65979874e-02]])
İpucu 1
Taşmaya, exp’in büyük bir argümanla çağrılması yol açar. Tüm skorlardan aynı sayısını çıkarırsan pay da payda da ile çarpılır. Bu çarpan sadeleşir ve olasılıklar değişmez.
‘yi exp’in argümanı hiç pozitif olmayacak biçimde seç.
İpucu 2
Her satırın maksimumunu (n, 1) shape’inde bir sütun olarak al. logits.max(axis=1) her satırın en büyük skorunu verir, ama (n,) shape’inde bir vektör olarak.
Bu vektörü logits’ten çıkarırsan NumPy onu son eksene (axis), yani sütunlara hizalar. Bu işleme yayınlama (broadcasting) denir. n = k ise hata bile vermez, yanlış sonuç verir.
Maksimumu sütuna çevirmenin iki yolu var:
logits.max(axis=1, keepdims=True)yaz.keepdims=True, indirgenen axis’i boyutu 1 olarak korur.logits.max(axis=1).reshape(-1, 1)yaz.
İpucu 3
Maksimumu çıkarıp np.exp aldıktan sonra her satırı kendi toplamına böl. Toplamı da maksimum gibi .sum(axis=1, keepdims=True) ya da .sum(axis=1).reshape(-1, 1) ile sütun olarak al. Böylece bölme her satıra kendi toplamını uygular.
Gereksinimler
logits,(n, k)shape’inde bir float array’idir. Her satır bir örnektir.- Dönüş değeri
logitsile aynı(n, k)shape’inde bir NumPy array’idir. Her satırın toplamı olur, sütunların değil. - Büyük girdilerde (
1000gibi) ve çok küçük girdilerde (-1000gibi) sonuçnanya dainfiçermemeli. - Satırlar birbirinden bağımsızdır. Bir satırın sonucu yalnızca o satırdaki skorlara bağlıdır. Bir satır
1000civarında, başka bir satır-1000civarında olabilir. logits’i değiştirme. Fonksiyon bittiğinde çağıran kodun array’i aynı kalmalı.- Satırlar üzerinde döngü kullanma: birkaç NumPy ifadesi yeter.
Softmax, her skorun üstelini alır ve sonucu toplama böler. Üç sınıflı bir örneğin logits’i olsun:
- Üstel değerleri bul: , ve .
- Toplamlarını al: yaklaşık .
- Her değeri toplama böl: yaklaşık , ve .
Softmax’ın özellikleri şunlardır:
- Skor ne kadar büyükse olasılık o kadar büyüktür.
- Hiçbir olasılık olmaz ve toplamları kalır.
- İki sınıf olduğunda softmax, iki skorun farkına uygulanan sigmoid’e (değerleri ile arasına sıkıştıran fonksiyon) dönüşür.
Tüm skorlara aynı sayıyı eklesen ya da onlardan çıkarsan olasılıklar değişmez. Pay ve paydadaki ortak çarpan sadeleşir. Kararlı sürüm bu özelliğe dayanır.
En büyük skoru çıkarırsan:
- O skor olur ve kalır.
- Geri kalanlar ‘nin negatif üslerine döner. En kötü ihtimalle ‘a yuvarlanır, taşmaz.
- Payda her zaman en az olur, bu yüzden bölme güvenlidir.
Çıkarılan sayıyı her satır için ayrı seç. Bir satırın skorları ötekilerden çok daha küçükse, bütün array’in maksimumunu çıkarmak o satırın bütün üstel değerlerini ‘a yuvarlar. Sonuç olur.
Daha fazlası için Nöronlar ve aktivasyonlar dersine bak.
Üstelden önce satır maksimumunu çıkarmak softmax’ı kararlı yapar.
- Her satırdan kendi maksimumunu çıkar.
- Sonucun üstelini al.
- Her satırı kendi toplamına böl.
keepdims=True, maksimumu ve toplamı (n, 1) shape’inde bir sütun olarak tutar. .reshape(-1, 1) de aynı işi görür.
import numpy as npdef softmax(logits: np.ndarray) -> np.ndarray: shifted = logits - logits.max(axis=1, keepdims=True) exps = np.exp(shifted) return exps / exps.sum(axis=1, keepdims=True)
Sık yapılan üç hata var:
- Maksimumu hiç çıkarmamak: küçük skorlarla doğru çalışır, ilk büyük skorda
nanverir. logits.max()ile bütün array’in maksimumunu çıkarmak: satırların ölçeği farklıysa küçük satırnanolur.- Maksimumu ya da toplamı sütuna çevirmeyi (
keepdims=Trueya dareshape(-1, 1)) unutmak:nilekfarklıysa shape hatası verir. Aynıysa hata vermeden sütunları normalize eder.
Bu problemde bir sorun mu var?