前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【机器学习笔记】:大话线性回归(一)

【机器学习笔记】:大话线性回归(一)

作者头像
Python数据科学
发布于 2018-12-05 10:27:55
发布于 2018-12-05 10:27:55
1.4K00
代码可运行
举报
文章被收录于专栏:Python数据科学Python数据科学
运行总次数:0
代码可运行

作者 | xiaoyu

知乎 | https://zhuanlan.zhihu.com/pypcfx

介绍 | 一个半路转行的数据挖掘工程师

线性回归作为监督学习中经典的回归模型之一,是初学者入门非常好的开始。宏观上考虑理解性的概念,我想我们在初中可能就接触过,y=ax,x为自变量,y为因变量,a为系数也是斜率。如果我们知道了a系数,那么给我一个x,我就能得到一个y,由此可以很好地为未知的x值预测相应的y值。这很符合我们正常逻辑,不难理解。那统计学中的线性回归是如何解释的呢?

对于统计模型线性回归,我想从以下六个方面来展开,并分两篇文章进行详细解读:

  • 线性回归模型定义
  • 线性回归的损失函数
  • 线性回归参数估计
  • 线性回归预测
  • 线性回归拟合优度
  • 线性回归假设检验
  • 线性回归诊断

▌线性回归模型定义

线性回归按变量数量的多少可以分为:一元线性回归(简单线性回归)多元线性回归

一元线性回归,也就是有一个自变量,其模型可以表示如下:

公式中参数解释如下:

x:自变量

y:因变量

β 0:截距

β 1:变量回归系数

ϵ:误差项的随机变量1

这些参数中,(β 0+β 1x)反映了由于x的变化而引起的y的线性变化;ϵ反映了除了x和y之间的线性关系之外的随机因素对y的影响,是不能由x和y之间的线性关系所解释的变异性。可以这么来理解ϵ:我们对y的预测是不可能达到与真实值完全一样的,这个真实值只有上帝知道,因此必然会产生误差,我们就用ϵ来表示这个无法预测的误差。

同样的,多元线性回归模型的表示如下:

我们通过引入了ϵ可以让模型达到完美状态,也就是理论的回归模型。但是我们要如何定义这个无法预测的误差项呢?为此,伟人们提出了一些假设条件

在统计学中,高斯-马尔可夫定理陈述的是:在误差零均值,同方差,且互不相关的线性回归模型中,回归系数的最佳无偏线性估计(BLUE)就是最小方差估计。

总结一下,有如下几个主要的假设条件:

(1)误差项ϵ是一个期望为0的随机变量,即E(ϵ)=0

(2)对于自变量的所有值,ϵ的方差σ^2 都相同

(3)误差项ϵ是一个服从正态分布的随机变量,且相互独立,即ϵ~N(0,σ^2 )

ϵ正态性意味着对于给定的自变量,因变量y也是一个服从正态分布的随机变量。根据回归模型的假设,有如下多元回归方程

▌线性回归的损失函数

从样本数据考虑,如果想让我们预测值尽量准确,那么我们就必须让真实值与预测值的差值最小,即让误差平方和ϵ最小,用公式来表达即:

用平方而没用误差绝对值是因为:平方对于后续求导比较方便。

虽然我们得到了损失函数,但是如果从统计理论的角度出发来推导损失函数,我认为更有说服力,也能更好地理解线性回归模型,以及为什么开始要提出那些假设条件。

根据上面假设条件:ϵ 服从均值为0,方差为σ的正态分布,且独立,因此随机变量ϵ 的概率密度函数(正态分布的概率密度函数)为:

我们把前面的多元线性回归模型简单地变换一下,如下:

然后将得到的ϵ公式带入上面概率密度函数:

有了概率密度函数,我们自然会想到用最大似然估计推导损失函数:

然后我们将似然函数取对数,这样可以将概率密度的乘法转换为加法:

再然后我们对似然函数取最大值,即最大化似然函数:

这样我们就从统计理论的角度得到了我们要找的损失函数,与我们最小化误差平方和得到的结果是一样的,也从侧面证实了前面提出假设的正确性。因此,多元线性回归模型的损失函数为:

公式里的1/2对损失函数没有影响,只是为了能抵消求导后的乘数2。

▌线性回归参数估计

损失函数只是一种策略,有了策略我们还要用适合的算法进行求解。在线性回归模型中,求解损失函数就是求与自变量相对应的各个回归系数和截距。有了这些参数,我们才能实现模型的预测(输入x,给出y)。

对于误差平方和损失函数的求解方法有很多,典型的如最小二乘法,梯度下降等。下面我们分别用这两种方法来进行求解。

最小二乘法

最小二乘法可以将误差方程转化为有确定解的代数方程组(其方程式数目正好等于未知数的个数),从而可求解出这些未知参数。这个有确定解的代数方程组称为最小二乘法估计的正规方程

我们将代数方程组用矩阵来代替可以简化推导过程,以及代码实现。

这里会涉及到矩阵求导的用法,详细介绍请看下面wiki的参考链接:

https://en.wikipedia.org/wiki/Matrix_calculus#Scalar-by-vector_identities

我们令上面得到的公式等于0,即可得到最终的求解:

Python中对于矩阵的各种操作可以通过Numpy库的一些方法来实现,非常方便。但在这个代码实现中需要注意:X矩阵不能为奇异矩阵,否则是无法求解矩阵的逆的。下面是手撸最小二乘法的代码实现部分。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def standRegres(xArr,yArr):
    """
    函数说明:计算回归系数w
    Parameters:
        xArr - x数据集
        yArr - y数据集
    Returns:
        ws - 回归系数
    """
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    #根据文中推导的公示计算回归系数
    xTx = xMat.T * xMat 
    if np.linalg.det(xTx) == 0.0:
        print("矩阵为奇异矩阵,不能求逆")
        return
    ws = xTx.I * (xMat.T*yMat)
    return ws

梯度下降法

梯度下降是另一种常用的方法,可以用来求解凸优化问题。它的原理有别于最小二乘法,它是通过一步步迭代(与最小二乘法的区别在后面介绍)求解,不断逼近正确结果,直到与真实值之差小于一个阈值,从而得到最小化损失函数的模型参数值的。它的公式如下:

对于损失函数的梯度(即求偏导的过程),上面在最小二乘法部分已经给出推导过程和结果。不同的是,我们不会将公式等于0来求极值,而是带入上面梯度下面公式来迭代完成求解,以下是梯度下降矩阵形式的最终求解结果。

最小二乘法 vs 梯度下降法

通过上面推导,我们不难看出,二者都对损失函数的回归系数进行了求偏导,并且所得到的推导结果是相同的,那么究竟哪里不同呢?

如果仔细观察,可以观察到:最小二乘法通过使推导结果等于0,从而直接求得极值,而梯度下降则是将推导结果带入迭代公式中,一步一步地得到最终结果。简单地说,最小二乘法是一步到位的,而梯度下降是一步步进行的。

因而通过以上的异同点,总结如下

最小二乘法:

  • 得到的是全局最优解,因为一步到位,直接求极值,因而步骤简单
  • 线性回归的模型假设,这是最小二乘方法的优越性前提,否则不能推出最小二乘是最佳(即方差最小)的无偏估计

梯度下降法:

  • 得到的是局部最优解,因为是一步步迭代的,而非直接求得极值
  • 既可以用于线性模型,也可以用于非线性模型,没有特殊的限制和假设条件

▌线性回归预测

上面我们已经手撸了最小二乘法和梯度下降法求解误差平方和损失函数的过程,即我们通过以上算法已经得到了我们想要的参数值。当然,我们也可以使用statsmodels或者sklearn库中已经被封装好了的模型来进行预测。不过,为了更好的了解模型,优化算法,而不仅仅是做一个调包侠,我们最好对每种算法都自己实现一遍。

为了更好的说明整个建模到预测的过程,我们通过一个例子来详细说明。对于一个数据集,我们通过自己手撸的最小二乘法来建模,求解参数然后进行预测。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class LeastSquared(object):
    def __init__(self):
        self.xArr = []
        self.yArr = []
        self.params = []
        self.y_predict = []

    def fit(self,xArr,yArr):
        self.xArr = xArr
        self.yArr = yArr
        xMat = np.mat(xArr)
        yMat = np.mat(yArr).T
        xTx = xMat.T*xMat
        if np.linalg.det(xTx) == 0.0:
            print('矩阵为奇异矩阵')
        params = xTx.I*(xMat.T*yMat)
        self.params = params

    def predict(self,x_new):
        y_predict = x_new*self.params
        self.y_predict = y_predict
        return y_predict

可以看到这是一个简单的二维平面,蓝色代表一个变量X和因变量Y的散点图,红色是我们通过最小二乘法拟合出来的直线。如果是多自变量,那么拟合结果将是一个平面,或者超平面。使用这个模型,我们就能对未知的X值进行预测。

然后,我们在x的范围内再取10个随机数,并进行预测感受一下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 生成最小二乘法类
xArr, yArr = loadDataSet('ex0.txt')
ls = LeastSquared()
ls.fit(xArr,yArr) #训练模型
y_predict = ls.predict(xArr) #预测模型

# 在x范围内,随机生成10个新的x值
x_min = np.min(np.array(xArr)[:,1])
x_max = np.max(np.array(xArr)[:,1])
x_random = np.random.uniform(x_min,x_max,[10,1])

x_new = np.c_[np.ones(10),x_random.flatten()]
y_new = ls.predict(x_new)
y_new = y_new.flatten().tolist()[0]
x_new = x_random.flatten().tolist()

# 可视化
n = len(xArr)                                                      
xcord = [];ycord = [];y_hat = []
for i in range(n): 
    xcord.append(xArr[i][1])
    ycord.append(yArr[i])                    
    y_hat.append(y_predict.tolist()[i][0])
fig = plt.figure()
#添加subplot
ax = fig.add_subplot(111)                                            
#绘制样本点
ax.plot(xcord, y_hat, c = 'red')
ax.scatter(xcord, ycord, s = 20, c = 'blue',alpha = .5)                
ax.scatter(x_new,y_new, s=150, c='r', alpha = 0.8)
#绘制title
plt.title('LeastSquareMethod')                                                
plt.xlabel('X')
plt.show()

这时我们看到,生成的10个随机数都在我们的拟合直线上,对应的y值就是我们的预测值。同样的,我们也手撸了梯度下降算法进行的求解过程,二者得到的结果参数几乎相等。二者可视化效果如下所示(可以看到两个拟合直线是重合的,红色和绿色):

代码语言:javascript
代码运行次数:0
运行
复制

二者所得参数对比如下,其中梯度下降迭代了500次,可以看到参数结果是几乎一样的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#最小二乘法
ls.params
>>matrix([[3.00774324],
         [1.69532264]])

#梯度下降法,迭代500次
gd.params
>>matrix([[3.00758726],
         [1.69562035]])

▌总结

本篇主要介绍了线性回归的前几个部分:模型定义假设,模型参数估计,模型预测。但是预测完模型之后,我们并不知道结果时好时坏,并且我们也不知道开始的假设是否成立,这些内容涉及模型拟合优度,模型假设检验,和模型诊断,将在下一篇进行介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python数据科学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
CRC校验算法详解、C语言实现
CRC(Cyclic Redundancy Check)校验算法是一种广泛应用于数据通信和存储系统中的错误检测方法,主要用于检测数据在传输过程中是否发生了改变。CRC算法通过计算一个固定长度的校验码,将该校验码附加到原始数据的末尾,接收方在接收到数据后重新计算校验码并与接收到的校验码进行比较,以此判断数据在传输过程中是否发生了错误。这种校验机制不仅能够检测出大多数类型的错误,而且计算效率高,占用资源少,因此在各种通信协议、文件系统、磁盘驱动器和网络协议中都有广泛应用。
DS小龙哥
2025/05/27
1130
CRC校验算法详解、C语言实现
【linux命令讲解大全】005.文件完整性校验与压缩包比较的常用命令:cksum、bzcmp和cmp
cksum命令是用来检查文件的CRC是否正确,以确保文件在从一个系统传输到另一个系统的过程中没有损坏。这种方法要求在源系统中计算出校验和,在目标系统中再次计算出校验和,然后比较这两个数字。如果校验和相等,则认为文件传输正确。
全栈若城
2024/03/02
6100
【linux命令讲解大全】182.常用的Linux命令详解:renice、cksum和lsusb
renice 命令可以修改正在运行的进程的调度优先级。预设是以程序识别码指定程序调整其优先权,您亦可以指定程序群组或用户名称调整优先权等级,并修改所有隶属于该程序群组或用户的程序的优先权。只有系统管理者可以改变其他用户程序的优先权,也仅有系统管理者可以设置负数等级。
全栈若城
2024/03/02
1590
Linux 命令(234)—— cksum 命令
CRC 校验码确保文件从一个系统传输到另一个系统的过程中不被损坏。这种方法要求校验和在源系统中被计算出来,在目的系统中又被计算一次,两个数字进行比较,如果校验和相等,则该文件被认为是正确传输了。
恋喵大鲤鱼
2022/12/25
1K0
Linux 文件管理命令语法、参数、实例全汇总(一)
命令:cat cat 命令用于连接文件并打印到标准输出设备上。 使用权限 所有使用者 语法格式 cat [-AbeEnstTuv] [--help] [--version] fileName 参数说明 -n 或 --number:由 1 开始对所有输出的行数编号。 -b 或 --number-nonblank:和 -n 相似,只不过对于空白行不编号。 -s 或 --squeeze-blank:当遇到有连续两行以上的空白行,就代换为一行的空白行。 -v 或 --show-nonprinting:使用 ^ 和
小小科
2018/05/04
1.4K0
汇总:Linux文件管理的50个命令
文 | 糖豆 图 | 来源网络 糖豆贴心提醒,本文阅读时间6分钟,文末有秘密! Linux cat命令 cat 命令用于连接文件并打印到标准输出设备上。 Linux chattr命令 Linux chattr命令用于改变文件属性。 Linux chgrp命令 Linux chgrp命令用于变更文件或目录的所属群组。 在UNIX系统家族里,文件或目录权限的掌控以拥有者及所属群组来管理。您可以使用chgrp指令去变更文件与目录的所属群组,设置方式采用群组名称或群组识别码皆可。 Linux chmo
小小科
2018/05/04
1.7K0
汇总:Linux文件管理的50个命令
15.linux 文件管理命令:rmdir删除目录 \ chattr改变文件的属性 \ split分割文件
linux 文件管理命令:rmdir删除目录 \ chattr改变文件的属性 \ cksum文件的 CRC 校验 \ cmp比较文件差异 \ split分割文件
度假的小鱼
2025/01/04
1340
15.linux 文件管理命令:rmdir删除目录 \ chattr改变文件的属性   \ split分割文件
Linux 命令(233)—— sum 命令
文章目录 1.命令简介 2.命令格式 3.选项说明 4.常用示例 参考文献 1.命令简介 sum 命令用于计算并显示指定文件的校验和与文件所占用的磁盘块数。 2.命令格式 sum [OPTION]... [FILE]... 如果没有 FILE,或者 FILE 为 -,则读取标准输入。 3.选项说明 -r 使用 BSD 加和算法(默认),以1KB 为一个块。 -s, --sysv 使用 System V 加和算法,以51双字节为一个块 --help 显示帮助信息并退出。 --version 显示版本
恋喵大鲤鱼
2022/12/25
4520
Linux好用的管道命令
1)在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
WHYBIGDATA
2023/01/31
9.6K0
Linux好用的管道命令
【linux命令讲解大全】183.Linux 常用工具之 md5sum 和 su
md5sum 命令采用 MD5 报文摘要算法(128 位)来计算和检查文件的校验和。一般来说,安装了 Linux 后,就会拥有 md5sum 这个工具,可以直接在命令行终端中使用。
全栈若城
2024/03/02
2030
Kali Linux 命令大全
您可以使用 arch 命令了解计算机体系结构。Arch 命令打印诸如“i386、i486、i586、alpha、arm、m68k、mips、sparc、x86_64 等”。
逍遥子大表哥
2021/12/22
12.8K0
Kali Linux 命令大全
Linux grep命令详解
grep指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为"-",则grep指令会从标准输入设备读取数据。
不吃西红柿
2022/07/29
6.1K0
【linux命令讲解大全】043.详解Linux中cpio命令的用法及常见选项
cpio 命令主要是用来建立或者还原备份档的工具程序,cpio 命令可以复制文件到归档包中,或者从归档包中复制文件。
全栈若城
2024/03/02
4480
MD5、SHA1、CRC32值是干什么的?
Hash,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
JavaEdge
2021/10/18
1.6K0
一文讲透CRC校验码-附赠C语言实例
CRC(Cyclic Redundancy Checksum)是一种纠错技术,代表循环冗余校验和。
C语言与CPP编程
2021/07/27
11K1
一文讲透CRC校验码-附赠C语言实例
20.linux 文件管理命令【md5sum】MD5 函数值计算和检查【awk】模式匹配语言
linux 文件管理命令:【md5sum】MD5 函数值计算和检查【awk】模式匹配语言
度假的小鱼
2025/01/10
2380
20.linux 文件管理命令【md5sum】MD5 函数值计算和检查【awk】模式匹配语言
Linux工作/面试常用命令大全详解
管道符“|”将两个命令隔开,左边命令的输出作为右边命令的输入。连续使用管道意味着第一个命令的输出会作为 第二个命令的输入,第二个命令的输出又会作为第三个命令的输入,依此类推
JavaEdge
2021/02/23
1.6K0
Linux工作/面试常用命令大全详解
Solidigm:基于PI块减少静默数据损坏
静默数据损坏 (SDC) 的原因、可能发生的地方和时间。它强调了 SDC 可能发生在数据生命周期的任何阶段,包括正常操作条件和各种数据处理过程中。
数据存储前沿技术
2025/02/11
1640
Solidigm:基于PI块减少静默数据损坏
CRC校验怎么算?
据说刚过去的高考数学很难,小编当年上学时挺喜欢数学的,最近特意复习了一下CRC校验的计算过程。
用户2366192
2022/12/06
3.6K0
CRC校验怎么算?
使用fold命令限制文件列宽
fold命令会从指定的文件里读取内容,将超过限定列宽的列加入增列字符后,输出到标准输出设备。若不指定任何文件名称,或是所给予的文件名为”-“,则fold指令会从标准输入设备读取数据。
用户1685462
2021/09/08
7000
推荐阅读
相关推荐
CRC校验算法详解、C语言实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验