机器学习深度学习笔记,常用算法Adam与Adagard。使用c++开发。

1. Adam

Adam 算法全称为 Adaptive Moment Estimate, 这种算法结合了基于动量的算法和基于自适应学习率的算法.

Adam 算法记录了梯度的一阶矩 (梯度的期望值) 和二阶矩 (梯度平方的期望值).

1.1 定义

其中p,g,m,v,β1,β2,E

分别表示参数, 梯度, 一阶矩, 二阶矩, 衰减率和极小值 (防止 0 分母).

Adam 的必要参数是衰减率 β1, β2 , 一般取 β1 = 0.9, β 2 = 0.999,β2=0.999,E取10e-10左右。

2. Adagard

2.1 定义 

容易看出,随着算法不断的迭代,gt 会越来越大,整体的学习率会越来越小。所以一般来说adagrad算法一开始是激励收敛,到了后面就慢慢变成惩罚收敛,速度越来越慢。

下面给出代码段

开头定义段

#include<stdio.h>
#include<math.h>

//ADAM定义1
//adagard定义置0 
#define Adam 1
//adam学习率10e-4,adagrad学习率10e-2; 
#define rate 0.0005
//学习次数 
#define len 9900000
//各个adam的参数b11对应v1的β1 ,B21对应st1的 β2  类推 
#define B11 0.9
#define B12 0.9
#define B13 0.9
#define B14 0.9
#define B21 0.99
#define B22 0.99
#define B23 0.99
#define B24 0.99
//定一个初值 合理化 去一个点随机算 
float bn=-3582,w=0.2,w1=2,w2=15,fun,loss = 0,rate1;
int learn=0; 

测试样本 由于样本较少就没有分test与train了 只是学习两种算法

float y[25]={519.28,537.82,571.7,629.89,700.02,775.59,947.35,2040.79,2090.73,2140.36,2390.47,2727.4,2821.86,2990.17,3296.91,4255.3,5126.88,6038.04,6909.82,8234.04,9262.8,10682.58,12581.51,25301.38,17636.45};
float buff1[25]={3624.1,4038.2,4517.8,4862.4,5294.7,5934.5,7171,8964.4,10202.2,11962.5,14928.3,16909.2,18547.9,21617.8,26638.1,34636.4,46759.4,58478.1,67884.6,74462.6,78345.2,82067.5,89468.1,97314.8,104790.6};
float buff2[25]={1122.09,1281.79,1228.83,1138.41,1229.98,1409.52,1701.02,2004.25,2204.91,2262.18,2491.21,2823.78,3083.59,3386.62,3742.2,4642.3,5792.62,6823.72,7937.55,9233.56,10798.18,13187.67,15886.5,18902.58,22053.15};
float buff3[25]={100.7,102,106,102.4,101.9,101.5,102.8,108.8,106,107.3,118.5,117.8,102.1,102.9,105.4,113.2,121.7,114.8,106.1,100.8,97.4,97,98.5,99.2,98.7};
/* y = w*buf1 + w1* buf2 + w2*buf3 +bn 
num 常数 补偿lossfunction*/ 

 

接下来是学习函数 包括两种算法 用定义和条件编译区分选择

void learning(float num,unsigned int size)
{
	//#if的条件编译 下面提到都类似。用于切换adam和adagrad。 
	#if Adam
//这里是定义的初代变量。上文有提到 adam的m与v 。
	static int i =0,j=0;
	float st1=0,st2=0,st3=0,st4=0;
	float v1=0,v2=0,v3=0,v4=0;
	float wh=0,go1=0,go2=0,go3=0,go4=0;

	#else
//这是adagrad的 gonu用来存储gt的平方和 go分别表示每个参数对应的梯度
	static int i =0,j=0;
	float gonu=0,gonu1=0,gonu2=0,gonu3=0;
	float wh=0,go1=0,go2=0,go3=0,go4=0;

	#endif
	for(j=0;j<len;j++)//len是学习次数,这里开始迭代学习
	{

	go1=0,go2=0,go3=0,go4=0;
	loss = 0;
for(i=0;i<size;i++)
{
//对函数 lossfunction 梯度进行运算
	fun = bn + w*buff1[i]+ buff2[i] *w1 +buff3[i]*w2;
	loss +=(y[i] - fun)*(y[i] - fun)+num *wh;
	go1 += -2*y[i]*buff1[i]+2*fun*buff1[i]+2*w*num;
	go2 += -2*y[i]*buff2[i]+2*fun*buff2[i]+2*w1*num;
	go3 += -2*y[i]*buff3[i]+2*fun*buff3[i]+2*w2*num;
	go4 += -2*y[i]+ 2*fun;
}
	#if Adam
//具体算法 上文有公式和过程
	v1=	B11*v1 + (1-B11)*go4;
	v2 = B12*v2 + (1-B12)*go1;
	v3 = B13*v3 + (1-B13)*go2;
	v4 = B14*v4 + (1-B14)*go3;
	st1 = B21*st1 + (1-B21)*go4*go4;
	st2 = B22*st2 + (1-B22)*go1*go1;
	st3 = B23*st3 + (1-B23)*go2*go2;
	st4 = B24*st4 + (1-B24)*go3*go3;
	rate1 = (v1/(1-B11))*(rate/(sqrt(fabs(st1))+0.000001));
	bn = bn- rate1;
	rate1 = (v2/(1-B12))*(rate/(sqrt(fabs(st2))+0.000001));
	w = w - rate1;
	rate1 = (v3/(1-B13))*(rate/(sqrt(fabs(st3))+0.000001));
	w1 = w1 - rate1;
	rate1 = (v4/(1-B14))*(rate/(sqrt(fabs(st4))+0.000001));
	w2 = w2 - rate1;
	#else
	gonu +=  go1*go1;
	gonu1 += go2*go2;
	gonu2 += go3*go3;
	gonu3 += go4*go4;
	rate1 = rate/((sqrt(gonu))+0.0000001);
	w = w - rate1*go1;
	rate1 = rate/((sqrt(gonu1))+0.0000001);
	w1 = w1 - rate1*go2;
	rate1 = rate/((sqrt(gonu2))+0.0000001);
	w2 = w2 - rate1*go3;
	rate1 = rate/(sqrt(gonu3));
	bn = bn- rate1*go4;
	wh += w*w+w1*w1+w2*w2;
	#endif
}

} 

 

主函数部分


int main(void)
{
	float xm=0,funt=0,loos=0,whh=0;
	static int ii=0;
	learning(0.9,25);
	
	#if Adam 
	printf("学习方式为Adam,学习次数为%ld,得到参数b=%f,x1=%f,x2=%f,x3=%f \n ",len,bn,w,w1,w2);
	#else 
	printf("学习方式为adgard,学习次数为%ld,得到参数b=%f,x1=%f,x2=%f,x3=%f \n ",len,bn,w,w1,w2);
	#endif
	 
	for(ii=0;ii<25;ii++)
	xm += y[ii];
	for(ii=0;ii<25;ii++)
	{
	funt = bn + w*buff1[ii]+ buff2[ii] *w1 +buff3[ii]*w2;
	loos += y[ii]-funt ;
}
printf("误差为百分之%.4f ",100*fabs(loos/xm));
	return 0;
 } 

最后附上运行截图(台式cpu不如笔记本,运行了5秒 笔记本1.6秒就完成)

总结 :adagrad的结果好像bn的值与初始值差距不大 可能是步长不够或者是我写的有错误什么的。 之前学习函数考虑用指针进行参数传递,但是出了一些小问题。

时间关系就更新这个了。

 

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SDU-cb

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

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

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

打赏作者

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

抵扣说明:

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

余额充值