带你学会深度学习之优化算法 - 2

本文介绍了几种常见的优化算法,包括动量法、自适应学习率的AdaGrad、RMSProp、针对学习率过度下降问题的AdaDelta以及结合了动量和自适应性的Adam。重点讲解了算法原理、公式和在深度学习框架中的应用。
摘要由CSDN通过智能技术生成

目录

前言

正文

续-动量法

AdaGrad [Adaptive Gradient Algorithm]

RMSProp [Root Mean Square Propagation]

AdaDelta

Adam[Adaptive Moment Estimation]


前言

笔者写下此系列文章是希望在复习人工智能相关知识同时为想学此技术的人提供一定帮助。

图源网络,所有者可随时联系笔者删除。

优化算法非常重要,用于调整模型内的参数,以最小化(loss损失)或最大化某个函数 。

正文

续-动量法

按照下图为例子

竖直方向斜率大于水平方向,学习率一定的情况,竖直方向收敛大于水平方向。

如若学习率太大,竖直方向会错过最佳值,过小,水平方向收敛太慢。

dc579da2b74e4ae6b8af9a9c181df7d0.png

动量法考虑到某个方向收敛“速度v”,在那个方向下降很快,则继续快下去,慢,就慢下去吧。

0dde6130746c4d93a5e06ebfb8e7f3e9.png

AdaGrad [Adaptive Gradient Algorithm]

名为自适应学习率优化算法,旨在解决不同参数的梯度更新速度差异大的问题。AdaGrad算法能够对每个参数自动调整学习率,使得频繁更新,梯度大的参数的学习率逐渐减小,而不频繁更新,梯度小的参数的学习率则相对较大,特别适合处理稀疏数据。

核心思想在于累积过去所有梯度的平方和,然后调整学习率。

公式如下:

9d969afb70b04a438ca8e28091e27415.png

其中,Gt​ 是到时间步 t 为止所有梯度平方的累积,η 是初始学习率,ϵ 是一个很小的数(比如 1e−8),用来防止分母为零。

实现示例代码

class AdaGrad:
    def __init__(self, lr=0.01, epsilon=1e-8):
        self.lr = lr
        self.epsilon = epsilon
        self.G = None  

    def update(self, params, grads):
        if self.G is None:
            self.G = {}
            for key, val in params.items():
                self.G[key] = np.zeros_like(val)

        for key in params.keys():
            self.G[key] += grads[key] * grads[key]
            params[key] -= self.lr * grads[key] / (np.sqrt(self.G[key]) + self.epsilon)

AdaGrad可以针对不同的参数进行特定的更新策略。

RMSProp [Root Mean Square Propagation]

由Geoff Hinton提出,解决了AdaGrad算法在训练深度网络时学习率逐渐减小到零的问题。RMSProp通过引入衰减系数来调整历史信息的积累方式,使得每个参数的学习率不仅基于其所有过去梯度的平方的累积,而且主要受最近梯度的影响,这样就避免了学习率持续下降的问题。

核心公式如下:

6ff7c25cc1e04868b9e96a27279936ef.png

其中,gt​ 是在时间步 t 的梯度,E[g2]t​ 是平方梯度的指数移动平均,β 是衰减率(通常设置为0.9),η 是学习率,ϵ 是一个很小的数,用来防止分母为零。

示例代码

class RMSProp:
    def __init__(self, lr=0.01, beta=0.9, epsilon=1e-8):
        self.lr = lr
        self.beta = beta
        self.epsilon = epsilon
        self.Eg = None  

    def update(self, params, grads):
        if self.Eg is None:
            self.Eg = {}
            for key, val in params.items():
                self.Eg[key] = np.zeros_like(val)

        for key in params.keys():
            self.Eg[key] = self.beta * self.Eg[key] + (1 - self.beta) * (grads[key] ** 2)
            params[key] -= self.lr * grads[key] / (np.sqrt(self.Eg[key]) + self.epsilon)

AdaDelta

RMSProp算法的扩展,由Matthew Zeiler在2012年提出,解决了AdaGrad和RMSProp算法中学习率可能过度下降的问题,AdaDelta不直接使用学习率,而是引入了一个参数更新的单位量,使得算法在没有初始学习率的情况下也能进行有效的参数更新。

首先计算过去梯度的平方,并维护一个窗口内平方梯度的移动平均值。

bfb1a504995e48d7b33ac5fc755e6b1c.png

接下来,算法计算过去参数更新量的均方根,模拟一个自适应学习率。

76adbd65ff0940aa8a622a37616010f2.png

然后,利用梯度的均方根和参数更新量的均方根来计算当前时间步的参数更新量

13d2eaefeaef4e0ea5772f1bf8bf5394.png

最后更新参数

9e89e9fd90eb452ebae9085cb7afb24d.png

Adam[Adaptive Moment Estimation]

被广泛使用。

由Diederik P. Kingma和Jimmy Ba在2014年提出,结合了AdaGrad和RMSProp算法的优点,并引入动量机制,核心在于同时计算梯度的均值和未中心化的方差的指数移动平均,从而为每个参数自适应地调整学习率。

ce59564b83374966b997f9c32c5ebae8.png

其中,gt​ 是在时间步 t 的梯度,mt​ 和 vt​ 分别是梯度的均值和未中心化的方差的估计,β1​ 和 β2​ 是衰减率参数,分别控制这两个矩的移动平均。

对mt和vt进行偏差修正

18c5c3f23063411baa6fe35d08805935.png

更新参数

6f9d1ba4f248444fbe263135b4d73efa.png

示例代码

class Adam:
    def __init__(self, lr=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
        self.lr = lr
        self.beta1 = beta1
        self.beta2 = beta2
        self.epsilon = epsilon
        self.m = None
        self.v = None
        self.t = 0

    def update(self, params, grads):
        if self.m is None:
            self.m, self.v = {}, {}
            for key, val in params.items():
                self.m[key] = np.zeros_like(val)
                self.v[key] = np.zeros_like(val)

        self.t += 1
        for key in params.keys():
            self.m[key] = self.beta1 * self.m[key] + (1 - self.beta1) * grads[key]
            self.v[key] = self.beta2 * self.v[key] + (1 - self.beta2) * (grads[key]**2)
            m_hat = self.m[key] / (1 - self.beta1**self.t)
            v_hat = self.v[key] / (1 - self.beta2**self.t)
            params[key] -= self.lr * m_hat / (np.sqrt(v_hat) + self.epsilon)

 最后的话,优化算法大致就介绍到这里了,文中的代码和公式都不懂也不用担心

Don't worry about it.

在Pytorch之类的框架里,比如使用Adam优化,只需要如下一行

optimizer = optim.Adam(model.parameters(), lr=0.001),所以内部实现就不重要了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目艾拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值