目录
AdaGrad [Adaptive Gradient Algorithm]
RMSProp [Root Mean Square Propagation]
Adam[Adaptive Moment Estimation]
前言
笔者写下此系列文章是希望在复习人工智能相关知识同时为想学此技术的人提供一定帮助。
图源网络,所有者可随时联系笔者删除。
优化算法非常重要,用于调整模型内的参数,以最小化(loss损失)或最大化某个函数 。
正文
续-动量法
按照下图为例子
竖直方向斜率大于水平方向,学习率一定的情况,竖直方向收敛大于水平方向。
如若学习率太大,竖直方向会错过最佳值,过小,水平方向收敛太慢。
动量法考虑到某个方向收敛“速度v”,在那个方向下降很快,则继续快下去,慢,就慢下去吧。
AdaGrad [Adaptive Gradient Algorithm]
名为自适应学习率优化算法,旨在解决不同参数的梯度更新速度差异大的问题。AdaGrad算法能够对每个参数自动调整学习率,使得频繁更新,梯度大的参数的学习率逐渐减小,而不频繁更新,梯度小的参数的学习率则相对较大,特别适合处理稀疏数据。
核心思想在于累积过去所有梯度的平方和,然后调整学习率。
公式如下:
其中,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通过引入衰减系数来调整历史信息的积累方式,使得每个参数的学习率不仅基于其所有过去梯度的平方的累积,而且主要受最近梯度的影响,这样就避免了学习率持续下降的问题。
核心公式如下:
其中,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不直接使用学习率,而是引入了一个参数更新的单位量,使得算法在没有初始学习率的情况下也能进行有效的参数更新。
首先计算过去梯度的平方,并维护一个窗口内平方梯度的移动平均值。
接下来,算法计算过去参数更新量的均方根,模拟一个自适应学习率。
然后,利用梯度的均方根和参数更新量的均方根来计算当前时间步的参数更新量
最后更新参数
Adam[Adaptive Moment Estimation]
被广泛使用。
由Diederik P. Kingma和Jimmy Ba在2014年提出,结合了AdaGrad和RMSProp算法的优点,并引入动量机制,核心在于同时计算梯度的均值和未中心化的方差的指数移动平均,从而为每个参数自适应地调整学习率。
其中,gt 是在时间步 t 的梯度,mt 和 vt 分别是梯度的均值和未中心化的方差的估计,β1 和 β2 是衰减率参数,分别控制这两个矩的移动平均。
对mt和vt进行偏差修正
更新参数
示例代码
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),所以内部实现就不重要了~