Sıradaki

Momentumlu SGD adımı

Zorluk: Orta

optimizasyon

Momentum, gradyan inişine (gradient descent) bir hafıza ekler. Parametre yalnızca o anki gradyanla değil, önceki adımların yönüyle de itilir. momentum_step(w, v, grad, lr=0.01, beta=0.9) fonksiyonunu yaz. Fonksiyon, momentumlu stokastik gradyan inişinin (SGD with momentum) tek bir güncelleme adımını yapar.

w parametreler, v hız (velocity), grad o anki gradyandır. Üçü de aynı shape’te NumPy array’leridir. β\beta momentum katsayısı, η\eta öğrenme oranıdır (learning rate). Önce hızı, sonra parametreleri güncelle:

vyeni=β v+∇Lwyeni=w−η vyeni\mathbf{v}_{\text{yeni}} = \beta\,\mathbf{v} + \nabla L \qquad \mathbf{w}_{\text{yeni}} = \mathbf{w} - \eta\,\mathbf{v}_{\text{yeni}}

Hız, geçmiş gradyanların üstel olarak azalan bir toplamıdır. β=0\beta = 0 ise hız gradyana eşittir ve bu düz SGD’dir. Fonksiyon (w_yeni, v_yeni) çiftini döndürür.

Örnekler

Girdi: w = [1.0, 2.0], v = [0.5, -1.0], grad = [2.0, 4.0], lr = 0.1, beta = 0.9
Çıktı: (array([0.755, 1.69 ]), array([2.45, 3.1 ]))

Girdi: w = [0.5, -0.5, 1.5], v = [0.0, 0.0, 0.0], grad = [1.0, -2.0, 0.5], lr = 0.5, beta = 0.0
Çıktı: (array([0. , 0.5 , 1.25]), array([ 1. , -2. , 0.5]))

Girdi: w = [[1.0, -2.0], [3.0, 0.0]], v = [[-0.5, 0.25], [1.0, -3.0]], grad = [[-1.0, 2.0], [0.0, -4.0]], lr = 0.05, beta = 0.8
Çıktı: (array([[ 1.07, -2.11], [ 2.96, 0.32]]), array([[-1.4, 2.2], [ 0.8, -6.4]]))

İpucu 1

Önce v_yeni’yi, sonra w_yeni’yi yaz. Formüldeki işlemler eleman bazında (element-wise) olduğu için döngü gerekmez.

İpucu 2

w_yeni satırında v_yeni’yi kullan. Eski v’yi kullanırsan adım bir adım gecikir. Girdi array’ine += ile yazma, yeni bir array oluştur.

Gereksinimler

  • Dönüş değeri iki array içeren bir demettir (tuple): (w_yeni, v_yeni). İkisi de girdilerle aynı shape’te olur. Vektör ya da matris olabilirler.
  • Parametreleri güncellerken yeni hızı kullan, eski hızı değil. Önce v_yeni hesaplanır, sonra w_yeni ona göre bulunur.
  • lr hıza uygulanmaz, yalnızca parametre adımına uygulanır. Hız η\eta‘yı içermez.
  • Varsayılanlar lr=0.01 ve beta=0.9’dur.
  • Girdileri yerinde değiştirme. w ve v aynı kalmalı, sonuçlar yeni array’ler olmalı.

Momentum, gradyanı bir topun hızı gibi biriktirir. Gradyan birkaç adım üst üste aynı yönü gösteriyorsa hız büyür ve adımlar uzar. Yön sürekli değişiyorsa, örneğin dar bir vadide iki yana zıplarken, değişen bileşenler birbirini söndürür.

Sabit bir gradyanda hız, gradyanın 1/(1−β)1/(1-\beta) katına kadar büyür. β=0,9\beta = 0{,}9 için bu 10 katıdır. Bu yüzden momentumla öğrenme oranını biraz küçük seçmek gerekebilir.

Literatürde iki yazım görürsün. PyTorch’un kullandığı biçim yukarıdaki gibidir. Diğer biçim v←β v−η ∇L\mathbf{v} \leftarrow \beta\,\mathbf{v} - \eta\,\nabla L ve w←w+v\mathbf{w} \leftarrow \mathbf{w} + \mathbf{v} olarak yazılır. Öğrenme oranı sabitken ikisi aynı w\mathbf{w} dizisini üretir. Yalnızca v\mathbf{v}‘nin ölçeği ve işareti farklıdır.

Daha fazlası için Bir MLP eğitmek dersine bak.

Hızı eski hızdan ve gradyandan hesapla, parametreyi yeni hızla güncelle:

import numpy as npdef momentum_step(w: np.ndarray, v: np.ndarray, grad: np.ndarray,                  lr: float = 0.01, beta: float = 0.9) -> tuple[np.ndarray, np.ndarray]:    v_new = beta * v + grad    w_new = w - lr * v_new    return w_new, v_new

Sık yapılan hata, w’yi güncellerken eski v’yi kullanmaktır. Bu durumda en son gradyan o adımın güncellemesine hiç girmez. Adım bir adım gecikir.

Bir başka hata, lr’yi hıza katmaktır (v = beta * v + lr * grad). Bu da adımı η\eta ile iki kez çarpar.

Bu problemde bir sorun mu var?

solution.py
import numpy as npdef momentum_step(w: np.ndarray, v: np.ndarray, grad: np.ndarray,                  lr: float = 0.01, beta: float = 0.9) -> tuple[np.ndarray, np.ndarray]:    """Momentumlu SGD'nin tek adımını yapar ve (yeni w, yeni v) çiftini döndürür."""    # Kodunu buraya yaz.    return w, v

İçindekiler

Geri bildirim

Tür