zoukankan      html  css  js  c++  java
  • 线性回归预测算法

    单变量的线性回归非常容易理解,就是生成一元一次方程:

    y=ax+b。x表示自变量,特征属性的值;y表示因变量,预测标签的值。
    二维图像更直观:x是横坐标,y是纵坐标,a是斜率,b是与纵坐标的截距。
    样本的坐标点有限,也不会都在一条直线上。如何拟合一条合理的直线,本文会详细解析。
     
    看懂一元一次方程的推导,就不难理解多元一次方程、一元m次方程、多元m次方程。后面的就不解析了。
    不管几元几次,都可以直接调用sklearn库相关模块:sklearn.linear_model和sklearn.preprocessing
    sklearn.linear_modlel封装的是线性函数:
    • 普通线性回归函数( LinearRegression ) 
    • 岭回归(Ridge) 
    • Lasso(Lasso)
    sklearn.preprocessing封装的是非线性函数:
    • 多项式回归(PolynomialFeatures)
     
    在实际项目中非线性回归远远多于线性回归。多项式回归实际上是先将变量X处理成多项式特征,然后使用线性模型学习多项式特征的参数,以达到多项式回归的目的。例如:X = [x1, x2]
    1.使用PolynomialFeatures构造X的二次多项式特征X_Poly:
    X_Poly=[x1,x2,x1x2,x1^2,x2^2]
    2.使用linear_model学习X_Poly和y之间的映射关系。
    多项式回归的最大优点是可以通过增加x的高次项对样本进行逼近,直至满意为止。
    PolynomialFeatures(degree=4)表示4次项,PolynomialFeatures(degree=9)表示9次项。
    degree设置过高,会让样本看起来完全拟合,其实就是过拟合现象。过拟合会导致新样本严重失真。
    合理设置degree,可以加大测试样本比较损失函数来挑选[1,10]间的自然数。也可以考虑矫正拟合方法:https://www.jianshu.com/p/f238457f505b 
    单变量线性回归推导示例:
    项目案例:某商企开业初期,在不同试点安排了若干名地推人员,推销会员活动。
    该商企想分析下地推人员数量和卖出会员数量的关系,以便后期类似活动时提前部署。
    数据信息如下(为了推演方便,仅选取5条数据):
    地推人员数量 卖出会员数量
           1        14
           2        24
           2        18
           1        17
           3        27
         
    将地推人员数量作为自变量X,卖出会员数量当做因变量Y,坐标轴上几个点的图形:
    线性回归预测算法
     
    这几个点上下交错,相互连接是构不成一条直线的。如何构建线性模型 y = ax + b 呢?
    这里就要提到线性回归的平方和损失函数:  
    线性回归预测算法
    Yi是样本真实值,Y'i是样本预测值,n表示样本数量。
    如果这条直线和各个点之间的距离损失和达到最小,那它就是最优直线。也就是对损失函数求最小值。
    线性回归预测算法
    对损失函数求最小值就是运用的最小二乘法思想:最小表示min,二乘表示平方。
    两点之间的距离更容易想到绝对值,用平方是因为比起取绝对值,更便于数据计算处理。
     
    因为Yi=a*Xi+b,所以需要求解的是:
    线性回归预测算法
     
    直接看求解答案:

    机器学习简单线性回归模型

    机器学习简单线性回归模型

    横线头代表样本均值,通过上面的公式可以计算得到a和b,从而得到线性方程 y = ax + b 。
      

    应用层面可以直接拿公式套,甚至公式也不用记,开源库都封装好了方法,传入样本数据即可得方程式。

    本着不光知其然还要知其所以然的态度,查阅了一些资料,总结成自己最易理解的语言阐述下求解过程。

    求解过程:

    令f(x,y)=∑(Yi-(a*Xi+b))^2,将样本点代入,并将a、b转为常见的x、y变量。得出:

    f(x,y)=(1x+y-14)^2+ (2x+y-24)^2+ (2x+y-18)^2 + (1x+y-17)^2+ (3x+y-27)^2 

    f(x,y)是一个二元二次分布式,看一下它的三维图像:

    线性回归预测算法

    上图x、y坐标显示很清晰,但是z坐标不立体,换个角度看:

    线性回归预测算法

    从上图可以看出,这个图像是有谷底的,谷底就是f(x,y)的最小值。

    在谷底处,不管x坐标,还是y坐标,其斜率都是0,也就是x和y的导数都是0。

    所以,求f(x,y)的最小值就是求x导数=0和y导数=0。这个结论是重点、重点、重点!

    为什么强调它,是因为查阅的N多文章都直接抛出:求f(x,y)的最小值就是求x和y的导数。这句话有2个问题:

    一、怎么得出这个结论的?

    二、x和y的导数是个函数,f(x,y)的最小值应该是个固定值,怎么能划等号?

    后来看到一篇严谨的文章说:求f(x,y)的最小值是求x和y的导数等于0,并不能仅仅说求x和y的导数。

    问题二解决了,可是问题一依然困惑。

    一元二次方程求极值=求一元变量导数等于0,这个容易理解是因为抛物线的图像深入我心。

    那不如类比一下,看看二元二次方程的图像吧。这才有了上面两个三维图像的来源。用python Axes3D画的。

    看这个图像就很容易理解为什么要求导、为什么求两个变量的、为什么导数应该等于0了!

    现在来重温下求导的知识点:

    • 基本求导公式
           给出自变量增量   ;
           得出函数增量 ;
           作商 ;
           求极限

           比如 y=x^2,求y的导数,按照上述步骤:

            Δy=(x+Δx)^2-x^2=2xΔx+Δx^2 ;Δy/Δx=2x+Δx ;Δx趋于0,所以y的导数=2x。

    • 导数的四则运算法则

           (u+v)'=u'+v'

           (u-v)'=u'-v'

           (uv)'=u'v+uv'

           (u/v)'=(u'v-uv')/v^2

    • 复合函数维度下降法求导

           f[g(x)]中,设g(x)=u,则f[g(x)]=f(u),f'[g(x)]=f'(u)*g'(x)

           比如y=(3x-2)^2,令y=u^2,u=3x-2. y'(x)=y'(u)*u'(x)=2*(3x-2)*3=18x-12.

    现在可以对 f(x,y)=(1x+y-14)^2+ (2x+y-24)^2+ (2x+y-18)^2 + (1x+y-17)^2+ (3x+y-27)^2 求导了 :

    x导数=2*(x+y-14)*1+2*(2x+y-24)*2+2*(2x+y-18)*2+2*(x+y-17)*1+2*(3x+y-27)*3

    y导数=2*(x+y-14)*1+2*(2x+y-24)*1+2*(2x+y-18)*1+2*(1x+y-17)*1+2*(3x+y-27)*1

    目的是求得x导数=0、y导数=0时的x、y值。即:

    (x+y-14)+(2x+y-24)*2+(2x+y-18)*2+(x+y-17)+(3x+y-27)*3=0

    (x+y-14)+(2x+y-24)+(2x+y-18)+(x+y-17)+(3x+y-27)=0

    即:

    19x+9y=196

    9x+5y=100

    这是一个二元一次方程,很容易求得:x=5.7142,y=9.7142.

    下面证明简化版的求解公式是怎么来的:

     分别对a和b求一阶偏导,求导后让其等于0,然后联立方程组解得参数a和b。

    机器学习简单线性回归模型

    机器学习简单线性回归模型

    机器学习简单线性回归模型

    套用这个公式,依然求得:a=5.7142,b=9.7142.

    看下二元方程图像求极值的代码,比较结果是否和求导/套用公式的一致:

    import numpy as np

    if __name__ == '__main__': 

       x = np.arange(0, 20, 0.1)

       y = np.arange(0, 20, 0.1)

       x, y = np.meshgrid(x, y) 

       z = (1*x+y-14)**2+ (2*x+y-24)**2+ (2*x+y-18)**2 + (1*x+y-17)**2+ (3*x+y-27)**2      

       q=[]

       for i in range(0,200,1):

          q.append(z[i])

       z=z.flatten()

       w= min(z)

       print ("损失函数的最小值是: "+str(w))

       for i in range(200):

           for j in range(200):

              if q[i][j]==w:

                 break

          else: 

              continue

           break

       print ("a、b参数的值分别是: "+str(x[i][j])+" , "+str(y[i][j]))

      输出:

      损失函数的最小值是: 22.58

      a、b参数的值分别是:5.7 , 9.7

    这个结果精度不如前面两个。原因在于x、y坐标移动步长0.1还可以更小。

    如果步长太小又会导致性能变差。顺着这个思路,就不难理解梯度下降法了。

    实际项目都是用计算机的梯度下降法来求极值,所以求导部分理解即可,不用强记。

    最后看下最优直线长什么样子吧:

  • 相关阅读:
    spring bean的三种管理方式·
    mybatis解决字段名和实体属性不相同
    python字符串格式化方法%s和format函数
    myeclipse配置springmvc教程
    2019ICPC南昌站
    浅谈可持久化线段树(主席树)
    2019CCPC厦门站总结
    牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
    2019牛客暑期多校训练营(第一场)A
    [The Preliminary Contest for ICPC Asia Nanjing 2019] L-Digit sum
  • 原文地址:https://www.cnblogs.com/myshuzhimei/p/11743544.html
Copyright © 2011-2022 走看看