RAdam 优化理解

  • 注:本篇blog旨在对文章RAdam: on the variance of the adaptive learning rate and beyond 进行理解

引言

x123
p1/31/31/3
    由上述简单的均匀分布可知,E(x) = 2, D(x) = 2 / 3
x123
p1/41/21/4
    由上述简单的随机分布可知,E(x) = 2, D(x) = 1 / 2
x123
p1/62/31/6
    由上述简单的随机分布可知,E(x) = 2, D(x) = 1 / 3

  • 对比上述三种分布可知,在其期望值相同的情形下,方差值随着分布的越"混乱",其值越大;当某个变量 x 如 P(x=1) = 1 时,其方差最小,为 0;
  • 熵:信息系统中的熵表达的是信息的混乱程度,熵的概念网上资料多如繁星,在此就不一一赘述了。

摘要

  • 机器学习中的学习率及其相关优化算法多如牛毛,从最初的固定的学习率,到后续的根据迭代次数的增加而学习率递减算法,再到后续主流标配的Adam算法,其主要目的都是期望model尽快收敛到一个最优解。学习率的启发式warmup算法多种多样、层出不穷,都是为了加速收敛过程和提升model的泛化能力;在主流如Adam算法的背后,追求的是一个自适应式的学习率过程。但是,在model训练的过程中,初始化的学习率也是很重要的,因为常规的算法诸如Adam,其variance太大了,不确定性因素较多,不太稳定。故而,他们 在Adam的基础上,针对自适应的学习率引入了一个修正项,来针对Adam的variance进行修正。

指数加权平均

  • 目前为止,主流的优化算法都是基于 指数加权平均 思路,进而针对model的各个参数进行更新计算。一般的参数更新过程如下:
    在这里插入图片描述

  • learning rate warmup:

    不同于将 α t {\alpha}_{t} αt 当做是一个常量值或者是简单的随着迭代次数的递增而递减,

    例如:线性warmup:设置 α t = t ∗ α 0 {\alpha}_{t} = t * {\alpha}_{0} αt=tα0 when t &lt; T w t &lt; {T}_{w} t<Tw

RAdam

    RAdam(Rectified Adam) model 在其导数的基础上,针对自适应的学习率,进行显式地修正其variance
  • 由于在model训练的早期,缺乏足够多的训练样本,会导致刚开始的几个样本对model的参数造成较大的影响(如:SGD算法),从而导致自适应式学习率产生较大的方差波动,进而导致model训练时陷入局部最优解

    在此分析一个简单的实例: 在上述的算法伪代码流程图中,当 t = 1 时,设置: ψ ( g 1 ) = 1 g 1 2 \psi({g}_{1}) = \sqrt {\frac{1}{{g}_{1}^2}} ψ(g1)=g121

    其中: { g 1 , g 2 , . . . , g t } \{{g}_{1}, {g}_{2}, ..., {g}_{t}\} {g1,g2,...,gt} 是从正态分布: N ( 0 , σ 2 ) \rm{N}(0, \sigma^2) N(0,σ2) ,因此, 1 g 1 2 \frac{1}{{g}_{1}^2} g121 服从于逆卡方分布: χ 2 ( 1 , 1 σ 2 ) \chi^2(1, \frac{1}{\sigma^2}) χ2(1,σ21)

    ,即为: V a r [ 1 g 1 2 ] ∝ ∫ 0 ∞ x − 1 e − x d x Var[\sqrt{\frac{1}{{g}_{1}^2}}] \propto \int_{0}^{\infty}{x}^{-1}e^{-x}{d}_{x} Var[g121 ]0x1exdx 。但是,该积分形式是发散的,此意味着在初始时或初始

    几个迭代后,其自适应学习率可能无穷大,在此,需要设置一个小的学习率对其进行缩放,

    从而来影响其variance: V a r [ α x ] = α 2 V a r [ x ] Var[\alpha x] = \alpha ^2 Var[x] Var[αx]=α2Var[x] ,这样,就可以在一定程度上缓和初始时学习率的variance过大的问题

  • 作者针对原始的Adam算法设计了两套变种算法:Adam-2k and Adam-eps

    1. Adam-2k :固定动量项: ϕ ( . ) \phi(.) ϕ(.) 和参数 θ \theta θ 不变,仅仅更新自适应学习率: ψ ( . ) \psi(.) ψ(.)

      通过此类方法,避免了原始 Adam 算法中所遇到的收敛困难的问题

    2. Adam-eps: 在原始的修改学习率的算法中,常常在梯度的分母中添加一个小的常量值 epsilon,以此来降低自适应学习率的 variance

    ψ ^ ( g 1 , g 2 , . . . , g t ) = 1 − β 2 t ϵ + ( 1 − β 2 ) ⋅ ∑ i = 1 t β 2 t − i ⋅ g i 2 \hat{\psi}({g}_{1}, {g}_{2}, ..., {g}_{t}) = \frac{\sqrt{1 - \beta_2^t}}{\epsilon + \sqrt{(1 - \beta_2) \cdot \sum_{i = 1}^t \beta_{2}^{t - i} \cdot {g}_{i}^2}} ψ^(g1,g2,...,gt)=ϵ+(1β2)i=1tβ2tigi2 1β2t

    假设 ψ ^ ( . ) \hat{\psi}(.) ψ^(.) 服从均匀分布,则其variance为: 1 12 ⋅ ϵ 2 \frac{1}{12 \cdot \epsilon^2} 12ϵ21 ,当 ϵ \epsilon ϵ 1 ∗ 10 − 8 1 * {10}^{-8} 1108 增加到 1 ∗ 10 − 4 1 * {10}^{-4} 1104 时,其收敛速度和精度均有不小的提升,如下图:
    在这里插入图片描述

证明及推导过程

- 其证明和推导过程繁琐而复杂,用到的数学分布较多,还有各种近似和求解极值;在经过一系列的尝试推导之后,依旧一团迷雾,不懂,略...

RAdam 算法

在这里插入图片描述

- 伪代码剖析
    - 变量说明:
        a_t:step size
        theta:参数
        m_t: 第 t 次迭代过程中的一次动量项
        v_t:第 t 次迭代过程中的二次动量项
        g_t:第 t 次迭代过程中的梯度
        f(theta):目标函数
    
    step 2:计算最大的指数加权平均长度,该值是根据一系列的计算公式推导而得出的收敛值
    step 4~6:指数加权平均的常规操作
    step 7:scale操作,计算修正指数加权移动平均值
    step 8:p_t,计算第 t 次迭代过程中的近似指数加权平均长度
    
    注:由于在推导过程中,需要其每次迭代过程中 p_t 的长度至少为 5 才成立,故而,当其长度大于 4 时,针对其二次动量项进行修正,同时计算 variance 修正项,更新参数等操作
实现
    def get_updates(self, loss, params):
        grads = self.get_gradients(loss, params)
        self.updates = [K.update_add(self.iterations, 1)]

        lr = self.lr
        # 衰减速率,学习率随着迭代次数的增加而下降
        if self.initial_decay > 0:
            lr = lr * (1.0 / (1.0 + self.decay * K.cast(self.iterations, K.dtype(self.decay))))

        t = K.cast(self.iterations, K.floatx()) + 1

        # 第 t 轮迭代的参数
        beta_1_t = K.pow(self.beta_1, t)
        beta_2_t = K.pow(self.beta_2, t)

        # Adam采用的是指数加权平均(exponential moving average),在此利用简单移动平均(simple moving average)
        # 当 t 趋近于无穷大时,其 SMA 的值趋近于 2 / (1 - beta_2) - 1
        rho = 2 / (1 - self.beta_2) - 1

        # 表示的是 rho 在第 t 轮迭代中的值
        rho_t = rho - 2 * t * beta_2_t / (1 - beta_2_t)

        # 计算方差修正项
        r_t = K.sqrt(K.relu(rho_t - 4) * K.relu(rho_t - 2) * rho / (K.relu(rho - 4) * K.relu(rho - 2) * rho_t))

        # 论文中算法的推导过程需要保证 rho_4 > 0 才能进行
        flag = K.cast(rho_t > 4, K.floatx())


        # 初始化指数移动平均中的一次动量项和二次动量项
        ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]
        vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params]
        self.weights = [self.iterations] + ms + vs


        for p, g, m, v in zip(params, grads, ms, vs):
            # 第 t 轮迭代中,指数移动的一次动量项
            m_t = (self.beta_1 * m) + (1.0 - self.beta_1) * g

            # 第 t 轮迭代中,指数移动的二次动量项
            v_t = (self.beta_2 * v) + (1.0 - self.beta_2) * K.square(g)

            # compute the bias-corrected moving average 1st moment
            m_hat_t = m_t / (1 - beta_1_t)

            # compute the bias-corrected moving average 2nd moment
            v_hat_t = K.sqrt(v_t / (1 - beta_2_t))

            # compute parameters with adaptive momentum
            p_t = p - lr * m_hat_t * (flag * r_t / (v_hat_t + self.epsilon) + (1 - flag))

            self.updates.append(K.update(m, m_t))
            self.updates.append(K.update(v, v_t))
            new_p = p_t


            # apply constraints
            if getattr(p, "constraint", None) is not None:
                new_p = p.constraint(new_p)

            self.updates.append(K.update(p, new_p))

        return self.updates

上述关键代码,采用keras实现;关键步骤都有注释,不再赘述

  • 实验效果:在本地跑了几个数据集和几个epoch,比传统的Adam稍快,但是其model对参数 epsilon 和 decay 比较敏感,整体预测效果较传统的 Adam 略有提升;但尚未与标杆 SGD 进行对比

参考文献

1、paper: on the variance of the adaptive learning rate and beyond

2、https://github.com/LiyuanLucasLiu/RAdam

3、https://github.com/bojone/keras_radam

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值