【skLearn 回归模型】线性回归 ---- Linear Regression



一、线性回归简介

  概念

  • 回归是一种应用广泛的预测建模技术,这种技术的核心在于预测的结果是连续型变量。回归(Regression)是监督学习的另一个重要问题,用于预测输入变量(自变量)和输出变量(因变量)之间的关系,特别是当输入变量的值发生变化时,输出变量的值随之发生的变化,回归模型正是表示从输入变量到输出变量之间映射的函数回归问题的学习等价于函数拟合:选择一条函数曲线,使其很好地拟合已知数据且很好地预测未知数据。在统计学中,线性回归(Linear Regression)是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析,这种函数是一个或多个被称为回归系数的模型参数的线性组合 。只有一个自变量的情况称为简单回归,大于一个自变量情况的称为多元回归。

  • 回归算法源于统计学理论,它可能是机器学习算法中产生最早的算法之一,其在现实的应用非常广泛,包括使用其他经济指标预测股票市场指数,根据喷射流的特征预测区域内的降水量,根据公司的广告花费预测总销售额,或者根据有机物质中残留的碳-14的量来估计化石的年龄等等,只要一切基于特征预测连续型变量的需求,我们都使用回归技术。

  • 既然线性回归是源于统计分析,是结合机器学习与统计学的重要算法。通常来说,我们认为统计学注重先验,要将一切准备工作就绪后才可以开始建模等后续步骤;而机器学习看重结果,因此机器学习中不会提前为线性回归排除共线性等可能会影响模型的因素,反而会先建立模型以查看效果。模型确立之后,如果效果不好,我们就根据统计学的指导来排除可能影响模型的因素。

返回顶部


  常见回归算法

回归需求在现实中非常多,所以我们自然也有各种各样的回归类算法。

  • 最著名的就是我们的 线性回归逻辑回归
  • 从他们衍生出了岭回归Lasso弹性网
  • 除此之外,还有众多分类算法改进后的回归,比如回归树随机森林的回归支持向量回归贝叶斯回归等等
  • 除此之外,我们还有各种鲁棒的回归:比如 RANSACTheil--sen估计胡贝尔回归等等。

考虑到回归问题在现实中的泛用性,回归家族可以说是非常繁荣昌盛,家大业大了。

理解线性回归可以有两种角度:矩阵的角度代数的角度。几乎所有机器学习的教材都是从代数的角度来理解线性回归的,类似于在逻辑回归和支持向量机中,将求解参数的问题转化为一个带条件的最优化问题,然后使用三维图像让大家理解求极值的过程。

返回顶部


二、多元线性回归 Linear Regression


线性回归就是指一个样本有多个特征的线性回归问题

例: y = ax + b
        y --> 标签
		x --> 特征
  • 但是在现实生活中,不可能全是一元问题,也就是变量不是一个的情况。多元就是对多个特征进行求解的线性回归问题。

• 线性回归基本原理

在这里插入图片描述

返回顶部


• 线性回归损失函数

在这里插入图片描述

返回顶部


• 最小二乘法求解多元线性回归的参数

基本原理

  • 最小二乘法就是通过最小化真实值和预测值之间的RSS来求解参数的方法
    求解极值的第一步往往是求解一阶导数并让一阶导数等于0,最小二乘法也是如此,在现有的残差平方和RSS上对参数向量w求导。

返回顶部


基本步骤 ---- 矩阵

在这里插入图片描述

到了这里,我们希望能够将w留在等式的左边,其他与特征矩阵有关的部分都放到等式的右边,如此就可以求出w的最优解了。这个功能非常容易实现,只需要我们左乘X^TX的逆矩阵就可以。在这里,逆矩阵存在的充分必要条件是特征矩阵不存在多重共线性

假设矩阵的逆是存在的,此时我们的w就是我们参数的最优解。求解出这个参数向量,我们就解出了我们的Xw,也就能够计算出我们的预测值了。

除了多元线性回归的推导之外,在这里还需要提到一些在上面的推导过程中不曾被体现出来的问题。在统计学中,使用最小二乘法来求解线性回归的方法是一种无偏估计的方法,这种无偏估计要求因变量,也就是标签的分布必须服从正态分布。这是说,我们的y必须经由正太化处理。在机器学习中,我们会先考虑模型的效果,如果模型效果不好,那我们可能考虑改变因变量的分布

返回顶部


• linear model.LinearRegression 类

class sklearn.linear_model.LinearRegression(*, fit_intercept=True, normalize=False, copy_X=True, n_jobs=None,
                                            positive=False)

在这里插入图片描述

  • 通过基础模型的了解可以看出,线性回归模型需要设定的参数并没有大量的数据参数,并且也没有必须设定的参数。这就说明线性回归模型的生成很大程度上取决于原始数据集本身

详细参数内容参见官方文档:https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression

返回顶部


简单案例

① 导库
from sklearn.linear_model import LinearRegression as LR  # 线性回归
from sklearn.model_selection import train_test_split     # 划分训练测试集
from sklearn.datasets import fetch_california_housing as fch  # 加利福尼亚房屋价格数据集
import pandas as pd
② 导入数据集并进行探索
# 1.导入数据集
# 1.1 实例化 --- 得到的是一个类似字典的数据集
house_value = fch()
keys = house_value.keys() # dict_keys(['data', 'target', 'feature_names', 'DESCR'])
# 1.2 通过data获取对应的数据集
x = pd.DataFrame(house_value.data)
print(x.shape) # (20640, 8)
# 1.3 通过target获取对应的标签 --- yhat
y = house_value.target
print(y.max()) # 5.00001
print(y.min()) # 0.14999
print(y.shape) # (20640,)
# 1.4 通过feature_names获取特证名称
features = house_value.feature_names
# ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
'''
MedInc:该街区住户的收入中位数
HouseAge:该街区房屋使用年代的中位数
AveRooms:该街区平均的房间数目
AveBedrms:该街区平均的卧室数目
Population:街区人口
AveOccup:平均入住率
Latitude:街区的纬度
Longitude:街区的经度
'''
# 1.5 将特征名称对应到x数据集
x.columns = features
③ 划分训练集、测试集
  • 将数据集进行拆分,训练集用于模型训练,得到一个大概的模型;测试集用于测试,利用训练集训练出的模型对测试集进行模型预测。
# 2.划分训练集和测试集
xtrain,xtest,ytrain,ytest = train_test_split(x,y,test_size=0.3,random_state=420)
# 2.1 恢复抽取数据的索引
for i in [xtrain,xtest]:
    i.index = range(i.shape[0])

在这里插入图片描述

④ 建模、预测
  • 首先,利用一组训练集xtrain(真实训练数据)ytrain(真实训练标签)进行模型训练,得到一个回归模型reg
  • 通过模型对测试集xtest进行回归预测,得出预测标签yhat,后期与真实标签ytest进行比对
# 3.建模
reg = LR().fit(xtrain,ytrain)
yhat = reg.predict(xtest)
print(yhat.min()) # -0.6528439725035966
print(yhat.max()) # 7.146198214270875
⑤ 查看模型拟合函数基本信息
  • reg.coef_ 查看回归系数
  • reg.intercept_ 查看截距
# 4.查看拟合函数
# 4.1 查看w,回归系数向量
coef = reg.coef_
# [ 4.37358931e-01  1.02112683e-02 -1.07807216e-01  6.26433828e-01,  5.21612535e-07 -3.34850965e-03 -4.13095938e-01 -4.26210954e-01]
# 4.1.1 将回归系数与特征对应
compare = [*zip(xtrain.columns,reg.coef_)]
# 4.2 获取截距
intercept = reg.intercept_ # -36.25689322920386

返回顶部


三、评估指标

评估指标,回归类与分类型算法的模型评估其实是相似的法则 ---- 找真实标签和预测值的差异。

  • 在分类算法中,这个差异只有一种角度来评判,那就是是否预测到了正确的分类,其结果只存在0(分类错误)或100(分类正确),并不存在中间过程的衡量标准

  • 在回归类算法中,我从两种不同的角度来看待回归的效果:

    • 第一,我们是否预测到了正确的数值
    • 第二,我们是否拟合到了足够的信息

    这两种角度,分别对应着不同的模型评估指标

• 是否预测了正确的值

1.均方误差(MSE)

回忆一下我们的RSS残差平方和,它的本质是我们的预测值与真实值之间的差异,也就是从第一种角度来评估我们回归的效力,所以RSS既是我们的损失函数,也是我们回归类模型的模型评估指标之一。但是,RSS有着致命的缺点:它是一个无界的和,可以无限地大。我们只知道,我们想要求解最小的RSS,从RSS的公式来看,它不能为负,所以RSS越接近0越好,但我们没有一个概念,究竟多小才算好,多接近0才算好?为了应对这种状况,sklearn中使用RSS的变体,均方误差MSE(mean squared error)来衡量我们的预测值和真实值的差异:
在这里插入图片描述

  • 均方误差,本质是在RSS的基础上除以了样本总量,得到了每个样本量上的平均误差。有了平均误差,我们就可以将每个样本的平均误差和我们的标签的取值范围在一起比较,以此获得一个较为可靠的评估依据。在 sklearn当中,我们有两种方式调用这个评估指标,一种是使用 sklearn专用的模型评估模块里的类mean_squared_error,另一种是调用交叉验证的类 cross_val_scoresco并使用里面的参数来设置使用均方误差。
  • 拿本案例来说,真实的标签范围约在[0,5];但是经过预测出来的却约在[0,7],就最大而言,误差率达到了40%,可以说模型较差
# 5.1 均方误差
from sklearn.metrics import mean_squared_error as MSE
mse = MSE(yhat,ytest) # 0.5309012639324571
# 查看真实
print(ytest.mean()) # 2.0819292877906976

通过均方误差计算,得出预测标签平均误差达到0.5,而真实标签的平均值为2左右,也就是每个预测标签差了近1/4。

返回顶部


2.交叉验证

参见大佬博文:机器学习 | 交叉验证

def cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None,
                    n_jobs=None, verbose=0, fit_params=None,
                    pre_dispatch='2*n_jobs', error_score=np.nan):
estimator:估计方法对象(分类器)
X:数据特征(Features)
y:数据标签(Labels)
soring:调用方法(包括accuracy和mean_squared_error等等)
cv:几折交叉验证
n_jobs:同时工作的cpu个数(-1代表全部)
# 5.2交叉验证
cross = cross_val_score(reg,x,y,cv=10,scoring="neg_mean_squared_error")
# [-0.48922052 -0.43335865 -0.8864377  -0.39091641 -0.7479731  -0.52980278, -0.28798456 -0.77326441 -0.64305557 -0.3275106 ]
print(cross.mean()) # -0.550952429695658
  • 注意:scoring=“neg_mean_squared_error”
    在这里插入图片描述

在这里插入图片描述

参见大佬博文:通俗聊聊损失函数中的均方误差以及平方误差

返回顶部


• 是否拟合了足够的信息


在这里插入图片描述

来看这张图,其中红色线是我们的真实标签,而蓝色线是我们的拟合模型。这是一种比较极端,但的确可能发生的情况。这张图像上,前半部分的拟合非常成功,看上去我们的真实标签和我们的预测结果几乎重合,但后半部分的拟合却非常糟糕,模型向着与真实标签完全相反的方向去了。对于这样的一个拟合模型,如果我们使用MSE来对它进行判断,它的MSE会很小,因为大部分样体其实都被完美拟合了,少数样本的真实值和预测值的巨大差异在被均分到每个样本上后,MSE就会很小。但这样的拟合结果必然不是一个好结果,因为一旦我的新样本是处于拟合曲线的后半段的,我的预测结果必然会有巨大的偏差,而这不是我们希望看到的。所以,我们希望找到新的指标,除了判断预测的数值是否正确之外,还能够判断我们的模型是否拟合了足够多的、数值之外的信息。


1.R2

在这里插入图片描述

# 方式一
from sklearn.metrics import r2_score
r_score = r2_score(y_true=ytest,y_pred=yhat) # 0.6043668160178817
# 方式二
score = reg.score(xtest,ytest) # 0.6043668160178817
# 方式三
cross_score = cross_val_score(reg,x,y,cv=10,scoring="r2").mean() # 0.5110068610524564

我们观察到,我们在加利福尼亚房屋价值数据集上的MSE其实不是一个很大的数(0.5),但我们的R2不高,这证明我们的模型比较好地拟合了一部分数据的数值,却没有能正确拟合数据的分布。下面绘图来看看,究竟是不是这样一回事。我们可以绘制一张图上的两条曲线,一条曲线是我们的真实标签 ytest,另一条曲线是我们的预测结果yhat,两条曲线的交叠越多,我们的模型拟合就越好。


绘图
# 绘图
from matplotlib import pyplot as plt
sorted(ytest)

plt.plot(range(len(ytest)),sorted(ytest),c='black',label='Data')
plt.plot(range(len(yhat)),sorted(yhat),c='red',label='Predict')
plt.legend()
plt.show()

在这里插入图片描述
可见,虽然我们的大部分数据被拟合得比较好,但是图像的开头和结尾处却有着较大的拟合误差。如果我们在图像右侧分布着更多的数据,我们的模型就会越来越偏离我们真正的标签。这种结果类似于我们前面提到的,虽然在有限的数据集上将数值预测正确了,但却没有正确拟合数据的分布,如果有更多的数据进入我们的模型,那数据标签被预测错误的可能性是非常大的。

返回顶部


补充 R2 出现负数情况
# 特例
import numpy as np

rng = np.random.RandomState(42)
X = rng.randn(100,80)
Y = rng.randn(100)
cross_val_sco = cross_val_score(LR(),X,Y,cv=5,scoring='r2')
# [-179.12952605   -5.692624    -15.61747513  -78.68042858  -59.5311006 ]

在这里插入图片描述
在这里插入图片描述
返回顶部


评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑着蜗牛ひ追导弹'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值