from .backend import xp def clip_grad_norm(params, max_norm): total = 0.0 for p in params: total = total + float((p.grad * p.grad).sum()) total = total ** 0.5 if total > max_norm: scale = max_norm / (total + 1e-6) for p in params: p.grad = p.grad * scale return total class AdamW: def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.01): self.params = list(params) self.lr = lr self.b1, self.b2 = betas self.eps = eps self.wd = weight_decay self.t = 0 self.m = [xp.zeros_like(p.data) for p in self.params] self.v = [xp.zeros_like(p.data) for p in self.params] def step(self): self.t += 1 bc1 = 1.0 - self.b1 ** self.t bc2 = 1.0 - self.b2 ** self.t for i, p in enumerate(self.params): g = p.grad self.m[i] = self.b1 * self.m[i] + (1.0 - self.b1) * g self.v[i] = self.b2 * self.v[i] + (1.0 - self.b2) * (g * g) mhat = self.m[i] / bc1 vhat = self.v[i] / bc2 p.data = p.data - self.lr * (mhat / (xp.sqrt(vhat) + self.eps) + self.wd * p.data) def zero_grad(self): for p in self.params: p.grad = xp.zeros_like(p.data)