Sıradaki

Sayısal gradyan

Zorluk: Orta

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ı xix_i için şunu hesapla:

∂f∂xi≈f(x+h ei)−f(x−h ei)2h\frac{\partial f}{\partial x_i} \approx \frac{f(\mathbf{x} + h\,\mathbf{e}_i) - f(\mathbf{x} - h\,\mathbf{e}_i)}{2h}

Formülde:

  • Sol taraf, ff‘nin diğer elemanlar sabitken yalnızca xix_i‘ye göre kısmi türevidir (partial derivative). Gradyan, bu kısmi türevleri bir araya getirir.
  • ei\mathbf{e}_i, x\mathbf{x} ile aynı şekle (shape) sahip bir dizidir (array). Yalnızca ii. elemanı 1, diğerleri 0’dır.

Böylece her xix_i için şunu yaparsın:

  1. xix_i‘yi hh kadar artır ve ff‘yi hesapla.
  2. xix_i‘yi hh kadar azalt ve ff‘yi hesapla.
  3. İki sonucun farkını 2h2h‘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:

fkareler(x)=∑ixi2fc¸arpım(x)=x0 x1fsinu¨s(x)=∑isin⁡xi\begin{aligned} f_{\text{kareler}}(\mathbf{x}) &= \sum_i x_i^2 \\ f_{\text{çarpım}}(\mathbf{x}) &= x_0 \, x_1 \\ f_{\text{sinüs}}(\mathbf{x}) &= \sum_i \sin x_i \end{aligned}

Ö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

  • x ile aynı shape’te bir array döndür. x iki boyutlu da olabilir.
  • x tam 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ü: f(x+h ei)−f(x)h\frac{f(\mathbf{x} + h\,\mathbf{e}_i) - f(\mathbf{x})}{h}

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.

FarkBakılan yerHata
Merkezi farkİki yan, eşit uzaklıktah2h^2 ile orantılı
İleri farkYalnızca bir yanhh ile orantılı

Küçük bir hh için merkezi fark çok daha isabetlidir.

hh‘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.

10−510^{-5} 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:

  1. Elemanı hh kadar artır ve f’yi hesapla.
  2. Aynı elemanı hh kadar azalt ve f’yi hesapla.
  3. Elemanı eski değerine geri koy.
  4. İki sonucun farkını 2h2h‘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 xi+hx_i + h‘nin yuvarlanmasını engeller.

Bu problemde bir sorun mu var?

solution.py
import numpy as npdef numerical_gradient(f, x: np.ndarray, h: float = 1e-5) -> np.ndarray:    """f'nin x noktasındaki gradyanını merkezi farklarla yaklaşık olarak hesaplar."""    grad = np.zeros_like(x, dtype=float)    # Kodunu buraya yaz.    return grad

İçindekiler

Geri bildirim

Tür