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

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签