梯度下降C++实现

事先声明,机器学习入门,手写代码加深理解,加了一些自己的理解。文中的代码实现借鉴自另一大神博主,如有需要,请戳:https://blog.csdn.net/pennyliang/article/details/6998517(自己动手真的能学到很多)

欢迎一起交流学习,不足之处,还请指正。

/*

Matrix_A

1   4
2   5
5   1
4   2
theta_C

?

?
Matrix_A*theta_C
19
26
19
20
*/

具体情景为对衣服的估价,矩阵A表示衣服的特征,如第一列可以表示颜色评分,第二列可以表示质地评分。矩阵C表示假设函数中的参数。矩阵A*矩阵C表示的是衣服的真实价格。

批梯度下降

#include "stdio.h"  
#include<iostream>

using namespace std;

int main()
{
	        float matrix[4][2] = { { 1,4 },{ 2,5 },{ 5,1 },{ 4,2 } };//训练集合特征
	        float result[4] = { 19,26,19,20 };
	        float theta[2] = { 2,5 };                   // 对于参数,给定一个初始值,后面根据训练集合来不断优化
	        float learning_rate = 0.01;
	        float loss = 1000.0;                    //用来判断是否收敛的一个变量,从后面可以看出,这里采用的是最小二乘法 
		for (int i = 0; i<100 && loss>0.0001; ++i)
		{
		    float error_sum = 0.0;
		    float cool[2] = { 0.0, 0.0 };
		    for (int j = 0; j<4; ++j)//对于每次迭代需要遍历一遍整个训练集合
	            {
			float h = 0.0;								
			for (int k = 0; k<2; ++k)
		        {
		            h += matrix[j][k] * theta[k];
		        }
			error_sum = h-result[j] ;//注意这里用的是假设函数减去样本							                for (int k = 0; k < 2; ++k)								                                    {
			    cool[k] += error_sum * matrix[j][k];
			}
		    }
		    for (int k = 0; k<2; ++k)//每次迭代需要更新一次参数
		    {
			theta[k] -= learning_rate * cool[k];
		    }
		    printf("*************************************\n");
		    printf("theta now: %f,%f\n", theta[0], theta[1]);
		    loss = 0.0;
		    for (int j = 0; j<4; ++j)//利用最小二乘法求出loss
		    {
		        float sum = 0.0;
			for (int k = 0; k<2; ++k)
		        {					
			    sum += matrix[j][k] * theta[k];
		        }
			    loss += (sum - result[j])*(sum - result[j]);
	            }
		    printf("loss  now: %f\n", loss);
	        }			
		system("PAUSE");
	        return 0;
}
这里有一点需要注意,原博文中把更新参数值放在了每次迭代时遍历整个训练集合的for循环中,评论区说是有问题,个人理解并没有问题,因为在每次迭代中更新theta时,每个训练样本对theta更新都用贡献,这里只是在每次遍历时去改变一下theta而不是最后求和来一次性更新theta,只是这样做使得theta概念有些不清晰,不易理解,所以我新加了一个cool数组。

随机梯度下降

int main()
{
        float matrix[4][2]={{1,4},{2,5},{5,1},{4,2}};
        float result[4]={19,26,19,20};
        float theta[2]={2,5};
        float loss = 10.0;
        for(int i =0 ;i<100&&loss>0.001;++i)
        {
                float error_sum=0.0;
                int j=i%4;//每次迭代只用一个训练样本,j=0,1,2,3,其他部分与批梯度下降相同
                {
                        float h = 0.0;
                        for(int k=0;k<2;++k)
                        {
                                h += matrix[j][k]*theta[k];

                        }
                        error_sum = result[j]-h;
                        for(int k=0;k<2;++k)
                        {
                                theta[k] += 0.01*(error_sum)*matrix[j][k];
                        }
                }
                printf("%f,%f\n",theta[0],theta[1]);
                float loss = 0.0;
                for(int j = 0;j<4;++j)
                {
                        float sum=0.0;
                        for(int k = 0;k<2;++k)
                        {

                                sum += matrix[j][k]*theta[k];
                        }
                        loss += (sum-result[j])*(sum-result[j]);
                }
                printf("%f\n",loss);
        }
        return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值