主页 > IT业界  > 

深度学习pytorch之19种优化算法(optimizer)解析

深度学习pytorch之19种优化算法(optimizer)解析

提示:有谬误请指正

摘要

本博客详细介绍了多种常见的深度学习优化算法,包括经典的LBFGS 、Rprop 、Adagrad、RMSprop 、Adadelta 、ASGD 、Adamax、Adam、AdamW、NAdam、RAdam以及SparseAdam等,通过对这些算法的公式和参数说明进行详细解析,博客旨在为机器学习工程师和研究人员提供清晰的理论指导,帮助读者选择合适的优化算法提升模型训练效率。

父类定义Optimizer torch.optim.Optimizer(params, defaults)

params (iterable): 一个可迭代对象,包含 :class:torch.Tensor 或 :class:dict。指定应该被优化的 Tensors。 defaults (dict): 一个字典,包含优化选项的默认值(当参数组未指定时使用)。

子类算法介绍

以下优化函数位于torch.optim包、timm.optim包内,使用句式形如:

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9) 1、SGD (Stochastic Gradient Descent) 1951

说明:随机梯度下降(Stochastic Gradient Descent, SGD)是最基础的优化算法之一。它在每次迭代中随机选择一个或一小批样本进行梯度计算并更新模型参数。 公式:

θ t + 1 = θ t − η ⋅ g t \theta_{t+1} = \theta_t - \eta \cdot g_t θt+1​=θt​−η⋅gt​

其中:

θ t \theta_t θt​: 在时间步 (t) 的模型参数 θ t + 1 \theta_{t+1} θt+1​: 在时间步 (t+1) 的模型参数 η \eta η: 学习率 (learning rate) g t g_t gt​: 时间步 (t) 的梯度,计算基于单个样本的损失函数对参数的导数 函数定义: def __init__(self, params, lr=required, momentum=0, dampening=0, weight_decay=0, nesterov=False, *, maximize=False, foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义了参数组的字典。 lr (float): 学习率。 momentum (float, optional): 动量因子(默认值:0)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 dampening (float, optional): 动量的阻尼因子(默认值:0)。 nesterov (bool, optional): 是否启用 Nesterov 动量(默认值:False)。 maximize (bool, optional): 是否基于目标函数最大化参数,而不是最小化(默认值:False)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.SGD(params, lr=0.1, momentum=0, dampening=0, weight_decay=0, nesterov=False) 2、LBFGS (Limited-memory Broyden-Fletcher-Goldfarb-Shanno) 1980

说明:有限内存布罗伊登 - 弗莱彻 - 戈德法布 - 香农算法(Limited-memory Broyden–Fletcher–Goldfarb–Shanno, LBFGS)是一种用于求解无约束优化问题的拟牛顿法,它通过使用有限的内存来近似海森矩阵的逆,从而减少了内存需求。 公式: θ t + 1 = θ t − α t H t ∇ θ J ( θ t ) \theta_{t+1} = \theta_t - \alpha_t H_t \nabla_{\theta} J(\theta_t) θt+1​=θt​−αt​Ht​∇θ​J(θt​)

其中:

θ t \theta_t θt​ 是当前的参数 α t \alpha_t αt​ 是步长 H t H_t Ht​是近似的海森矩阵 ∇ θ J ( θ t ) \nabla_{\theta} J(\theta_t) ∇θ​J(θt​) 是当前的梯度

函数定义:

def __init__(self, params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-7, tolerance_change=1e-9, history_size=100, line_search_fn=None):

lr (float): 学习率(默认值:1)。 max_iter (int): 每个优化步骤的最大迭代次数(默认值:20)。 max_eval (int): 每个优化步骤的最大函数评估次数(默认值:max_iter * 1.25)。 tolerance_grad (float): 关于一阶最优性的终止容忍度(默认值:1e-5)。 tolerance_change (float): 关于函数值/参数变化的终止容忍度(默认值:1e-9)。 history_size (int): 更新历史的大小(默认值:100)。 line_search_fn (str): 线搜索方法,取值为 ‘strong_wolfe’ 或 None(默认值:None)。

使用方式:

optimizer = torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-7, tolerance_change=1e-9) 3、Rprop (Resilient Propagation) 1993

说明:弹性反向传播算法(Resilient Backpropagation, Rprop)是一种专门为神经网络设计的优化算法,它只考虑梯度的符号而忽略梯度的大小,从而避免了梯度大小对学习率的影响。 公式: θ t + 1 = θ t − η i ⋅ sign ( ∇ θ J ( θ t ) ) \theta_{t+1} = \theta_t - \eta_i \cdot \text{sign}(\nabla_{\theta} J(\theta_t)) θt+1​=θt​−ηi​⋅sign(∇θ​J(θt​)) 其中:

η i \eta_i ηi​ 是每个参数的独立学习率 sign ( ∇ θ J ( θ t ) ) \text{sign}(\nabla_{\theta} J(\theta_t)) sign(∇θ​J(θt​)) 是梯度的符号函数

函数定义:

def __init__(self, params, lr=1e-2, etas=(0.5, 1.2), step_sizes=(1e-6, 50), foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-2)。 etas (Tuple[float, float], optional): 一对 (etaminus, etaplus),分别是乘法增长因子和减少因子(默认值:(0.5, 1.2))。 step_sizes (Tuple[float, float], optional): 最小和最大允许步长的一对值(默认值:(1e-6, 50))。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.Rprop(params, lr=1e-2, etas=(0.5, 1.2), step_sizes=(1e-6, 50)) 4、Adagrad(Adaptive Gradient Algorithm)2011

说明:自适应梯度算法(Adaptive Gradient Algorithm, Adagrad)是一种自适应学习率的优化算法,它为不同的参数分配不同的学习率,在处理稀疏数据时表现良好。 公式: θ t + 1 = θ t − η G t + ϵ ∇ θ J ( θ t ) \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t + \epsilon}} \nabla_{\theta} J(\theta_t) θt+1​=θt​−Gt​+ϵ ​η​∇θ​J(θt​) 其中:

G t G_t Gt​ 是历史梯度平方的累计和 ϵ \epsilon ϵ 是避免除以零的常数

函数定义:

def __init__( self, params, lr=1e-2, lr_decay=0, weight_decay=0, initial_accumulator_value=0, eps=1e-10, foreach: Optional[bool] = None, *, maximize: bool = False ):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-2)。 lr_decay (float, optional): 学习率衰减(默认值:0)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-10)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。 maximize (bool, optional): 是否基于目标最大化参数,而不是最小化(默认值:False)。

使用方式:

optimizer = torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0) 5、RMSprop (Root Mean Square Propagation) 2012

说明:均方根传播算法RMSprop 是对 Adagrad 的一种改进,它通过引入衰减因子,指数移动平均的方式来调整学习率,解决了 Adagrad 在训练后期学习率下降过快过小的问题。 公式: θ t + 1 = θ t − η E [ ∇ θ J ( θ t ) ] 2 + ϵ ∇ θ J ( θ t ) \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[\nabla_{\theta} J(\theta_t)]^2 + \epsilon}} \nabla_{\theta} J(\theta_t) θt+1​=θt​−E[∇θ​J(θt​)]2+ϵ ​η​∇θ​J(θt​) 其中:

E [ ∇ θ J ( θ t ) ] 2 E[\nabla_{\theta} J(\theta_t)]^2 E[∇θ​J(θt​)]2 是梯度平方的移动平均 ϵ \epsilon ϵ 是避免除以零的常数

函数定义:

def __init__(self, params, lr=1e-2, alpha=0.99, eps=1e-8, weight_decay=0, momentum=0, centered=False, foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-2)。 momentum (float, optional): 动量因子(默认值:0)。 alpha (float, optional): 平滑常数(默认值:0.99)。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 centered (bool, optional): 如果为True,则计算中心化的RMSProp,梯度将根据其方差的估计进行归一化。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False) 6、Adadelta 2012

说明:自适应学习率调整Adadelta 是对 Adagrad 和 RMSprop 的改进,通过使用梯度平方的指数移动平均来调整学习率,避免了 Adagrad 学习率单调递减的问题。 公式: θ t + 1 = θ t − η E [ Δ θ ] t 2 + ϵ Δ θ t \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[\Delta \theta]^2_t + \epsilon}} \Delta \theta_t θt+1​=θt​−E[Δθ]t2​+ϵ ​η​Δθt​ 其中:

E [ Δ θ ] t 2 E[\Delta \theta]^2_t E[Δθ]t2​ 是梯度的更新的平方的滑动平均

函数定义:

def __init__(self, params, lr=1.0, rho=0.9, eps=1e-6, weight_decay=0, foreach: Optional[bool] = None, *, maximize: bool = False):

params (iterable): 需要优化的参数,或者定义参数组的字典。 rho (float, optional): 用于计算平方梯度的移动平均的系数(默认值:0.9)。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-6)。 lr (float, optional): 用于缩放梯度更新的系数,在应用到参数之前(默认值:1.0)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。 maximize (bool, optional): 基于目标最大化参数,而不是最小化(默认值:False)。

使用方式:

optimizer = torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-6, weight_decay=0) 7、ASGD (Averaged Stochastic Gradient Descent)2012

说明:平均随机梯度下降(Average Stochastic Gradient Descent, ASGD)是一种对随机梯度下降的改进算法,它通过对梯度更新的参数进行取平均,来减少参数更新的方差,提高算法的稳定性。 公式: θ t + 1 = θ t − η t ∇ θ J ( θ t ) \theta_{t+1} = \theta_t - \eta_t \nabla_{\theta} J(\theta_t) θt+1​=θt​−ηt​∇θ​J(θt​) 同时,参数会更新为所有迭代的平均值: θ avg = 1 t ∑ i = 1 t θ i \theta_{\text{avg}} = \frac{1}{t} \sum_{i=1}^{t} \theta_i θavg​=t1​i=1∑t​θi​

其中:

θ t \theta_t θt​: 在时间步 (t) 的模型参数 θ avg \theta_{\text{avg}} θavg​: 在时间步 (t) 的模型参数的平均值 η \eta η: 学习率 (learning rate) ∇ θ J ( θ t ) \nabla_{\theta} J(\theta_t) ∇θ​J(θt​): 在时间步 (t) 计算的梯度 函数定义: def __init__(self, params, lr=1e-2, lambd=1e-4, alpha=0.75, t0=1e6, weight_decay=0, foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-2)。 lambd (float, optional): 衰减项(默认值:1e-4)。 alpha (float, optional): 用于更新学习率的幂次(默认值:0.75)。 t0 (float, optional): 开始平均的点(默认值:1e6)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.ASGD(params, lr=1e-2, lambd=1e-4, alpha=0.75, t0=1e6, weight_decay=0) 8、SGDP (Stochastic Gradient Descent with Momentum and Nesterov Accelerated Gradient)2015

说明:平均随机梯度下降(Average Stochastic Gradient Descent, ASGD)是一种对随机梯度下降的改进算法,它通过对梯度更新的参数进行取平均,来减少参数更新的方差,提高算法的稳定性。 公式:

计算动量:首先,计算当前的动量: v t + 1 = μ v t + η ∇ θ J ( θ t ) v_{t+1} = \mu v_t + \eta \nabla_{\theta} J(\theta_t) vt+1​=μvt​+η∇θ​J(θt​)

Nesterov 加速:然后,通过提前计算在更新后的位置的梯度来进行梯度修正: θ t + 1 = θ t − v t + 1 \theta_{t+1} = \theta_t - v_{t+1} θt+1​=θt​−vt+1​

其中

θ t \theta_t θt​ 是当前参数$ v_t$是动量(前一次更新的累积梯度) η \eta η是学习率 μ \mu μ是动量因子 ∇ θ J ( θ t ) \nabla_{\theta} J(\theta_t) ∇θ​J(θt​) 是当前的梯度

函数定义:

def __init__(self, params, lr=required, momentum=0, dampening=0,weight_decay=0, nesterov=False, eps=1e-8, delta=0.1, wd_ratio=0.1):

params (iterable): 需要优化的参数,或者定义了参数组的字典。 lr (float): 学习率。 momentum (float, optional): 动量因子(默认值:0)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 dampening (float, optional): 动量的阻尼因子(默认值:0)。 nesterov (bool, optional): 是否启用 Nesterov 动量(默认值:False)。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 delta(float, optional):调节学习率的更新或梯度的平滑度,影响参数更新时的速度(默认值:0.1)。 wd_ratio(float, optional): 控制 weight decay (权重衰减)应用到参数更新时的比例(默认值:0.1)。

使用方式:

from timm.optim.sgdp import SGDP optimizer = SGDP(params, lr=required, momentum=0, dampening=0,weight_decay=0, nesterov=False, eps=1e-8, delta=0.1, wd_ratio=0.1) 9、Adamax 2014

说明:Adamax 是 Adam 的一个变体,使用 L∞ 范数来代替 Adam 中的二阶矩估计(L2范数),在某些情况下比 Adam 更稳定。 公式: θ t + 1 = θ t − η m ^ t / ( v ^ t + ϵ ) \theta_{t+1} = \theta_t - \frac{\eta}{\hat{m}_t / (\hat{v}_t + \epsilon)} θt+1​=θt​−m^t​/(v^t​+ϵ)η​ 其中:

m ^ t \hat{m}_t m^t​ 是梯度的一阶矩的估计 v ^ t \hat{v}_t v^t​ 是梯度的二阶矩的估计

函数定义:

def __init__(self, params, lr=2e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, foreach: Optional[bool] = None, *, maximize: bool = False):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:2e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。 maximize (bool, optional): 基于目标最大化参数,而不是最小化(默认值:False)。

使用方式:

optimizer = torch.optim.Adamax(params, lr=2e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0) 10、Adam (Adaptive Moment Estimation) 2015

说明:自适应矩估计(Adaptive Moment Estimation, Adam)结合了 AdaGrad 和 RMSProp 的优点,通过计算梯度的一阶矩估计(均值)和二阶矩估计(方差)来为不同的参数动态调整学习率,具有较强的收敛性能 公式: θ t + 1 = θ t − η m ^ t v ^ t + ϵ \theta_{t+1} = \theta_t - \frac{\eta \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} θt+1​=θt​−v^t​ ​+ϵηm^t​​ 其中:

m ^ t \hat{m}_t m^t​是梯度的一阶矩估计 v ^ t \hat{v}_t v^t​ 是梯度的二阶矩估计

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, amsgrad=False, *, foreach: Optional[bool] = None, maximize: bool = False, capturable: bool = False):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚项)(默认值:0)。 amsgrad (boolean, optional): 是否使用AMSGrad算法变体,来源于论文《On the Convergence of Adam and Beyond》(默认值:False)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。 maximize (bool, optional): 基于目标最大化参数,而不是最小化(默认值:False)。 capturable (bool, optional): 是否允许将此实例捕获到CUDA图中。传入True可能会影响未图形化的性能,因此如果不打算捕获图形,建议保持False(默认值:False)。

使用方式:

optimizer = torch.optim.Adam(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, amsgrad=False) 11、AdamW 2017

说明:AdamW 是 Adam 的一种变体,主要解决了 Adam 在使用正则化时存在的问题。它加入了权重衰减进行改进,来更好地处理正则化。 公式: θ t + 1 = θ t − η ⋅ m ^ t v ^ t + ϵ − η ⋅ λ θ t \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} - \eta \cdot \lambda \theta_t θt+1​=θt​−η⋅v^t​ ​+ϵm^t​​−η⋅λθt​ 其中:

λ \lambda λ是权重衰减系数

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=1e-2, amsgrad=False, *, maximize: bool = False, foreach: Optional[bool] = None, capturable: bool = False):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减系数(默认值:1e-2)。 amsgrad (boolean, optional): 是否使用AMSGrad算法变体,来源于论文《On the Convergence of Adam and Beyond》(默认值:False)。 maximize (bool, optional): 基于目标最大化参数,而不是最小化(默认值:False)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。 capturable (bool, optional): 是否允许将此实例捕获到CUDA图中。传入True可能会影响未图形化的性能,因此如果不打算捕获图形,建议保持False(默认值:False)。

使用方式:

optimizer = torch.optim.AdamW(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=1e-2, amsgrad=False) 12、NAdam (Nesterov-accelerated Adaptive Moment Estimation) 2017

说明:NAdam 是 Adam 的一个改进版本,结合了 Nesterov 加速梯度(NAG)方法 公式: θ t + 1 = θ t − η ⋅ m ^ t v ^ t + ϵ \theta_{t+1} = \theta_t - \frac{\eta \cdot \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} θt+1​=θt​−v^t​ ​+ϵη⋅m^t​​ 参数说明:

θ t \theta_t θt​: 在时间步 (t) 的模型参数。 η \eta η: 学习率(Learning rate),控制每次更新的步长。 m ^ t \hat{m}_t m^t​: 第 (t) 次时间步的偏置校正后的动量估计。

Nadam 中使用了 Nesterov 加速梯度的动量估计公式:

m ^ t = β 1 ⋅ m ^ t − 1 + ( 1 − β 1 ) ⋅ ∇ θ J ( θ t ) \hat{m}_t = \beta_1 \cdot \hat{m}_{t-1} + (1 - \beta_1) \cdot \nabla_{\theta} J(\theta_t) m^t​=β1​⋅m^t−1​+(1−β1​)⋅∇θ​J(θt​) 其中, β 1 \beta_1 β1​ 是一阶动量的衰减率(通常接近 1)。

v ^ t \hat{v}_t v^t​: 第 (t) 次时间步的偏置校正后的平方梯度估计:

v ^ t = β 2 ⋅ v ^ t − 1 + ( 1 − β 2 ) ⋅ ( ∇ θ J ( θ t ) ) 2 \hat{v}_t = \beta_2 \cdot \hat{v}_{t-1} + (1 - \beta_2) \cdot (\nabla_{\theta} J(\theta_t))^2 v^t​=β2​⋅v^t−1​+(1−β2​)⋅(∇θ​J(θt​))2 其中 β 2 \beta_2 β2​是 二阶动量的衰减率,控制历史梯度平方的影响,通常接近 1

函数定义:

def __init__(self, params, lr=2e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, momentum_decay=4e-3, foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:2e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚)(默认值:0)。 momentum_decay (float, optional): 动量衰减(默认值:4e-3)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.NAdam(params, lr=2e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, momentum_decay=4e-3) 13、RAdam (Rectified Adam) 2018

说明:Rectified Adam(RAdam)是对 Adam 算法的改进,通过自适应学习率调整机制,解决了 Adam 在小批量训练时的不稳定性问题。 公式: θ t + 1 = θ t − η ⋅ m ^ t v ^ t + ϵ ⋅ rectifier ( t ) \theta_{t+1} = \theta_t - \frac{\eta \cdot \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \cdot \text{rectifier}(t) θt+1​=θt​−v^t​ ​+ϵη⋅m^t​​⋅rectifier(t) 其中,rectifier(t) 是对学习率进行修正的函数。

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, foreach: Optional[bool] = None):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚)(默认值:0)。 foreach (bool, optional): 是否使用优化器的“foreach”实现(默认值:None)。

使用方式:

optimizer = torch.optim.RAdam(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0) 14、SparseAdam 2018

说明:SparseAdam 是 Adam 算法专门针对稀疏梯度进行优化的版本,通常是在 Adam 算法基础上针对稀疏数据场景的修改和扩展。

公式:

计算一阶矩估计(梯度的均值): m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt​=β1​mt−1​+(1−β1​)gt​

计算二阶矩估计(梯度的平方的均值): v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt​=β2​vt−1​+(1−β2​)gt2​

修正一阶矩估计和二阶矩估计(以抵消初始化偏差): m ^ t = m t 1 − β 1 t , v ^ t = v t 1 − β 2 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} m^t​=1−β1t​mt​​,v^t​=1−β2t​vt​​

更新参数(只对非零梯度进行更新): θ t + 1 = θ t − η v ^ t + ϵ m ^ t \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t θt+1​=θt​−v^t​ ​+ϵη​m^t​

其中:

g t g_t gt​ 是当前时刻的梯度。 β 1 , β 2 \beta_1, \beta_2 β1​,β2​ 是动量参数(通常设置为 0.9 和 0.999)。 η \eta η 是学习率。 ϵ \epsilon ϵ 是用于防止除零错误的小常数(通常设置为 1e-8)。

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8):

params (iterable): 需要优化的参数,或者定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加到分母上的项,以提高数值稳定性(默认值:1e-8)。

使用方式:

optimizer = torch.optim.SparseAdam(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8) 15、Adafactor 2018

说明:Adafactor 的更新规则与 Adam 类似,但它在梯度更新时使用了低秩矩阵近似,避免了存储整个梯度二阶矩阵,从而大大减少了内存消耗。

梯度的平方累积: Adafactor 使用梯度的指数衰减平均来估计梯度的方差:

v t , diag = β 1 v t − 1 , diag + ( 1 − β 1 ) g t 2 v_{t, \text{diag}} = \beta_1 v_{t-1, \text{diag}} + (1 - \beta_1) g_t^2 vt,diag​=β1​vt−1,diag​+(1−β1​)gt2​ v t , offdiag = β 2 v t − 1 , offdiag + ( 1 − β 2 ) g t g t − 1 v_{t, \text{offdiag}} = \beta_2 v_{t-1, \text{offdiag}} + (1 - \beta_2) g_t g_{t-1} vt,offdiag​=β2​vt−1,offdiag​+(1−β2​)gt​gt−1​

其中:

v t , diag v_{t, \text{diag}} vt,diag​ 表示梯度平方的对角部分(用于每个维度的自适应学习率)。 v t , offdiag v_{t, \text{offdiag}} vt,offdiag​ 是梯度协方差的离对角部分(用于捕捉不同维度之间的相关性)。 g t g_t gt​是当前的梯度。 β 1 \beta_1 β1​ 和 β 2 \beta_2 β2​ 是衰减系数。

更新规则: Adafactor 对参数更新采用以下公式:

θ t + 1 = θ t − η ⋅ g t v t , diag + ϵ \theta_{t+1} = \theta_t - \eta \cdot \frac{g_t}{\sqrt{v_{t, \text{diag}}} + \epsilon} θt+1​=θt​−η⋅vt,diag​ ​+ϵgt​​

其中:

θ t \theta_t θt​ 是当前的参数值。 η \eta η 是学习率。 v t , diag v_{t, \text{diag}} vt,diag​ 是在每个维度上的累积平方梯度。 ϵ \epsilon ϵ 是一个小常数,用于避免除零错误。

函数定义:

def __init__(self, params, lr=None, eps=1e-30, eps_scale=1e-3, clip_threshold=1.0,decay_rate=-0.8, betas=None, weight_decay=0.0, scale_parameter=True, warmup_init=False):

params (iterable): 要优化的参数迭代器,或者定义参数组的字典。 lr (float, optional): 外部学习率(默认值:None)。 eps (tuple[float, float]): 用于正则化常数的平方梯度和参数规模的常数(默认值:(1e-30, 1e-3))。 clip_threshold (float): 最终梯度更新的均方根阈值(默认值:1.0)。 decay_rate (float): 用于计算平方梯度的运行平均值的系数(默认值:-0.8)。 beta1 (float): 用于计算梯度运行平均值的系数(默认值:None)。 weight_decay (float, optional): 权重衰减(L2惩罚)(默认值:0)。 scale_parameter (bool): 如果为True,学习率将按参数的均方根进行缩放(默认值:True)。 warmup_init (bool): 是否使用预热初始化来进行时间依赖的学习率计算,具体取决于是否使用了预热初始化(默认值:False)。

使用方式:

from timm.optim.adafactor import Adafactor optimizer = Adafactor(params, lr=None, eps=1e-30, eps_scale=1e-3, clip_threshold=1.0,decay_rate=-0.8, betas=None, weight_decay=0.0) 16、NovoGrad 2019

说明:由 NVIDIA 团队提出,通过结合自适应梯度的方法与基于二阶矩阵的优化技巧,克服了传统的梯度下降法和一些常见优化算法在训练过程中可能遇到的挑战,如稀疏性和梯度消失问题。 公式: θ t + 1 = θ t − η g t v t + ϵ \theta_{t+1} = \theta_t - \eta \frac{g_t}{\sqrt{v_t} + \epsilon} θt+1​=θt​−ηvt​ ​+ϵgt​​

其中:

θ t \theta_t θt​:参数向量(当前迭代时的权重) η \eta η:学习率 g t g_t gt​:梯度向量 v t v_t vt​:梯度的动量(历史信息) ϵ \epsilon ϵ:避免除以零的小常数

函数定义:

def __init__(self,params,lr=1e-3,betas=(0.95, 0.98), eps=1e-8,weight_decay=0, grad_averaging=False, amsgrad=False):

params (iterable): 要优化的参数的可迭代对象,或定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.95, 0.98))。 eps (float, optional): 加入分母的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚)(默认值:0)。 grad_averaging: 梯度平均。 amsgrad (boolean, optional): 是否使用AMSGrad变体,这个变体来自论文《On the Convergence of Adam and Beyond》中的算法(默认值:False)

使用方式:新版timm已舍弃该算法

from timm.optim.novograd import NovoGrad optimizer = NovoGrad(params,lr=1e-3,betas=(0.95, 0.98), eps=1e-8,weight_decay=0) 17、NvNovoGrad 2020

说明:NvNovoGrad 采用了与 Adam 类似的思路,使用了梯度的 一阶矩估计(即动量项)和 二阶矩估计(即梯度的平方的指数衰减平均)。

公式:

一阶矩估计(动量项): m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt​=β1​mt−1​+(1−β1​)gt​

二阶矩估计(梯度平方的移动平均): v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt​=β2​vt−1​+(1−β2​)gt2​

更新参数: θ t = θ t − 1 − η m t v t + ϵ \theta_t = \theta_{t-1} - \frac{\eta m_t}{\sqrt{v_t} + \epsilon} θt​=θt−1​−vt​ ​+ϵηmt​​

其中

θ t \theta_t θt​ 是当前参数, g t g_t gt​ 是当前的梯度, m t m_t mt​ 是一阶矩(梯度的动量估计), v t v_t vt​ 是二阶矩(梯度平方的动量估计), η \eta η 是学习率, β 1 \beta_1 β1​ 和 β 2 \beta_2 β2​分别是一阶和二阶矩的衰减率, ϵ \epsilon ϵ 是一个小常数(用于避免除零)

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.95, 0.98), eps=1e-8, weight_decay=0, grad_averaging=False, amsgrad=False):

params (iterable): 要优化的参数的可迭代对象,或定义参数组的字典。 lr (float, optional): 学习率(默认值:1e-3)。 betas (Tuple[float, float], optional): 用于计算梯度及其平方的运行平均值的系数(默认值:(0.95, 0.98))。 eps (float, optional): 加入分母的项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2惩罚)(默认值:0)。 grad_averaging: 梯度平均。 amsgrad (boolean, optional): 是否使用AMSGrad变体,这个变体来自论文《On the Convergence of Adam and Beyond》中的算法(默认值:False)。

使用方式:

from timm.optim.nvnovograd import NvNovoGrad optimizer = NvNovoGrad(params, lr=1e-3, betas=(0.95, 0.98), eps=1e-8, weight_decay=0, grad_averaging=False, amsgrad=False) 18、AdamP 2020

说明:AdamP 与 Adam 的最大区别在于它对 权重衰减(weight decay) 的处理方式。标准的 Adam 优化算法中,权重衰减是作为一种正则化方式直接加到梯度上,而 AdamP 采用了更合适的方式,在梯度更新前对每个参数的梯度做了 正则化 处理,能够更有效地将权重衰减融入到优化过程中。 公式:

动量更新: 与 Adam 一样,AdamP 使用一阶矩和二阶矩的更新:

m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt​=β1​mt−1​+(1−β1​)gt​ v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt​=β2​vt−1​+(1−β2​)gt2​

其中:

m t m_t mt​ 是梯度的动量(与梯度的加权平均相关)。 v t v_t vt​ 是梯度的平方的加权平均(即梯度的方差估计)。 g t g_t gt​ 是当前梯度。 β 1 \beta_1 β1​ 和 β 2 \beta_2 β2​ 是衰减率超参数。 梯度校正: 与 Adam 类似,为了消除动量的偏差,AdamP 会对 m t m_t mt​和 v t v_t vt​进行偏差校正:

m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t​=1−β1t​mt​​ v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t​=1−β2t​vt​​

权重衰减的处理: AdamP 的关键区别在于它采用了一种不同的方式来处理权重衰减。具体来说,在每次更新时,AdamP 会通过以下方式将权重衰减与梯度结合:

θ t + 1 = θ t − η ⋅ m ^ t v ^ t + ϵ − η ⋅ λ ⋅ θ t \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} - \eta \cdot \lambda \cdot \theta_t θt+1​=θt​−η⋅v^t​ ​+ϵm^t​​−η⋅λ⋅θt​

其中:

θ t \theta_t θt​ 是当前的参数。 η \eta η是学习率。 λ \lambda λ 是权重衰减因子(通常为一个很小的值,如 (10^{-4}) 或 (10^{-5}))。 ϵ \epsilon ϵ 是一个小常数,防止除零错误。

函数定义:

def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0, delta=0.1, wd_ratio=0.1, nesterov=False):

使用方式:

from timm.optim.adamp import AdamP optimizer = AdamP(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0, delta=0.1, wd_ratio=0.1) 19、Adahessian 2021

说明:AdaHessian 引入了 Hessian 矩阵(即二阶导数矩阵)的近似,它包含了损失函数的二阶信息,能够更精确地调整学习率和梯度更新方向。AdaHessian 结合了梯度的一阶矩、二阶矩和 Hessian 矩阵的信息。 公式:

梯度计算: g t = ∇ θ L ( θ t ) g_t = \nabla_\theta L(\theta_t) gt​=∇θ​L(θt​) 其中, g t g_t gt​是损失函数 L ( θ ) L(\theta) L(θ)关于模型参数 θ t \theta_t θt​的梯度。

Hessian 矩阵的近似: AdaHessian 通过一种高效的方式来近似 Hessian 矩阵,避免了直接计算二阶导数带来的高计算成本。通常,AdaHessian 使用二阶矩的估计来近似 Hessian。具体的近似方法可以通过使用 Kronecker-factored Approximate Curvature (K-FAC) 技术或其他矩阵分解方法来实现。

更新规则: AdaHessian 使用自适应的学习率来更新参数。其更新公式如下: θ t + 1 = θ t − η t v t + ϵ ⋅ H ^ t − 1 g t \theta_{t+1} = \theta_t - \frac{\eta_t}{\sqrt{v_t + \epsilon}} \cdot \hat{H}_t^{-1} g_t θt+1​=θt​−vt​+ϵ ​ηt​​⋅H^t−1​gt​ 其中:

η t \eta_t ηt​ 是学习率。 v t v_t vt​ 是梯度的一阶矩估计(类似于 Adam 中的一阶动量)。 H ^ t \hat{H}_t H^t​ 是对 Hessian 矩阵的近似。 ϵ \epsilon ϵ是一个小常数,防止除零错误。 H ^ t − 1 \hat{H}_t^{-1} H^t−1​是 Hessian 矩阵的逆近似。

函数定义:

def __init__(self, params, lr=0.1, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.0, hessian_power=1.0, update_each=1, n_samples=1, avg_conv_kernel=False):

params (iterable): 可迭代的参数,定义了要优化的参数或包含参数组的字典。 lr (float, optional): 学习率(默认值:0.1)。 betas ((float, float), optional): 用于计算梯度和平方海森矩阵迹的运行平均的系数(默认值:(0.9, 0.999))。 eps (float, optional): 加入分母中的小项,以提高数值稳定性(默认值:1e-8)。 weight_decay (float, optional): 权重衰减(L2 正则化)参数(默认值:0.0)。 hessian_power (float, optional): 海森矩阵迹的指数(默认值:1.0)。 update_each (int, optional): 每经过 该 步数后才计算海森矩阵迹的近似值(用于节省时间)(默认值:1)。 n_samples (int, optional): 采样 z 的次数,用于近似海森矩阵迹(默认值:1)。

使用方式:

from timm.optim.adahessian import Adahessian optimizer = Adahessian(params, lr=0.1, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.0, hessian_power=1.0, update_each=1, n_samples=1)
标签:

深度学习pytorch之19种优化算法(optimizer)解析由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“深度学习pytorch之19种优化算法(optimizer)解析