41 | 线性回归(下):如何使用最小二乘法进行效果验证?-程序员宅基地

技术标签: 数学基础  最小二乘法  线性回归  

上一节我们已经解释了最小二乘法的核心思想和具体推导过程。今天我们就用实际的数据操练一下,这样你的印象就会更加深刻。我会使用几个具体的例子,演示一下如何使用最小二乘法的结论,通过观测到的自变量和因变量值,来推算系数,并使用这个系数来进行新的预测。

基于最小二乘法的求解

假想我们手头上有一个数据集,里面有 3 条数据记录。每条数据记录有 2 维特征,也就是 2 个自变量,和 1 个因变量。

如果我们假设这些自变量和因变量都是线性的关系,那么我们就可以使用如下这种线性方程,来表示数据集中的样本:

也就是说,我们通过观察数据已知了自变量 x1​、x2​ 和因变量 y 的值,而要求解的是 b1​ 和 b2​ 这两个系数。如果我们能求出 b1​ 和 b2​,那么在处理新数据的时候,就能根据新的自变量 x1​ 和 x2​ 的取值,来预测 y 的值。

可是我们说过,由实际项目中的数据集所构成的这类方程组,在绝大多数情况下,都没有精确解。所以这个时候我们没法使用之前介绍的高斯消元法,而是要考虑最小二乘法。根据上一节的结论,我们知道对于系数矩阵 B,有:

既然有了这个公式,要求 B 就不难了,让我们从最基本的几个矩阵开始。

矩阵 的求解稍微繁琐一点。逆矩阵的求法我还没讲解过,之前我们说过线性方程组之中,高斯消元和回代的过程,就是把系数矩阵变为单位矩阵的过程。我们可以利用这点,来求解 X^{-1}。我们把原始的系数矩阵 X 列在左边,然后把单位矩阵列在右边,像 [X∣I] 这种形式,其中 I 表示单位矩阵。

然后我们对左侧的矩阵进行高斯消元和回代,把左边矩阵 X 变为单位矩阵。同时,我们也把这个相应的矩阵操作运用在右侧。这样当左侧变为单位矩阵之后,那么右侧的矩阵就是原始矩阵 X 的逆矩阵X^{-1},具体证明如下:

最终,我们求出系数矩阵为 [11.5],也就是说 b1​=1, b2​=1.5。实际上,这两个数值是精确解。我们用高斯消元也是能获得同样结果的。接下来,稍微修改一下 y 值,让这个方程组没有精确解。

计算完毕之后,你会发现两个系数的值分别变为 b1​=0.938,b2​=1.415。由于这不是精确解,所以让我们看看有了这系数矩阵 B 之后,原有的观测数据中,真实值和预测值的差别。

首先我们通过系数矩阵 B 和自变量矩阵 X 计算出来预测值。

然后是样本数据中的观测值。这里我们假设这些值是真实值。

根据误差 ε 的定义,我们可以得到:

说到这里,你可能会怀疑,通过最小二乘法所求得的系数 b1​=0.949 和 b2​=1.415,是不是能让 ε 最小呢?这里,我们随机的修改一下这两个系数,变为 b1​=0.95 和 b2​=1.42,然后我们再次计算预测的 y 值和 ε。

很明显,0.064 是大于之前的 0.0158。

这两次计算预测值 _y_ 的过程,其实也是我们使用线性回归,对新的数据进行预测的过程。简短地总结一下,线性回归模型根据大量的训练样本,推算出系数矩阵 B,然后根据新数据的自变量 X 向量或者矩阵,计算出因变量的值,作为新数据的预测。

Python 代码实现

这一部分,我们使用 Python 的代码,来验证一下之前的推算结果是不是正确,并看看最小二乘法和 Python sklearn 库中的线性回归,这两种结果的对比。

首先,我们使用 Python numpy 库中的矩阵操作来实现最小二乘法。主要的函数操作涉及矩阵的转置、点乘和求逆。具体的代码和注释列在了下方。

from numpy import *

x = mat([[0,1],[1,-1],[2,8]])
y = mat([[1.4],[-0.48],[13.2]])

# 分别求出矩阵X'、X'X、(X'X)的逆
# 注意,这里的I表示逆矩阵而不是单位矩阵
print("X矩阵的转置X':\n", x.transpose())
print("\nX'点乘X:\n", x.transpose().dot(x))
print("\nX'X矩阵的逆\n", (x.transpose().dot(x)).I)

print("\nX'X矩阵的逆点乘X'\n", (x.transpose().dot(x)).I.dot(x.transpose()))
print("\n系数矩阵B:\n", (x.transpose().dot(x)).I.dot(x.transpose()).dot(y))

通过上述代码,你可以看到每一步的结果,以及最终的矩阵 B。你可以把输出结果和之前手动推算的结果进行对比,看看是不是一致。

除此之外,我们还可把最小二乘法的线性拟合结果和 sklearn 库中的 LinearRegression().fit() 函数的结果相比较,具体的代码和注释也放在了这里。

import pandas as pd
from sklearn.linear_model import LinearRegression

df = pd.read_csv("/Users/shenhuang/Data/test.csv")
df_features = df.drop(['y'], axis=1)     #Dataframe中除了最后一列,其余列都是特征,或者说自变量
df_targets = df['y']                     #Dataframe最后一列是目标变量,或者说因变量

print(df_features, df_targets)
regression = LinearRegression().fit(df_features, df_targets)        #使用特征和目标数据,拟合线性回归模型
print(regression.score(df_features, df_targets))        #拟合程度的好坏
print(regression.intercept_)
print(regression.coef_)            #各个特征所对应的系数

其中,test.csv 文件的内容我列在了这里。

这样写是为了方便我们使用 pandas 读取 csv 文件并加载为 dataframe。

在最终的结果中,1.0 表示拟合程度非常好,而 -0.014545454545452863 表示一个截距,[0.94909091 1.41454545]表示系数 b1​ 和 b2​ 的值。这个结果和我们最小二乘法的结果有所差别,主要原因是 LinearRegression().fit() 默认考虑了有线性函数存在截距的情况。那么我们使用最小二乘法是不是也可以考虑有截距的情况呢?答案是肯定的,不过我们首先要略微修改一下方程组和矩阵 X。如果我们假设有截距存在,那么线性回归方程就要改写为:

其中,b0​ 表示截距,而我们这里的方程组用例就要改写为:

而矩阵 X 要改写为:

然后我们再执行下面这段代码。

from numpy import *

x = mat([[1,0,1],[1,1,-1],[1,2,8]])
y = mat([[1.4],[-0.48],[13.2]])

print("\n系数矩阵B:\n", (x.transpose().dot(x)).I.dot(x.transpose()).dot(y))

你就会得到:

 系数矩阵B:
     [[-0.01454545]
     [ 0.94909091]
     [ 1.41454545]]

这个结果和 LinearRegression().fit() 的结果就一致了。

需要注意的是,使用线性回归的时候,我们都有一个前提假设,那就是数据的自变量和因变量之间呈现线性关系。如果不是线性关系,那么使用线性模型来拟合的效果一定不好。比如,之前在解释欠拟合的时候,用过下面这个例子。

上面这张图的数据分布并没有表达线性关系,所以我们需要对原始的数据进行非线性的变换,或者是使用非线性的模型来拟合。

那么,我们如何判断一个数据集是不是能用线性模型表示呢?在线性回归中,我们可以使用决定系数 R2。这个统计指标使用了回归平方和与总平方和之比,是反映模型拟合度的重要指标。它的取值在 0 到 1 之间,越接近于 1 表示拟合的程度越好、数据分布越接近线性关系。随着自变量个数的增加,R2 将不断增大,因此我们还需要考虑方程所包含的自变量个数对 R2 的影响,这个时候可使用校正的决定系数 Rc2。所以,在使用各种科学计算库进行线性回归时,你需要关注 R2 或者 Rc2,来看看是不是一个好的线性拟合。在之前的代码实践中,我们提到的 regression.score 函数,其实就是返回了线性回归的 R2。

总结

今天我们使用了具体的案例来推导最小二乘法的计算过程,并用 Python 代码进行了验证。通过最近 3 节的讲解,相信你对线性方程组求精确解、求近似解、以及如何在线性回归中运用这些方法,有了更加深入的理解。

实际上,从广义上来说,最小二乘法不仅可以用于线性回归,还可以用于非线性的回归。其主要思想还是要确保误差ε最小,但是由于现在的函数是非线性的,所以不能使用求多元方程求解的办法来得到参数估计值,而需要采用迭代的优化算法来求解,比如梯度下降法、随机梯度下降法和牛顿法。

思考题

这里给出一个新的方程组,请通过最小二乘法推算出系数的近似解,并使用你熟悉的语言进行验证。



本文介绍了线性回归模型的基本原理和最小二乘法的实现过程。通过详细的数学推导和Python代码示例,读者可以快速了解如何使用最小二乘法来计算线性回归模型的系数矩阵,并与sklearn库中的线性回归结果进行对比。文章还提到了线性回归模型的前提假设,以及如何使用决定系数R2来判断数据集是否适合使用线性模型。此外,文章还涉及到最小二乘法在非线性回归中的应用,以及提出了一个思考题供读者练习。通过本文的阅读,读者可以深入理解最小二乘法在线性回归中的应用,以及其在非线性回归中的潜在价值。 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37756660/article/details/137672314

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法