Skip to main content

Adam AdamW

Adam核心计算流程

  1. 初始化参数

    • 初始化一阶矩(动量)向量 m0​=0 和二阶矩(梯度平方的指数平均)向量 v0​=0。
    • 设定超参数:学习率 η(默认0.001)、动量衰减因子 β1​(默认0.9)、二阶矩衰减因子 β2​(默认0.999)、数值稳定常数 ϵ(默认1e-8)
  2. 计算当前梯度 在时间步 t,计算损失函数对参数 θ_{t}​ 的梯度 g_{t}​

  3. 更新一阶矩(动量项)​ 对梯度进行指数加权移动平均,模拟动量效果:m_{t}​=β1​⋅m_{t−1}​+(1−β1​)⋅g_{t}​

  4. 更新二阶矩(梯度平方的指数平均)​ 计算梯度平方的移动平均,用于自适应调整学习率:v_{t​}=β2​⋅v_{t−1}​+(1−β2​)⋅g_{t}^{2}​

  5. 偏差校正(Bias Correction)​ 因初始时刻 mt​ 和 vt​ 偏向0,需通过时间步 t 修正: m_{t​}=m_{t​}/(1−β_{1}^{t})​ v^{t}​=v^{t}/(1−β_{2}t)

  6. 参数更新 结合修正后的矩估计调整学习率,更新参数

class AdamOptimizer:
    def __init__(self, learning_rate=0.01, beta1=0.9, beta2=0.999, epsilon=1e-8):
        self.lr = learning_rate
        self.beta1 = beta1
        self.beta2 = beta2
        self.epsilon = epsilon
        self.m = 0
        self.v = 0
        self.t = 0
    def update(self, params, grads):
        self.t += 1
        for param, grad in zip(params, grads):
            self.m[param] = self.beta1 * self.m[param] + (1 - self.beta1) * grad
            self.v[param] = self.beta2 * self.v[param] + (1 - self.beta2) * grad**2
            m_hat = self.m[param] / (1 - self.beta1**self.t)
            v_hat = self.v[param] / (1 - self.beta2**self.t)
            param = param - self.lr * m_hat / (np.sqrt(v_hat) + self.epsilon)
        return params

weight decay

权重衰减,本质上希望对权重进行惩罚,权重绝对值越大越不好

w = w - lr * w.grad - lr * weight_decay * w

L2正则化,表示对权重的衰减比例和权重绝对值的平方成正比

final_loss = loss + wd * all_weights.pow(2).sum() / 2

Adam在实现L2正则化的时候是直接修改梯度,随后梯度会参与动量的计算,导致L2正则化的梯度就会被抵消掉,导致效果不佳

grad_w = grad_w + weight_decay * w

AdamW

AdamW 的实现方法与传统的 L2 正则化不同,它直接对权重进行衰减,而不是将其加到损失函数上(改变grad_w)

grad_w = grad_w
# update step
w = w - learning_rate * grad_w - learning_rate * weight_decay * w