线性回归原理推导+python代码手动实现

前言:

     线性回归在统计学中占据着极其重要的地位,可以说很多算法都是依据线性回归而优化升级出来的。因此,了解线性回归的基本原理,是学习统计学、机器学习不可或缺的一步。

关键词:一元线性回归、多元线性回归、最小二乘法、矩阵求导

引入:

       严谨的一对一,一对多的数学函数往往具有更大的说服力。然而,在日常的生活中,我们不得不承认,这种带有估计量的统计学更切近日常。因为生活中我们往往没有办法能够拿到所有的数据,因此,退而求其次地取其样本来估计总体就成了统计学的目标。而线性回归,就便是用样本来估计总体的一个算法。比如在研究国民体重和身高的关系的时候,我们没有办法对所有人都进行丈量,因此我们希望从人群中抽样出一部分具有代表性的人,对他们进行衡量,从而建立一个数学模型。估计出大概的身高和体重的关系。

算法原理及其推导:

       高中数学就已经教过线性回归的内容。其图像表达如下:

        我们的目标就是用样本去拟合一条直线y=wx+b其中y为对应的函数值,w被称为权重值或者参数,b为截距项也同时称为参数。我们可以将x看作是体重,y看作是身高,我们的目标就是要找出他们的关系。具体步骤可分为4步,也是统计机器学习几乎都要经历的4步:

  • 选定模型算法。
  • 确定损失函数。
  • 估计模型参数。
  • 用模型去估计预测。

        那么什么是损失函数,简而言之就是损失函数就是预测的值和真实值的差值

                                                                        \begin{matrix} {\varepsilon = {\mathit{\min}{\sum\limits_{i = 1}^{n}\left. \left( y \right._{i} - {\hat{y}}_{i} \right)^{2}}}\#(1.1)} \\ \end{matrix}                         

        其中y为对应的样本真实值,\hat{y}为对应的y=wx+b的值。我们的目标显而易见,就是要让\varepsilon最小,因此,损失函数的就可以写成如下

\begin{matrix} {​{\min\varepsilon} = {\min{\sum\limits_{i = 1}^{n}\left. \left( y \right._{i} - {\hat{y}}_{i} \right)^{2}}} = {\min{\sum\limits_{i = 1}^{n}\left\lbrack {y_{i} - \left( {wx_{i} + b} \right)} \right\rbrack^{2}}}\#(1.2)} \\ \end{matrix}

        再严谨一些实际上应该写作:

\begin{matrix} {​{\min\limits_{W,b}{\sum\limits_{i = 1}^{n}\left\lbrack {y_{i} - \left( {wx_{i} + b} \right)} \right\rbrack^{2~}}}\#(1.3)} \\ \end{matrix}

        意为将w、b作为变量,最小化这个函数。

        因此,当我们找到能够使这个函数达到最小,对应的w,b就是我们所要求的参数。那么如何能够求到最小值,当燃是使用最小二乘法啦,依据最小二乘法。我们可以得出如下公式(此处以一维变量为例,即假设x的维度是一维)

一元线性回归推导:

\begin{matrix} {w = \frac{​{\sum{x_{i}y_{i} - n{\overset{¯}{x}}_{i}}}{\overset{-}{y}}_{i}}{​{\sum{x_{i}}^{2}} - n{​{\overset{-}{x}}_{i}}^{2}}~~b = {\overset{-}{y}}_{i} - w{\overset{-}{x}}_{i}\#(1.4)} \\ \end{matrix}\displaystyle

        即当w、b的取值为上面的值的时候,我们就认为此时的损失函数达到最小。其中为单个样本其公式推导如下:

        因为我们要最小化公式(1.3).因此,根据我们的常识,如何求一个函数的最小值呢?当然是导数啦!公式中将W,b作为变量,因此,我们对这两个变量分别求导:

       对b求导(以下为了方便对Σ的起止省略):

    \begin{matrix} {\frac{\partial f(w,b)}{\partial b} = {\sum\left\lbrack {\left( {y_{i} - wx_{i} - b} \right)\left( {- 1} \right)} \right\rbrack}} \\ {~~~~~~~~~ = {\sum{​{- y}_{i} + {\sum{wx_{i} + {\sum b}}}}}} \\ \end{matrix}

       因为b的值不受i控制,因此

{\sum\limits_{i = 1}^{n}b} = n*b

        所以:

\begin{matrix} {​{\sum{​{- y}_{i} + {\sum{wx_{i} + {\sum b}}}}}\#} \\ \end{matrix}

\begin{matrix} {= {\sum{​{- y}_{i} + {\sum{wx_{i} + nb}}}} = 0\#} \\ \end{matrix}\displaystyle

移项得:

\begin{matrix} {b = \frac{​{\sum y_{i}} - {\sum{wx_{i}}}}{n} = \overset{-}{y} - w\overset{-}{x}\#(1.5)} \\ \end{matrix}

              对w求导并等于0

                                        \begin{matrix} {\frac{\partial f\left( {w,b} \right)}{\partial w} = {\sum\left\lbrack {\left( {y_{i} - wx_{i} - b} \right)\left( {- x_{i}} \right)} \right\rbrack}\#} \\ \end{matrix}

              将式(1.5)代入:

                                            \sum\left\lbrack {\left( {y_{i} - wx_{i} - b} \right)\left( {- x_{i}} \right)} \right\rbrack

= {\sum\left\lbrack {\left( {y_{i} - wx_{i} - \overset{-}{y} + w\overset{-}{x}} \right)\left( {- x_{i}} \right)} \right\rbrack}

= {\sum\left\lbrack \left( {​{- y}_{i}x_{i} + w{x_{i}}^{2} + \overset{-}{y}x_{i} - w\overset{-}{x}x_{i}} \right) \right\rbrack}\displaystyle

= - {\sum{y_{i}x_{i}}} + {\sum{w{x_{i}}^{2}}} + {\sum{\overset{-}{y}x_{i}}} - {\sum{w\overset{-}{x}x_{i}}} = 0

              移项得:

w\left( {\sum{​{x_{i}}^{2} - {\sum{\overset{-}{x}x_{i}}}}} \right) = {\sum{y_{i}x_{i}}} - {\sum{\overset{-}{y}x_{i}}}

              即:

w = \frac{​{\sum{y_{i}x_{i}}} - {\sum{\overset{-}{y}x_{i}}}}{\sum{​{x_{i}}^{2} - {\sum{\overset{-}{x}x_{i}}}}}

              因为:

                                                       \left. \overset{-}{x} = \frac{1}{n}{\sum x_{i}}\rightarrow n\overset{-}{x} = {\sum x_{i}} \right.

              所以:

w = = \frac{​{\sum{y_{i}x_{i}}} - n\overset{-}{y}\overset{-}{x}}{\sum{​{x_{i}}^{2} - n{\overset{-}{x}}^{2}}}

       因此,公式就出来啦!

多元线性回归推导:

        然而,现实生活中,我们遇到的往往不仅仅是体重和身高关系的这种问题,其有更为复杂的问题。比如我们要研究一个人的(身高,体重,颜值,智商)等等与气质的关系。并且要求求出各个变量对气质的影响程度,因此。我们就要引入多元线性回归。其表达式我们依然用    

        注意了,这里的W^1代表的是W的分量的,也就是W的一个维度分量。
为了方便运算和求导证明,接下来我们对线性方程变换一下y=w^T*X

其中:

                                        

              那么此时的损失函数又该如何求解呢?首先,必须掌握对矩阵求导的知识。

       在此笔者不作证明,直接给出必要的矩阵求导公式,感兴趣的读者可以查阅资料进行了解。

     

       

       来看损失函数,

       令:

令                            

  

  

       由此可得:

                          

       所以:“

        由于:

              因此

       要对其求最小化,就对其W求导:

       整理得:

优化:

        可以看到,公式(1.7)实际上是有点问题的,我们如何确定一定可逆呢?我们是无法确定的,当样本的容量不能够远远的大于样本的维度时,可能会造成不可逆。换一角度来说,这实际上会造成模型的过拟合。而解决模型过拟合的方式,有一种·有力的方式就是在损失函数加入L1或者L2正则化项。最终其损失函数如下                     

       最终沿用上面的求解方法,得出:

因为

        ​​

所以为半正定矩阵,又因λI为正定矩阵,所以为正定矩阵,可逆。

代码实现:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from mpl_toolkits.mplot3d import Axes3D
'''
本次代码使用二维变量
'''
np.random.seed(200) #随机数种子
#绘图函数
def plt_piture(x1,x2,norm_y,w):
    fig=plt.figure()
    y_predict=x1*w[0][0]+x2*w[1][0]+w[2][0]
    ax=Axes3D(fig)
    ax.plot(x1,x2,y_predict)
    ax.scatter(x1,x2,norm_y, c="r")
    plt.show()

def main():
    x1 = np.arange(0, 100, 2).reshape(-1,1)#变量的第一个维度并重新定义形状
    x2=np.arange(0,100,2).reshape(-1,1)#变量的第二个维度并重新定义形状
    x=np.concatenate([x1,x2],axis=1)#将两个维度合并 shape(50,2)
    #依据公式,为了方便,我们将x的维度扩展一个全为1的维度
    x_b=np.concatenate([x,np.ones_like(x1).reshape(-1,1)],axis=1)
    #计算对应的y,并从均值为0,方差为10的正太分布中抽取样本加上原始的y值
    norm_y=(x1+x2+stats.norm.rvs(0,10,x1.size).reshape(-1,1))
    #依据普通损失函数,利用最小二乘法求出w的值,其中@代表点积,pinv求矩阵的伪逆
    w=np.linalg.pinv(x_b.T@x_b)@x_b.T@norm_y
    #计算正则化后的损失函数对应的w,linalg.inv为求矩阵的逆,np.eye是生成单位矩阵
    lambda_=0.01
    norm_w=np.linalg.inv(x_b.T@x_b+lambda_*np.eye(x_b.shape[1]))@x_b.T@norm_y
    #打印对应的值
    print("原损失函数的权重值:")
    print("x1系数为{}".format(w[0][0]))
    print("x2系数为{}".format(w[1][0]))
    print("截距b为{}".format(w[2][0]))
    print("正则化后损失函数的权重值:")
    print("x1系数为{}".format(norm_w[0][0]))
    print("x2系数为{}".format(norm_w[1][0]))
    print("截距b为{}".format(norm_w[2][0]))
    #绘制函数图像
    plt_piture(x_b[:,0],x_b[:,1],norm_y.reshape(-1),w)
if __name__ == '__main__':
    main()

结束语:

       文章中有许多不够严谨的地方,如果有什么不对的地方还望读者能够不吝赐教。因为笔者也是正在学习的阶段,写博客纯粹就是为了确认自己是否是真的懂了,是否遗漏了什么细节,是否印象足够深刻。所以,各位多多担待哈,阿里嘎多。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值