Source code for snn.optimizers.nadam
import numpy as np
from .base import Optimizer
[docs]
class Nadam(Optimizer):
"""
Nadam — Nesterov-accelerated Adaptive Moment Estimation.
Combines Adam's adaptive learning rates with Nesterov momentum,
giving faster convergence than standard Adam in many settings.
f(θ) update rule::
m_t = β₁ · m_{t-1} + (1 − β₁) · g_t
v_t = β₂ · v_{t-1} + (1 − β₂) · g_t²
m̂ = β₁ · m_t / (1−β₁^{t+1}) + (1−β₁) · g_t / (1−β₁^t)
θ_t = θ_{t-1} − lr · m̂ / (√v̂ + ε)
Parameters
----------
learning_rate : float
Step size (default 2e-3).
beta_1 : float
Exponential decay for first moment (default 0.9).
beta_2 : float
Exponential decay for second moment (default 0.999).
epsilon : float
Numerical stability constant (default 1e-8).
weight_decay : float
L2 regularisation coefficient (default 0.0).
"""
def __init__(self, learning_rate=2e-3, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, weight_decay=0.0):
super().__init__(learning_rate)
self.beta_1 = beta_1
self.beta_2 = beta_2
self.epsilon = epsilon
self.weight_decay = weight_decay
self._m = {}
self._v = {}
[docs]
def apply_gradients(self, params, grads):
self._iterations += 1
t = self._iterations
updates = {}
b1t = 1.0 - self.beta_1 ** t
b2t = 1.0 - self.beta_2 ** t
for key, grad in grads.items():
param = params[key]
g = grad + self.weight_decay * param if self.weight_decay else grad
m = self._m.get(key, np.zeros_like(param))
v = self._v.get(key, np.zeros_like(param))
m_new = self.beta_1 * m + (1.0 - self.beta_1) * g
v_new = self.beta_2 * v + (1.0 - self.beta_2) * g ** 2
self._m[key] = m_new
self._v[key] = v_new
# Nesterov look-ahead estimate of m̂
m_hat = (self.beta_1 * m_new / (1.0 - self.beta_1 ** (t + 1))
+ (1.0 - self.beta_1) * g / b1t)
v_hat = v_new / b2t
updates[key] = param - self.learning_rate * m_hat / (np.sqrt(v_hat) + self.epsilon)
return updates
[docs]
def get_config(self):
cfg = super().get_config()
cfg.update({
"beta_1": self.beta_1,
"beta_2": self.beta_2,
"epsilon": self.epsilon,
"weight_decay": self.weight_decay,
})
return cfg