梯度下降算法解决多元线性回归问题 c++实现
没有数据标准化的版本,效率非常低,而且训练结果并不好。
#include <iostream> #define maxn 105 #include <cstdio> #include <cmath> using namespace std; int n,m; //n个特征,m个数据 double theta[maxn];//参数集 double temp[maxn]; double data[maxn][maxn];//数据集 double Y[maxn];//结果集 double hx[maxn]; const double eps=1e-9; double alpha=0.00001; double h(int x)//计算假设函数 { double res=0; for(int i=0;i<=n;++i) { res+=theta[i]*data[x][i]; } return res; } double J_theta()//计算cost function { double res=0; for(int i=1;i<=m;++i) { res+=(h(i)-Y[i])*(h(i)-Y[i]); } res=res/(2*m); return res; } double f(int x)//求偏导数 { double res=0; for(int i=1;i<=m;++i) { res+=hx[i]*data[i][x]; } res/=m; return res; } void Gradient_Descent()//梯度下降 { for(int i=1;i<=m;++i) { data[i][0]=1; } for(int i=0;i<=n;++i) { theta[i]=1;//初始化 } double now,nex; do { now=J_theta(); for(int i=1;i<=m;++i) { hx[i]=h(i)-Y[i]; } for(int i=0;i<=n;++i) { temp[i]=theta[i]-alpha*f(i); } for(int i=0;i<=n;++i) { theta[i]=temp[i]; } nex=J_theta(); //cout<<J_theta()<<endl; }while (abs(nex-now)>eps); } int main() { freopen("in.txt","r",stdin); cin>>n>>m; for(int i=1;i<=m;++i) { for(int j=1;j<=n;++j) { cin>>data[i][j]; } } for(int i=1;i<=m;++i) { cin>>Y[i]; } Gradient_Descent(); for(int i=0;i<=n;++i) { printf("%.2lf\n",theta[i]); } return 0; }
下面是将数据归一化之后的版本,效率较高:
#include <iostream> #define maxn 105 #include <cmath> #include <algorithm> #include <cstdio> using namespace std; int n,m; //n个特征,m个数据 double theta[maxn];//参数集 double temp[maxn]; double data[maxn][maxn];//数据集 double Y[maxn];//结果集 double hx[maxn]; const double eps=1e-9; double alpha=0.001; double ave[maxn]; void Mean_Normaliazation() { for(int i=0;i<=n;++i) { double maxim=-1e9; double minum=1e9; double tmp=0; for(int j=1;j<=m;++j) { tmp+=data[j][i]; } tmp/=m; double mb=0; for (int j=1;j<=m;++j) { mb+=(data[j][i]-tmp)*(data[j][i]-tmp); } mb/=m; mb=sqrt(mb); for(int j=1;j<=m;++j) { data[j][i]=(data[j][i]-tmp)/mb; } } double maxim=-1e9; /*double tmp=0; for(int i=1;i<=m;++i) { maxim=max(Y[i],maxim); tmp+=Y[i]; } tmp/=m; for(int i=1;i<=m;++i) { Y[i]=(Y[i]-tmp)/maxim; }*/ } double h(int x)//计算假设函数 { double res=0; for(int i=0;i<=n;++i) { res+=theta[i]*data[x][i]; } return res; } double J_theta()//计算cost function { double res=0; for(int i=1;i<=m;++i) { res+=(h(i)-Y[i])*(h(i)-Y[i]); } res=res/(2*m); return res; } double f(int x)//求偏导数 { double res=0; for(int i=1;i<=m;++i) { res+=hx[i]*data[i][x]; } res/=m; return res; } void Gradient_Descent()//梯度下降 { for(int i=1;i<=m;++i) { data[i][0]=1; } for(int i=0;i<=n;++i) { theta[i]=1;//初始化 } double now,nex; do { now=J_theta(); for(int i=1;i<=m;++i) { hx[i]=h(i)-Y[i]; } for(int i=0;i<=n;++i) { temp[i]=theta[i]-alpha*f(i); } for(int i=0;i<=n;++i) { theta[i]=temp[i]; } nex=J_theta(); //cout<<J_theta()<<endl; }while (abs(nex-now)>eps); } int main() { freopen("in.txt","r",stdin); cin>>n>>m; for(int i=1;i<=m;++i) { for(int j=1;j<=n;++j) { cin>>data[i][j]; } } for(int i=1;i<=m;++i) { cin>>Y[i]; } Mean_Normaliazation(); Gradient_Descent(); for(int i=0;i<=n;++i) { printf("%.2lf\n",theta[i]); } return 0; }
训练数据在这里:
2 10 100 4 50 3 100 4 100 2 50 2 80 2 75 3 65 4 90 3 90 2 9.3 4.8 8.9 6.5 4.2 6.2 7.4 6.0 7.6 9.3 4.8 8.9 6.5