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

1. Adam

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

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

1.1 定义

机器学习深度学习笔记,常用算法Adam与Adagard。使用c++开发。_第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 定义 

机器学习深度学习笔记,常用算法Adam与Adagard。使用c++开发。_第2张图片

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

下面给出代码段

开头定义段

#include
#include

//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

 

主函数部分


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秒就完成)

机器学习深度学习笔记,常用算法Adam与Adagard。使用c++开发。_第3张图片

机器学习深度学习笔记,常用算法Adam与Adagard。使用c++开发。_第4张图片

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

时间关系就更新这个了。

 

你可能感兴趣的:(机器学习,深度学习,机器学习,矩阵,算法,c++)