之前事情太多一直没写博客,上学期十二月份打完区域赛就耻辱退役了。。。这段时间会一边学习一边用C++实现机器学习和图像识别的算法,希望代码没事。。。
线性回归中只有一个极值点所以可以放心用Batch梯度下降法
提前求和之后每次梯度下降复杂度为O(1)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps=1e-10;
//假设函数为y=theta[1]*x+theta[0]
//Batch梯度下降法求解线性回归
double * solve(double x[],double y[],int m)//输入数组x,y和长度m(训练集大小)
{
static double theta[5]; //返回Theta0和1作为结果
double alpha=0.1; //设置学习率
theta[1]=0.5,theta[0]=0.0; //设置初始值
double tmp1=0.0,tmp2=0.0;
double sumx=0.0,sumy=0.0,sumx2=0.0,sumxy=0.0;
for(int i=1;i<=m;i++)
{
sumx=1.0*sumx+1.0*x[i];
sumy=1.0*sumy+1.0*y[i];
sumx2=1.0*sumx2+1.0*x[i]*x[i];
sumxy=1.0*sumxy+1.0*x[i]*y[i];
}
//cout<<sumx<<" "<<sumy<<" "<<sumx2<<" "<<sumxy<<endl;
//int t=100; 下降次数过多时可以设置次数观察是否有问题
while(1)
{
tmp1=1.0*theta[1]*sumx+1.0*m*theta[0]-1.0*sumy;
tmp2=1.0*theta[1]*sumx2+1.0*sumx*theta[0]-1.0*sumxy;
cout<<tmp1<<" "<<tmp2<<endl;
if(abs(tmp1)<eps&&abs(tmp2)<eps)//导数等于0时停止
{
break;
}
tmp1=1.0*alpha/(1.0*m)*tmp1;
tmp2=1.0*alpha/(1.0*m)*tmp2;
theta[0]=1.0*theta[0]-1.0*tmp1;
theta[1]=1.0*theta[1]-1.0*tmp2;
cout<<tmp1<<" "<<tmp2<<endl;
cout<<theta[1]<<" "<<theta[0]<<endl;
}
return theta;
}
int main()
{
double x[15],y[15];
int m=3;
x[1]=1;
x[2]=2;
x[3]=3;
y[1]=1;
y[2]=2;
y[3]=3;
double * theta;
theta=solve(x,y,m);
cout<<theta[1]<<" "<<theta[0]<<endl;
return 0;
}
实际函数是y=x+1,初始值设定为y=0.5x
下面是包含了每次的导数的结果