"""
@Title: optimizer
@Time: 2024/3/10 10:52
@Author: Michael
"""
import math
# 批量梯度下降BGD、随机梯度下降SGD、小批量梯度下降MBGD
# 算法简单,可以快速收敛至目标值
# 学习率的选择对优化结果影响较大(过小导致收敛速度过慢,过大又越过极值点)
# 学习率在迭代过程中保持不变,很容易造成算法被卡在鞍点位置
# 可能收敛至局部极小值
def sgd(w, grad, alpha=0.01):
return w - alpha * grad
# 动量Momentum
# 相比于SGD纵轴学习变慢,横轴学习加快
def momentum(w, v, grad, alpha=0.01, beta=0.9):
v = beta * v + grad
return w - alpha * v, v
# AdaGrad
# 通过参数调整学习率,非常适合处理稀疏数据
# 学习率会随着迭代次数的增加而减小,不会因为学习率过大而越过极值点
# 相比于SGD算法不容易卡在鞍点位置
# 可能因其累积梯度平方导致学习率过早或过量的减少
def ada_grad(w, s, grad, alpha=0.01, epsilon=1e-6):
s += grad ** 2
return w - alpha / (math.sqrt(s) + epsilon) * grad, s
# RMSProp
# 通过修改AdaGrad得来,其在非凸背景下效果更好
# 解决梯度平方和累计越来越大的问题
def rms_prop(w, s, grad, alpha=0.01, epsilon=1e-6, rho=0.9):
s = rho * s + (1 - rho) * grad ** 2
return w - alpha / (math.sqrt(s) + epsilon) * grad, s
# Adam
# 本质是带有动量项的RMSProp,适用于大规模数据及不稳定目标函数的场景
# 经过偏置校正后,每一次迭代学习率都有个确定范围,使参数比较稳定
def adam(w, m, v, t, grad, alpha=0.01, epsilon=1e-6, beta1=0.9, beta2=0.999):
m = beta1 * m + (1 - beta1) * grad
v = beta2 * v + (1 - beta2) * grad ** 2
mt = m / (1 - beta1 ** t)
vt = v / (1 - beta2 ** t)
return w - alpha * mt / (math.sqrt(vt) + epsilon), m, v