ADAM : A METHOD FOR STOCHASTIC OPTIMIZATION

Kingma D P, Ba J. Adam: A Method for Stochastic Optimization[J]. arXiv: Learning, 2014.

@article{kingma2014adam:,
title={Adam: A Method for Stochastic Optimization},
author={Kingma, Diederik P and Ba, Jimmy},
journal={arXiv: Learning},
year={2014}}

鼎鼎大名.

主要内容

f(θ)表示目标函数, 随机最优通常需要最小化E(f(θ)), 但是因为每一次我们都取的是一个小批次, 故实际上我们处理的是f1(θ),,fT(θ). 用gt=θft(θ)表示第t步对应的梯度.

Adam 方法分别估计梯度E(gt)的一阶矩和二阶矩(Adam: adaptive moment estimation 名字的由来).

算法

注意: 下面的算法中关于向量的运算都是逐项(element-wise)的运算.
在这里插入图片描述

选择合适的参数

首先, 分析为什么会有

(A.1)m^tmt/(1β2t),v^tvt/(1β2t).

可以用归纳法证明

(A.2)mt=(1β1)i=1tβ1tigivt=(1β2)i=1tβ2tigi2.

倘若分布稳定: E[gt]=E[g],E[gt2]=E[g2], 则

(A.3)E[mt]=E[g](1β1t)E[vt]=E[g2](1β2t).

这就是为什么会有(A.1)这一步.

Adam提出时的一个很大的应用场景就是dropout(正对梯度是稀疏的情况), 这是往往需要我们取较大的β2(可理解为抵消随机因素).

既然E[g]/E[g2]1, 我们可以把步长α理解为一个信赖域(既然|Δt|<a).

另外一个很重要的性质是, 比如函数扩大(或缩小)ccf, 此时梯度相应为cg, 我们所对应的

cm^tc2v^t=m^tv^t,

并无变化.

一些别的优化算法

AdaGrad:

θt+1=θtα1i=1tgt2+ϵgt.

RMSprop:

vt=β2vt1+(1β2)gt2θt+1=θtα1vt+ϵgt.

AdaDelta:

vt=β2vt1+(1β2)gt2θt+1=θtαmt1+ϵvt+ϵgtmt=β1mt1+(1β1)[θt+1θt]2.

注: 均为逐项

AdaMax

本文还提出了另外一种算法

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

理论

不想谈了, 感觉证明有好多错误.

代码

在这里插入图片描述




import numpy as np

class Adam:

    def __init__(self, instance, alpha=0.001, beta1=0.9, beta2=0.999,
                 epsilon=1e-8, beta_decay=1., alpha_decay=False):
        """ the Adam using numpy
        :param instance: the theta in paper, should have the grad method to call the grads
                            and the zero_grad method for clearing the grads
        :param alpha: the same as the paper default:0.001
        :param beta1: the same as the paper default:0.9
        :param beta2: the same as the paper default:0.999
        :param epsilon: the same as the paper default:1e-8
        :param beta_decay:
        :param alpha_decay: default False, if True, we will set alpha = alpha / sqrt(t)
        """
        self.instance = instance
        self.alpha = alpha
        self.beta1 = beta1
        self.beta2 = beta2
        self.epsilon = epsilon
        self.beta_decay = beta_decay
        self.alpha_decay = alpha_decay
        self.initialize_paras()

    def initialize_paras(self):
        self.m = 0.
        self.v = 0.
        self.timestep = 0

    def update_paras(self):
        grads = self.instance.grad
        self.beta1 *= self.beta_decay
        self.beta2 *= self.beta_decay
        self.m = self.beta1 * self.m + (1 - self.beta1) * grads
        self.v = self.beta2 * self.v + (1 - self.beta2) * grads ** 2
        self.timestep += 1
        if self.alpha_decay:
            return self.alpha / np.sqrt(self.timestep)
        return self.alpha

    def zero_grad(self):
        self.instance.zero_grad()

    def step(self):
        alpha = self.update_paras()
        betat1 = 1 - self.beta1 ** self.timestep
        betat2 = 1 - self.beta2 ** self.timestep
        temp = alpha * np.sqrt(betat2) / betat1
        self.instance.parameters -= temp * self.m / (np.sqrt(self.v) + self.epsilon)






class PPP:

    def __init__(self, parameters, grad_func):
        self.parameters = parameters
        self.zero_grad()
        self.grad_func = grad_func

    def zero_grad(self):
        self.grad = np.zeros_like(self.parameters)

    def calc_grad(self):
        self.grad += self.grad_func(self.parameters)



def f(x):
    return x[0] ** 2 + 5 * x[1] ** 2

def grad(x):
    return np.array([2 * x[0], 100 * x[1]])


if __name__ == "__main__":

    x = np.array([10., 10.])
    x = PPP(x, grad)
    xs = []
    ys = []
    optim = Adam(x, alpha=0.4)
    for i in range(100):
        xs.append(x.parameters.copy())
        y = f(x.parameters)
        ys.append(y)
        optim.zero_grad()
        x.calc_grad()
        optim.step()
    xs = np.array(xs)
    ys = np.array(ys)
    import matplotlib.pyplot as plt
    fig, (ax0, ax1)= plt.subplots(1, 2)
    ax0.plot(xs[:, 0], xs[:, 1])
    ax0.scatter(xs[:, 0], xs[:, 1])
    ax0.set(title="trajectory", xlabel="x", ylabel="y")
    ax1.plot(np.arange(len(ys)), ys)
    ax1.set(title="loss-iterations", xlabel="iterations", ylabel="loss")
    plt.show()











posted @   馒头and花卷  阅读(1335)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示