zoukankan      html  css  js  c++  java
  • 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( heta))表示目标函数, 随机最优通常需要最小化(mathbb{E}(f( heta))), 但是因为每一次我们都取的是一个小批次, 故实际上我们处理的是(f_1( heta),ldots, f_T( heta)). 用(g_t= abla_{ heta}f_t( heta))表示第(t)步对应的梯度.

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

    算法

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

    选择合适的参数

    首先, 分析为什么会有

    [ ag{A.1} hat{m}_t leftarrow m_t / (1-eta_2^t), \ hat{v}_t leftarrow v_t / (1-eta_2^t). ]

    可以用归纳法证明

    [ ag{A.2} m_t = (1-eta_1) sum_{i=1}^t eta_1^{t-i} cdot g_i \ v_t = (1-eta_2) sum_{i=1}^t eta_2^{t-i} cdot g_i^2. ]

    倘若分布稳定: (mathbb{E}[g_t]=mathbb{E}[g],mathbb{E}[g_t^2]=mathbb{E}[g^2]), 则

    [ ag{A.3} mathbb{E}[m_t]=mathbb{E}[g] cdot(1-eta_1^t) \ mathbb{E}[v_t]= mathbb{E}[g^2] cdot (1- eta_2^t). ]

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

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

    既然(mathbb{E}[g]/sqrt{mathbb{E}[g^2]}le 1), 我们可以把步长(alpha)理解为一个信赖域(既然(|Delta_t| frac{<}{approx} a)).

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

    [frac{c cdot hat{m}_t}{sqrt{c^2 cdot hat{v}_t}}= frac{hat{m}_t}{sqrt{hat{v}_t}}, ]

    并无变化.

    一些别的优化算法

    AdaGrad:

    [ heta_{t+1} = heta_t -alpha cdot frac{1}{sqrt{sum_{i=1}^tg_t^2}+epsilon} g_t. ]

    RMSprop:

    [v_t = eta_2 v_{t-1} + (1-eta_2) g_t^2 \ heta_{t+1} = heta_t -alpha cdot frac{1}{sqrt{v_t+epsilon}}g_t. ]

    AdaDelta:

    [v_t = eta_2 v_{t-1} + (1-eta_2) g_t^2 \ heta_{t+1} = heta_t -alpha cdot frac{sqrt{m_{t-1}+epsilon}}{sqrt{v_t+epsilon}}g_t \ m_t = eta_1 m_{t-1}+(1-eta_1)[ heta_{t+1}- heta_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()
    
    
    
    
    
    
    
    
    
    
    
    
  • 相关阅读:
    使用tcmalloc编译启动时宕机
    使用tcmalloc编译出现undefined reference to `sem_init'
    使用AddressSanitizer做内存分析(一)——入门篇
    VIM-美化你的标签栏
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
    Entity Framework Code First (一)Conventions
  • 原文地址:https://www.cnblogs.com/MTandHJ/p/13046754.html
Copyright © 2011-2022 走看看