批量梯度下降是一种对参数的update进行累积,然后批量更新的一种方式。用于在已知整个训练集时的一种训练方式,但对于大规模数据并不合适。
随机梯度下降是一种对参数随着样本训练,一个一个的及时update的方式。常用于大规模训练集,当往往容易收敛到局部最优解。
logistics是离散的,必须是分类变量,一般用于分类问题,比如身高高矮;
而线性回归必须是连续性数据变量,比如告诉你一些身高与体重,得到身高与体重的关系。
这是一开始的程序,后来发现有误,因为权重的更新应该是在所有样本在这次的迭代之后.(英文太难理解了,看得一知半解)
#include <stdio.h> #include <string.h> int main() { double matrix[4][3]={{1,1,4},{1,2,5},{1,5,1},{1,4,2}};//4组数据,每组数据有2个因素(第一个为1) double result[4]={19,26,19,20}; double theta[3]={0,0,0};//也就是要求的系数,因为影响的因素有两个,所以系数有两个 double loss,sum,error_sum,h; int t,i,j,k; loss=10;//loss是为了当精度已经符合要求时提前退出的操作,可省略 for (t=1;t<=100000&&loss>0.01;t++)//迭代1000次 { for (i=0;i<4;i++)//4组数据 { h=0; error_sum=0; for (k=0;k<3;k++)//2个影响因子 { h=h+matrix[i][k]*theta[k];//按照现在的系数和数据得到的拟合值 } error_sum=result[i]-h; for (k=0;k<3;k++) { theta[k]=theta[k]+0.01*error_sum*matrix[i][k]; } } loss=0;//接下来的部分是评估系数是否合格,如果迭代次数够多肯定也没问题 for (j=0;j<4;j++) { sum=0; for (k=0;k<3;k++) { sum=sum+matrix[j][k]*theta[k]; } loss=loss+(sum-result[j])*(sum-result[j]);//这个差值的评估函数与最小二乘法是一致的 } } printf("%lf,%lf,%lf,%lf\n",theta[0],theta[1],theta[2],loss); return 0; }
#include <stdio.h> #include <string.h> int main() { double matrix[4][2]={{1,4},{2,5},{5,1},{4,2}};//4组数据,每组数据有2个因素(第一个为1) double result[4]={19,26,19,20}; double theta[2]={0,0};//也就是要求的系数,因为影响的因素有两个,所以系数有两个 double loss,sum,h; int t,i,j,k; loss=10;//loss是为了当精度已经符合要求时提前退出的操作,可省略 for (t=1;t<=10000&&loss>0.01;t++)//迭代1000次 { double error_sum[2]={0.0,0.0};//注意更新权重是在所有样本求和之后进行梯度下降的 for (i=0;i<4;i++)//4组数据 { h=0.0; for (k=0;k<2;k++)//2个影响因子 { h=h+matrix[i][k]*theta[k];//按照现在的系数和数据得到的拟合值 } for (k=0;k<2;k++) { error_sum[k]=error_sum[k]+(result[i]-h)*matrix[i][k];//先记录下cost数组,但是不跟新(等到所有样本在该次迭代中都被访问过了,再迭代) } } for (k=0;k<2;k++) { theta[k]=theta[k]+0.001*error_sum[k]/4; } loss=0;//接下来的部分是评估系数是否合格,如果迭代次数够多肯定也没问题 for (j=0;j<4;j++) { sum=0; for (k=0;k<2;k++) { sum=sum+matrix[j][k]*theta[k]; } loss=loss+(sum-result[j])*(sum-result[j]);//这个差值的评估函数与最小二乘法是一致的 } } printf("%lf,%lf,%lf\n",theta[0],theta[1],loss); return 0; }
代码和线性回归基本一样,唯一的区别是增加了一个sigmoid函数,把原来的h(x)变为1/1+e^(-hx) 然后求误差,梯度下降改参数,同上
另外注意引入sigmoid函数,其实这个函数的目的就是将原来梯度下降求得的y值转化为0~1区间的一个值。
/* sigmoid函数是一个良好的阈值函数, 连续,光滑 严格单调 关于(0,0.5)中心对称 对阈值函数有一个良好的近似 原函数:f(x) = 1/[1+e^(-x)] 其中,当你写代码的时候,如果f(x)不好写,你可以写成f(x)=ex/1+ex的形式,其中ex是pow(2.7182818228,x)的形式,即e的x次幂 */ #include <stdio.h> #include <math.h> double Function(double x) { double ex=exp(x); return ex/(1+ex); } int main() { double matrix[6][4]= {{1,47,76,24}, {1,46,77,23}, {1,48,74,22}, {1,34,76,21}, {1,35,75,24}, {1,34,77,25}, }; double result[6]={1,1,1,0,0,0}; double theta[4]={0,0,0,0}; int i,j,k; double h,error,sum; for (i=0;i<100000;i++) { double cost[4]={0,0,0,0}; for (j=0;j<6;j++) { h=0; for (k=0;k<4;k++) h=h+matrix[j][k]*theta[k]; error=Function(h)-result[j]; for (k=0;k<4;k++) { cost[k]=cost[k]+error*matrix[j][k]; } } for (k=0;k<4;k++) theta[k]=theta[k]-cost[k]*0.01/4;//这里的正负是与前面的加减法有关的 printf("%.4f %.4f %.4f %.4f\n",theta[0],theta[1],theta[2],theta[3]); } return 0; }