Adam adımı
Zorluk: Zor Çözüldüoptimizasyon
Adam, her parametre için adım boyutunu gradyanın geçmişine göre ayarlar. İki hareketli ortalama tutar: gradyanın ortalaması (birinci moment, ) ve gradyanın karesinin ortalaması (ikinci moment, ). adam_step(w, m, v, grad, t, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8) fonksiyonunu yaz. Fonksiyon, Adam’ın yanlılık düzeltmeli (bias correction) tek bir adımını yapar.
t adım numarasıdır ve 1’den başlar: ilk güncellemede t = 1. Önce momentleri güncelle:
Momentler sıfırdan başladığı için ilk adımlarda sıfıra doğru yanlıdır. Yanlılık düzeltmesi bunu giderir:
Sonra parametreleri güncelle. Kare ve karekök eleman bazındadır (element-wise):
Fonksiyon (w_yeni, m_yeni, v_yeni) üçlüsünü döndürür. Momentler düzeltilmemiş hâlleriyle döner. Çünkü bir sonraki adım onlardan devam eder.
Örnekler
Girdi: w = [1.0, -1.0], m = [0.0, 0.0], v = [0.0, 0.0], grad = [0.5, -3.0], t = 1, lr = 0.001
Çıktı: (array([ 0.999, -0.999]), array([ 0.05, -0.3 ]), array([0.00025, 0.009 ]))
Girdi: w = [0.2, 0.4, -0.6], m = [0.1, -0.2, 0.05], v = [0.01, 0.04, 0.0025], grad = [0.3, -0.1, 0.2], t = 5, lr = 0.01, beta1 = 0.8, beta2 = 0.99
Çıktı: (array([ 0.19556409, 0.4029747 , -0.60491289]), array([ 0.14, -0.18, 0.08]), array([0.0108 , 0.0397 , 0.002875]))
Girdi: w = [[1.0, -2.0], [0.0, 3.0]], m = [[-0.5, 0.5], [0.0, 1.0]], v = [[0.25, 0.25], [1.0, 4.0]], grad = [[-1.0, 1.0], [2.0, -2.0]], t = 20, lr = 0.1
Çıktı: (array([[ 1.0175992 , -2.0175992 ],
[-0.00319986, 2.99439186]]), array([[-0.55, 0.55],
[ 0.2 , 0.7 ]]), array([[0.25075, 0.25075],
[1.003 , 4. ]]))
İpucu 1
m_yeni ve v_yeni’yi eski değerlerden hesapla. grad ** 2 eleman bazında karedir. Düzeltilmemiş değerleri sakla, çünkü fonksiyon onları döndürür.
İpucu 2
m_hat = m_yeni / (1 - beta1 ** t) ve v_hat için benzerini yaz. , ilk adımda küçüktür ve t büyüdükçe 1’e yaklaşır.
İpucu 3
Paydada np.sqrt(v_hat) + eps kullan. İlk adımda m_hat = grad ve np.sqrt(v_hat) = |grad| olur. Parametre yaklaşık kadar, gradyanın tersi yönünde oynar.
Gereksinimler
- Dönüş değeri üç array içeren bir demettir:
(w_yeni, m_yeni, v_yeni). Üçü dewile aynı shape’te olur. m_yenivev_yenidüzeltmeden önceki değerlerdir. Yalnızca parametre adımında ve kullanılır.eps, karekökten sonra paydaya eklenir: . Karekökün içine girmez.t1 ya da daha büyük bir tam sayıdır.t = 0verilmez.- Varsayılanlar
lr=0.001,beta1=0.9,beta2=0.999veeps=1e-8’dir. - Gradyan sıfırken sonuç
nanolmamalı. Girdileri yerinde değiştirme.
Adam, momentumu (momentum) ve adım boyutunu parametre başına uyarlamayı birleştirir. Birinci moment momentumun işini yapar: gradyanın yönünü düzler. İkinci moment adım boyutunu ayarlar: gradyanı sürekli büyük olan parametrenin adımı küçülür, küçük olanın adımı büyür.
Yanlılık düzeltmesi neden gerekli? ile başlarsan, ilk adımda olur. Gerçek ortalamanın onda biridir. için ise gerçek değerin binde biri kadar olur. Düzeltme olmadan ilk adımlar yanlış ölçekte olur. ile bölmek bu eksikliği tam olarak tamamlar.
İlk adımda gradyanın işaretidir. Bu yüzden her parametre ilk adımda yaklaşık kadar oynar. yalnızca sıfıra bölmeyi engeller.
Daha fazlası için Bir MLP eğitmek dersine bak.
Momentleri güncelle, düzelt ve parametre adımını at:
import numpy as npdef adam_step(w: np.ndarray, m: np.ndarray, v: np.ndarray, grad: np.ndarray, t: int, lr: float = 0.001, beta1: float = 0.9, beta2: float = 0.999, eps: float = 1e-8) -> tuple[np.ndarray, np.ndarray, np.ndarray]: m_new = beta1 * m + (1 - beta1) * grad v_new = beta2 * v + (1 - beta2) * grad ** 2 m_hat = m_new / (1 - beta1 ** t) v_hat = v_new / (1 - beta2 ** t) w_new = w - lr * m_hat / (np.sqrt(v_hat) + eps) return w_new, m_new, v_new
Sık yapılan hata, düzeltilmiş momentleri geri döndürmektir. Bir sonraki adımda onları yeniden düzeltirsin ve moment ortalamaları bozulur. Düzeltme yalnızca parametre adımının içinde yapılır.
Bir başka hata, eps’i karekökün içine koymaktır (np.sqrt(v_hat + eps)). Gradyan çok küçükken adım boyutu belirgin biçimde değişir.
Bu problemde bir sorun mu var?