梯度下降及logistic回归

批量梯度下降是一种对参数的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;
}








你可能感兴趣的:(梯度下降及logistic回归)