SGD,Adam,Adamw练习笔记

本文介绍了随机梯度下降(SGD)的基本原理和示例,展示了如何寻找函数F的极值点。接着讨论了Adam算法,一种自适应学习率的优化方法,以及它在处理稀疏梯度问题上的优势。最后,提到了AdamW,即Adam算法结合L2正则化的变体,并给出了相应的代码实现。所有算法都在解决相同优化问题上进行了比较,展示了它们的迭代次数差异。
摘要由CSDN通过智能技术生成

SGD

是梯度下降法的改进,无需对每一组数据进行运算,而是随机抽取一组数据进行运算
学习率(步长):每次前进的距离,设为 lr
梯度(方向向量):每次前进的方向,设为 grad;
此处将参数设为 x
损失函数:

x_{t+1}=x_t-lr\times \rho F/\rho x_txt+1​=xt​−lr×ρF/ρxt​

例题:求F=pow(sin(x),2)+cos(x)+5最靠近6的极值点;

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main(){
    double lr=1e-2;
    double x=6,y=6,x_new,x1,y1;            
    double eps=1e-5;
    double grad=2*sin(x)*cos(x)-sin(x);
    double F;
    int t=0;
    while(fabs(grad)>eps){
        grad=2*sin(x)*cos(x)-sin(x);
        x_new=x-grad*lr;
        x=x_new;
        t++;
    }
    x1=x;
    y1=pow(sin(x1),2)+cos(x)+5;
    printf("(%.5lf , %.5lf)\n",x1,y1);
    printf("%d",t);
}

最终结果为:

(6.28318 , 6.00000)
1026

Adam(自适应性梯度算法)

Adam是梯度下降法的变种,用来更新神经网络的权重
通过计算梯度的一阶矩估计和二阶矩估计而为不同参数设计独立的自适应性学习率
加大的学习率(lr)会导致更新速度之前的初始学习速度更快,较小的则会降低。
\beta _1 一阶矩估计的指数衰减率估算值 \beta _2阶矩估计的指数衰减率。对于梯度稀疏的问题,应设为接近1.0 \epsilon 是一个很小的值,以防止在实现中被零除β1​一阶矩估计的指数衰减率估算值β2​阶矩估计的指数衰减率。对于梯度稀疏的问题,应设为接近1.0ϵ是一个很小的值,以防止在实现中被零除

Adam更新公式:

m_{t+1}=\beta _1\times m_t+(1-\beta _1)grad_tmt+1​=β1​×mt​+(1−β1​)gradt​
v_{t+1}=\beta _2\times m_t+(1-\beta _2){grad_t}^2vt+1​=β2​×mt​+(1−β2​)gradt​2
m_{t+1}=m_t/(1-{\beta _1}^t)mt+1​=mt​/(1−β1​t)
v_{t+1}=v_t/(1-{\beta _2}^t)vt+1​=vt​/(1−β2​t)
x_{t+1}=x_t-(lr\times m_t)/(\sqrt[]{v_t} +\epsilon )xt+1​=xt​−(lr×mt​)/(vt​​+ϵ)

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main(){
  double lr=1e-2,eps=1e-5,beta_1=0.9,beta_2=0.991,m=1,v=1,mt,vt,m_t,v_t,x=6,x_new,y=6,epsilon =1e-7;
  int t=0;
  double grad=2*sin(x)*cos(x)-sin(x);
  while(fabs(grad)>eps){
    t++;
    grad=2*sin(x)*cos(x)-sin(x);
    mt=beta_1*m+(1-beta_1)*grad;
    m=mt;
    vt=beta_2*v+(1-beta_2)*grad*grad;
    v=vt;
    m_t=mt/(1-pow(beta_1,t));
    v_t=vt/(1-pow(beta_2,t));
    x_new=x-lr*mt/(sqrt(vt)+epsilon);
    x=x_new;
  }
  printf("x=%.5lf  y=%.5lf\n",x,pow(sin(x),2)+cos(x)+5);
  printf("%d\n",t);
}

结果为:

x=6.28318 y=6.00000
300

Adamw

相对于Adam多了一个L2正则化
一般在以下位置加入\lambda x_t一般在以下位置加入λxt​
x_{t+1}=x_t-lr(m_t/( \sqrt[2]{v_t} +\epsilon) +\lambda x_t)xt+1​=xt​−lr(mt​/(2vt​​+ϵ)+λxt​)

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main(){
  double lr=1e-2,eps=1e-5,lambda=0.0001,beta_1=0.9,beta_2=0.999,m=0.1,v=0.1,mt,vt,m_t,v_t,x=6,x_new,y=6,epsilon =1e-7;
  int t=0;
  double grad=2*sin(x)*cos(x)-sin(x);
  while(fabs(grad)>eps){
    t++;
    grad=2*sin(x)*cos(x)-sin(x);
    mt=beta_1*m+(1-beta_1)*grad;
    m=mt;
    vt=beta_2*v+(1-beta_2)*grad*grad;
    v=vt;
    m_t=mt/(1-pow(beta_1,t));
    v_t=vt/(1-pow(beta_2,t));
    x_new=x-lr*mt/(sqrt(vt)+epsilon +lambda*x);
    x=x_new;
  }
  printf("x=%.5lf  y=%.5lf\n",x,pow(sin(x),2)+cos(x)+5);
  printf("%d\n",t);
}

结果为:

x=6.28284 y=6.00000
13

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值