Sayısal gradyan
Zorluk: Orta Çözüldükalkülüs
Gradyanı (gradient) elle türetemediğin bir fonksiyonda bile yaklaşık olarak hesaplayabilirsin. numerical_gradient(f, x, h=1e-5) fonksiyonunu yaz. Fonksiyon, f’nin x noktasındaki gradyanını merkezi farklarla (central differences) bulur.
x’in her elemanı için şunu hesapla:
Formülde:
- Sol taraf, ‘nin diğer elemanlar sabitken yalnızca ‘ye göre kısmi türevidir (partial derivative). Gradyan, bu kısmi türevleri bir araya getirir.
- , ile aynı şekle (shape) sahip bir dizidir (array). Yalnızca . elemanı 1, diğerleri 0’dır.
Böylece her için şunu yaparsın:
- ‘yi kadar artır ve ‘yi hesapla.
- ‘yi kadar azalt ve ‘yi hesapla.
- İki sonucun farkını ‘ye böl.
Diğer elemanlar aynı kalır.
f bir NumPy array’i alır ve tek bir sayı döndürür. Test durumlarında f bir isimle verilir.
Testler bu ismi fonksiyona, x’i de NumPy array’ine çevirir. Sonra ikisini senin fonksiyonuna verir.
Üç isim vardır: 'kareler', 'çarpım' ve 'sinüs'. Fonksiyonları şunlardır:
Örnekler
Girdi: f = 'kareler', x = [1.0, -2.0, 3.0]
Çıktı: array([ 2., -4., 6.])
Girdi: f = 'çarpım', x = [2.0, 5.0]
Çıktı: array([5., 2.])
Girdi: f = 'sinüs', x = [0.0, 1.0, 2.0]
Çıktı: array([ 1. , 0.54030231, -0.41614684])
İpucu 1
x = np.array(x, dtype=float) ile bir kopya al. Elemanları bu kopyada değiştir.
İpucu 2
for i in np.ndindex(x.shape): bir ya da iki boyutlu her array’i tek döngüyle dolaşır. Elemanı değiştirdikten sonra eski değerine geri koymayı unutma.
Gereksinimler
xile aynı shape’te bir array döndür.xiki boyutlu da olabilir.xtam sayılardan oluşan bir array de olabilir. Gradyan yine float olur.x’i değiştirme. Fonksiyon bittiğinde çağıran kodun array’i aynı kalır.- Merkezi farkı kullan. İleri fark (forward difference) testleri geçecek kadar yakın sonuç vermez. İleri farkın formülü:
Türev (derivative), fonksiyonun küçük bir değişime ne kadar tepki verdiğidir. Merkezi fark noktanın iki yanına eşit uzaklıkta bakar. İleri fark yalnızca bir yana bakar.
| Fark | Bakılan yer | Hata |
|---|---|---|
| Merkezi fark | İki yan, eşit uzaklıkta | ile orantılı |
| İleri fark | Yalnızca bir yan | ile orantılı |
Küçük bir için merkezi fark çok daha isabetlidir.
‘yi çok küçültmek de işe yaramaz. Bilgisayar sayıları sınırlı hassasiyetle tutar. Çok yakın iki değerin farkını alırken yuvarlama hatası büyür.
civarı bu iki hatayı dengeler.
Sayısal gradyan yavaştır: her eleman için iki fonksiyon çağrısı gerekir. Ama güvenilirdir, bu yüzden elle yazılmış gradyanları onunla kontrol edersin.
Geri yayılım (backpropagation) dersinde bunu gradyan kontrolü (gradient check) olarak göreceksin.
Daha fazlası için Gradyan inişi dersine bak.
Bir kopya al ve her eleman için iki yana bak. Önce x’in bir kopyasını al. Sonra her eleman için şu adımları tekrarla:
- Elemanı kadar artır ve
f’yi hesapla. - Aynı elemanı kadar azalt ve
f’yi hesapla. - Elemanı eski değerine geri koy.
- İki sonucun farkını ‘ye böl.
import numpy as npdef numerical_gradient(f, x: np.ndarray, h: float = 1e-5) -> np.ndarray: x = np.array(x, dtype=float) grad = np.zeros_like(x) for i in np.ndindex(x.shape): old = x[i] x[i] = old + h f_plus = f(x) x[i] = old - h f_minus = f(x) x[i] = old grad[i] = (f_plus - f_minus) / (2 * h) return grad
np.array(x, dtype=float) iki işi birden yapar:
- Fonksiyonu çağıran kodun array’ini korur.
- Tam sayı array’lerinde ‘nin yuvarlanmasını engeller.
Bu problemde bir sorun mu var?