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还可以更小。

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

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

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

  • 相关阅读:
    欧拉回路 定理
    UESTC 1087 【二分查找】
    POJ 3159 【朴素的差分约束】
    ZOJ 1232 【灵活运用FLOYD】 【图DP】
    POJ 3013 【需要一点点思维...】【乘法分配率】
    POJ 2502 【思维是朴素的最短路 卡输入和建图】
    POJ 2240 【这题貌似可以直接FLOYD 屌丝用SPFA通过枚举找正权值环 顺便学了下map】
    POJ 1860【求解是否存在权值为正的环 屌丝做的第一道权值需要计算的题 想喊一声SPFA万岁】
    POJ 1797 【一种叫做最大生成树的很有趣的贪心】【也可以用dij的变形思想~】
    js 实现slider封装
  • 原文地址:https://www.cnblogs.com/myshuzhimei/p/11743544.html
Copyright © 2011-2022 走看看