Momentumlu SGD adımı
Zorluk: Orta Çözüldü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. momentum katsayısı, öğrenme oranıdır (learning rate). Önce hızı, sonra parametreleri güncelle:
Hız, geçmiş gradyanların üstel olarak azalan bir toplamıdır. 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_yenihesaplanır, sonraw_yeniona göre bulunur. lrhıza uygulanmaz, yalnızca parametre adımına uygulanır. Hız ‘yı içermez.- Varsayılanlar
lr=0.01vebeta=0.9’dur. - Girdileri yerinde değiştirme.
wvevaynı 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 katına kadar büyür. 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 ve olarak yazılır. Öğrenme oranı sabitken ikisi aynı dizisini üretir. Yalnızca ‘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ı ile iki kez çarpar.
Bu problemde bir sorun mu var?