• 梯度优化算法Adam


    最近读一个代码发现用了一个梯度更新方法, 刚开始还以为是什么奇奇怪怪的梯度下降法, 最后分析一下是用一阶梯度及其二次幂做的梯度更新。网上搜了一下, 果然就是称为Adam的梯度更新算法, 全称是:自适应矩估计(adaptive moment estimation)

    国际惯例, 参考博文:

    一文看懂各种神经网络优化算法:从梯度下降到Adam方法

    Adam:一种随机优化方法

    An overview of gradient descent optimization algorithms

    梯度下降优化算法综述

    Hinton的神经网络课程第六课

    理论
    由于参考博客介绍的很清晰, 我就直接撸公式了:

    假设tt时刻, 目标函数对于参数的一阶导数是gtgt,那么我们可以先计算
    mtvt=β1mt−1+(1−β1)gt=β2vt−1+(1−β2)g2t
    mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2

    接下来计算
    mt^=mt1−βt1vt^=vt1−βt2
    mt^=mt1−β1tvt^=vt1−β2t

    最后我们的梯度更新方法就是
    θt+1=θt−η⋅mt^vt^−−√+ϵ
    θt+1=θt−η⋅mt^vt^+ϵ

    注意几个量, ηη是学习步长, 剩下的三个参数取值的建议是β1=0.9,β2=0.999,ϵ=10−8β1=0.9,β2=0.999,ϵ=10−8, 分母中的ϵϵ是为了防止除零. 其实这个步长的话,一般来说是建议选η=0.001η=0.001之类的, 注意βt1,βt2β1t,β2t中的tt是参与指数运算的
    其实再看一下公式,其实就是当前时刻的梯度更新利用了上一时刻的平方梯度vtvt的指数衰减均值vt^vt^和上一时刻的梯度mtmt的指数衰减均值mt^mt^
    代码实现
    以下非一个神经网络的完整实现, 主要在于看看定义网络参数以后怎么去使用Adam去更新每一时刻的梯度, 在theano中的实现方法如下:

    先看看神经网络的参数

    self.layers = [
    self.W0, self.W1, self.W2,
    self.b0, self.b1, self.b2]

    self.params = sum([layer.params for layer in self.layers], [])
    1
    2
    3
    4
    5
    然后初始化一开始时候的mt,vtmt,vt,分别对应代码中的m0params,m1paramsm0params,m1params
    self.params = network.params
    self.m0params = [theano.shared(np.zeros(p.shape.eval(), dtype=theano.config.floatX), borrow=True) for p in self.params]
    self.m1params = [theano.shared(np.zeros(p.shape.eval(), dtype=theano.config.floatX), borrow=True) for p in self.params]
    self.t = theano.shared(np.array([1], dtype=theano.config.floatX))
    1
    2
    3
    4
    定义目标函数=损失函数+正则项:

    cost = self.cost(network, input, output) + network.cost(input)
    1
    计算当前梯度

    gparams = T.grad(cost, self.params)
    1
    计算m0params,m1paramsm0params,m1params
    m0params = [self.beta1 * m0p + (1-self.beta1) * gp for m0p, gp in zip(self.m0params, gparams)]
    m1params = [self.beta2 * m1p + (1-self.beta2) * (gp*gp) for m1p, gp in zip(self.m1params, gparams)]
    1
    2
    使用Adam梯度更新

    params = [p - self.alpha *
    ((m0p/(1-(self.beta1**self.t[0]))) /
    (T.sqrt(m1p/(1-(self.beta2**self.t[0]))) + self.eps))
    for p, m0p, m1p in zip(self.params, m0params, m1params)]
    1
    2
    3
    4
    然后更新下一时刻网络中的梯度值,m0paramsm0params,m1paramsm1params,tt
    updates = ([( p, pn) for p, pn in zip(self.params, params)] +
    [(m0, m0n) for m0, m0n in zip(self.m0params, m0params)] +
    [(m1, m1n) for m1, m1n in zip(self.m1params, m1params)] +
    [(self.t, self.t+1)])
    ---------------------
    作者:风翼冰舟
    来源:CSDN
    原文:https://blog.csdn.net/zb1165048017/article/details/78392623
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    【2020Python修炼记】web框架之 Django自带的序列化组件/form组件
    【2020Python修炼记】web框架之数据批量插入/分页器
    3.栈与队列
    2.链表
    1.数组
    越来越少人用JQuery,但你就不学了吗?(4)
    越来越少人用JQuery,但你就不学了吗?(3)
    越来越少人用JQuery,但你就不学了吗?(2)
    越来越少人用JQuery,但你就不学了吗?(1)
    JS事件、Bom对象和Dom对象(4)(乐字节架构)
  • 原文地址:https://www.cnblogs.com/jfdwd/p/11243462.html
Copyright © 2020-2023  润新知