Sıradaki

Doğrusal regresyon eğit

Zorluk: Zor

doğrusal modelleroptimizasyon

Bu problemde doğrusal regresyonu (linear regression) gradyan inişiyle (gradient descent) eğitirsin. Model, ağırlık (weight) w\mathbf{w} ve sapma (bias) bb ile y^=Xw+b\hat{\mathbf{y}} = X\mathbf{w} + b tahminlerini (prediction) üretir. Kayıp (loss) olarak ortalama kare hatayı (mean squared error, MSE) kullanırsın.

train(X, y, lr=0.1, epochs=100) fonksiyonunu yaz. Girdiler şunlardır:

  • X: şekli (shape) (n, d) olan bir dizi (array). Her satır bir örnek (sample), her sütun bir öznitelik (feature) taşır.
  • y: hedef değerleri (target) içeren, (n,) shape’inde bir vektör.
  • lr: öğrenme oranı (learning rate, η\eta).
  • epochs: epoch sayısı. Bir epoch, veri kümesinin (dataset) tamamı üzerinden bir turdur.

w\mathbf{w}‘yi sıfır vektöründen, bb‘yi 00‘dan başlat. Her epoch’ta tüm örnekleri kullan. Bir epoch şu adımlardan oluşur:

  1. Tahminleri hesapla.
  2. İki gradyanı da aynı tahminlerden hesapla.
  3. İki parametreyi birden güncelle.

Güncelleme şudur:

w←w−η 2NX⊤(y^−y),b←b−η 2N∑i=1N(y^i−yi)\mathbf{w} \leftarrow \mathbf{w} - \eta\,\frac{2}{N}X^\top(\hat{\mathbf{y}} - \mathbf{y}), \qquad b \leftarrow b - \eta\,\frac{2}{N}\sum_{i=1}^{N}(\hat{y}_i - y_i)

Son epoch’tan sonra öğrenilen parametreleri (w, b) biçiminde bir tuple olarak döndür. w, (d,) shape’inde bir array’dir. b bir float’tur.

Örnekler

Girdi: X = [[0.0], [1.0], [2.0], [3.0], [4.0]], y = [1.0, 3.0, 5.0, 7.0, 9.0], lr = 0.05, epochs = 200
Çıktı: (array([2.00021768]), 0.9993794316260418)

Girdi: X = [[1.0, 2.0], [3.0, 1.0], [2.0, 2.0]], y = [3.0, 4.0, 5.0], lr = 0.1, epochs = 1
Çıktı: (array([1.66666667, 1.33333333]), 0.8)

Girdi: X = [[-1.0, 0.5], [0.0, -2.0], [1.5, 1.0], [2.0, -0.5]], y = [-2.0, 1.0, 3.0, 0.5], lr = 0.1, epochs = 50
Çıktı: (array([ 1.04945265, -0.05330975]), -0.04378417163098562)

İpucu 1

Döngünün içine bir epoch’u yaz:

  1. Tahminleri hesapla.
  2. Hatayı hesapla.
  3. İki gradyanı hesapla.
  4. İki parametreyi güncelle.

Gradyan hesabı MSE gradyanı problemindeki hesabın aynısıdır. Sonra bunu epochs kez tekrarla.

İpucu 2

w’yi değiştirmeden önce hem grad_w’yi hem grad_b’yi hesapla. Aksi hâlde b’nin gradyanı, güncellenmiş w’nin tahminlerinden çıkar.

İpucu 3

Küçük bir örnekle kendini kontrol et:

  • X = [[1.0], [2.0]], y = [1.0, 1.0], lr = 0.1 ve bir epoch.
  • Sıfırdan başlayınca hatalar −1-1 ve −1-1, gradyanlar −3-3 ve −2-2 olur.
  • Sonuç w=0,3w = 0{,}3 ve b=0,2b = 0{,}2 çıkmalı.

Gereksinimler

  • X (n, d) ve y (n,) shape’inde array’lerdir. lr pozitif bir float’tur. epochs, 0 ya da daha büyük bir int’tir.
  • (w, b) biçiminde bir tuple döndür. w (d,) shape’inde bir NumPy array’i olmalı, (d, 1) bir sütun değil.
  • b tek bir float’tur. np.sum’ın verdiği np.float64 de kabul edilir.
  • w’yi sıfırlardan, b’yi 0.0’dan başlat. epochs = 0 ise (sıfırlar, 0.0) döndür.
  • Gradyanları, parametreleri güncellemeden önce, aynı tahminlerden hesapla. w’yi güncelleyip tahminleri yeniden hesaplarsan b’nin gradyanı farklı çıkar.
  • Her epoch’ta bütün örnekleri kullanarak tek bir güncelleme yap. Örnek örnek ya da küçük gruplar hâlinde güncelleme yapma.
  • Veriyi olduğu gibi kullan: train içinde ölçekleme ya da başka bir ön işlem yapma.
  • Testlerdeki veriler küçüktür: feature değerleri en fazla 4 civarındadır. lr = 0.1 bu veriler için güvenlidir.
  • Metrekare gibi yüzlerle ölçülen ham feature’larda aynı lr ıraksar (divergence). Böyle bir veriyi train’e vermeden önce kendin ölçekle ya da lr’yi küçült.
  • X’i ve y’yi değiştirme. Fonksiyon bittiğinde onu çağıran kodun array’leri aynı kalmalı.
  • Epoch’lar üzerinde bir for döngüsü kullan. Örnekler üzerinde döngü kullanma.

Gradient descent, loss’u en hızlı artıran yönün tersine küçük adımlar atar. Doğrusal regresyonda gradyanın formülü bilindiği için eğitim kısa bir döngüdür. Döngü üç adımdır:

  1. Tahmin et.
  2. Hatayı ve gradyanı hesapla.
  3. Parametreleri güncelle.

Her epoch tek bir adım atar, çünkü gradyan bütün örneklerden hesaplanır.

Küçük bir örnekte x=(1,2)x = (1, 2), y=(3,5)y = (3, 5) ve η=0,1\eta = 0{,}1 olsun. Parametreler sıfırdan başlar. İki epoch şöyle ilerler:

EpochTahminlerHatalarGradyan (w; b)(w;\ b)Güncellenen (w; b)(w;\ b)
10; 0−3; −5(−13; −8)(-13;\ -8)(1,3; 0,8)(1{,}3;\ 0{,}8)
22,1; 3,4−0,9; −1,6(−4,1; −2,5)(-4{,}1;\ -2{,}5)(1,71; 1,05)(1{,}71;\ 1{,}05)

Bu iki noktadan geçen doğru y^=2x+1\hat{y} = 2x + 1‘dir. Parametreler ona, yani w=2w = 2 ve b=1b = 1‘e doğru ilerler.

Learning rate’i yanlış seçersen iki şey olur:

  • Çok büyükse adımlar minimumu aşar, loss artar ve parametreler ıraksar.
  • Çok küçükse yakınsama (convergence) yavaştır.

Feature’lar büyük ya da çok farklı ölçeklerdeyse aynı learning rate ıraksayabilir ve küçük olanı yavaşlatır. Bu yüzden gerçek veride feature’ları önce ölçeklersin (öznitelik ölçekleme, feature scaling) ve ölçekli veriyi train’e verirsin.

Doğrusal regresyonun çözümü kapalı formda (closed form) da bulunur. Ama gradient descent, kapalı formu olmayan modeller için de çalışan genel yöntemdir.

Daha fazlası için Doğrusal regresyon dersine bak.

Çözüm şu adımlardan oluşur:

  1. Parametreleri sıfırla.
  2. Her epoch’ta hatayı bir kez hesapla.
  3. İki gradyanı bu hatadan çıkar.
  4. İkisini birden uygula.

Kodda bu adımlar şöyle görünür:

import numpy as npdef train(X: np.ndarray, y: np.ndarray, lr: float = 0.1, epochs: int = 100) -> tuple[np.ndarray, float]:    n, d = X.shape    w = np.zeros(d)    b = 0.0    for _ in range(epochs):        error = X @ w + b - y  # y_hat - y        grad_w = 2 / n * (X.T @ error)        grad_b = 2 / n * np.sum(error)        w = w - lr * grad_w        b = b - lr * grad_b    return w, float(b)

Sık yapılan hata, w’yi güncelledikten sonra error’ı yeniden hesaplamaktır. O zaman b’nin gradyanı bu yeni hatadan çıkar. İki gradyan aynı adımın parçasıdır ve aynı tahminlerden gelmelidir.

Sonuç çoğu zaman yine yakınsar, bu yüzden hata fark edilmez. Ama değerler formülle uyuşmaz.

Bu problemde bir sorun mu var?

solution.py
import numpy as npdef train(X: np.ndarray, y: np.ndarray, lr: float = 0.1, epochs: int = 100) -> tuple[np.ndarray, float]:    """Doğrusal regresyonu gradyan inişiyle eğitir; öğrenilen (w, b) çiftini döndürür."""    n, d = X.shape    w = np.zeros(d)    b = 0.0    # Kodunu buraya yaz.    return w, b

İçindekiler

Geri bildirim

Tür