9. 线性回归 Linear Regresion

回归是一种应用广泛的预测建模技术,这种技术的核心在于预测的结果是连续型变量。

决策树,随机森林,支持向量机的分类器等分类算法的预测标签是分类变量,多以{0,1}来表示,而无监督学习算法比如PCA,KMeans的目标根本不是求解出标签,注意加以区别。

只要一切基于特征预测连续型变量的需求,我们都使用回归技术。

既然线性回归是源于统计分析,我们就可以用不同的角度去理解它。从统计学的角度来看,我们对线性回归有许多要求,比如残差要满足正态分布,要排除共线性等等;然而从机器学习的角度来说,无论服从什么分布,无论是否存在共线性,只要模型效果好就行。

回归需求在现实中非常多,所以我们自然也有各种各样的回归类算法。最著名的就是我们的线性回归和逻辑回归, 从他们衍生出了岭回归,Lasso,弹性网,除此之外,还有众多分类算法改进后的回归,比如回归树,随机森林的回归,支持向量回归,贝叶斯回归等等。除此之外,我们还有各种鲁棒的回归:比如RANSAC,Theil-Sen估计,胡贝尔回归等等。考虑到回归问题在现实中的泛用性,回归家族可以说是非常繁荣昌盛,家大业大了。

我们要明白各个回归算法的优劣,明白如何衡量回归算法的效果,然后了解什么时间该选用什么回归。

 

这里只讲普通的线性回归 Linear Regresion怎么用。

 

做一次线性回归 步骤:

1.导入需要的模块和库

2.导入数据,探索数据

3.分训练集与测试集

4.建模

5. 探索建好的模型(即看这个模型的各种属性)

 

 

1.导入需要的模块和库

from sklearn.linear_model import LinearRegression as LR
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.datasets import fetch_california_housing as fch
# 加利福尼亚房屋价值数据集
import pandas as pd

2.导入数据,探索数据

housevalue=fch()
x=pd.DataFrame(housevalue.data)
x.shape

(20640, 8)
y=housevalue.target
y.shape

(20640,)
housevalue.feature_names

['MedInc',
 'HouseAge',
 'AveRooms',
 'AveBedrms',
 'Population',
 'AveOccup',
 'Latitude',
 'Longitude']
x

 

# 把列名替换成真正的属性名字
x.columns=housevalue.feature_names

其中
"""
MedInc:该街区住户的收入中位数 
HouseAge:该街区房屋使用年代的中位数 
AveRooms:该街区平均的房间数目 
AveBedrms:该街区平均的卧室数目 
Population:街区人口 
AveOccup:平均入住率 
Latitude:街区的纬度 
Longitude:街区的经度
"""

3.分训练集与测试集

Xtrain,Xtest,Ytrain,Ytest=train_test_split(x,y,test_size=0.3,random_state=420)
Xtrain
# 索引是乱的,因为是随机抽取组成的训练集

恢复索引:

for i in [Xtrain,Xtest]:
    i.index=range(i.shape[0])
Xtrain

4.建模

# 实例化+fit训练模型
reg=LR().fit(Xtrain,Ytrain)

# 调用predict接口,返回输入的测试集上的每个样本点的回归结果
yhat=reg.predict(Xtest)

# yhat为预测的结果。因为有8列,所以有8个预测值
yhat

 

5. 探索建好的模型(即看这个模型的各种属性)

线性回归有两个属性:coef_和intercept_

# coef_属性:coefficient,系数w
# 数字越大,越重要 

# yhat有8列,所以有8个系数
reg.coef_

# zip:能将两个结构相似的对象结合在一起
zip(Xtrain.columns,reg.coef_)
# 这样写是会报错的,这是一个惰性对象,要显示惰性对象有两种方式:1.tolist,2,[*]

# 正确写法:
[*zip(Xtrain.columns,reg.coef_)]

# intercept_属性:截距
reg.intercept_

-36.256893229204074

 

多元线性回归的模型评估指标(看效果好不好)

回归类与分类型算法的模型评估其实是相似的法则——找真实标签和预测值的差异。
只不过在分类型算法中,这个差异只有一种角度来评判,那就是是否预测到了正确的分类;而在我们的回归类算法中,我们有两种不同的角度来看待回归的效果:
    第一,我们是否预测到了正确的数值;
    第二,我们是否拟合到了足够的信息。 
这两种角度,分别对应着不同的模型评估指标。 

 

第一,我们是否预测到了正确的数值:

用均方误差MSE(mean squared error)来衡量我们的预测值和真实值的差异。

在sklearn当中,我们有两种方式调用这个评估指标:
一种是使用sklearn专用的模型评估模块metrics里的类mean_squared_error;
另一种是调用交叉验证的类cross_val_score 并使用里面的scoring参数来设置使用均方误差。

第一种:使用sklearn专用的模型评估模块metrics里的类mean_squared_error

from sklearn.metrics import mean_squared_error as MSE
MSE(yhat,Ytest)

0.5309012639324571


第二种:调用交叉验证的类cross_val_score 并使用里面的scoring参数来设置使用均方误差

cross_val_score(reg,x,y,cv=10,scoring="neg_mean_squared_error").mean()

-0.550952429695659

可见,第二种算出来的均方误差是负的。

 

线性回归的大坑一号:均方误差为负。

 

这是因为sklearn在计算模型评估指标的时候,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失(loss)。
在sklearn当中, 所有的损失都使用负数表示,因此均方误差也被显示为负数了。
真正的均方误差MSE的数值,其实就是 neg_mean_squared_error去掉负号的数字。

 

第二,我们是否拟合到了足够的信息:

对于回归类算法而言,只探索数据预测是否准确是不足够的。
除了数据本身的数值大小之外,我们还希望我们的模型能够捕捉到数据的”规律“,比如数据的分布规律,单调性等等,而是否捕获了这些信息并无法使用MSE来衡量。

在我们学习降维算法PCA的时候,我们提到我们使用方差来衡量数据上的信息量。如果方差越大,代表数据上的信息量越多,而这个信息量不仅包括了数值的大小,还包括了我们希望模型捕捉的那些规律。

为了衡量模型对数据上的信息量的捕捉,我们定义了R^2和可解释性方差分数EVS(explained_variance_score)。

两者都衡量 1 - 我们的模型没有捕获到的信息量占真实标签中所带的信息量的比例,所以,两者都是越接近1越好。

R^2我们可以使用三种方式来调用:
第一种是直接从metrics中导入r2_score,输入预测值和真实值后打分;
第二种是直接从线性回归LinearRegression的接口score来进行调用;
第三种是在交叉验证中,输入"r2"来调用。

EVS有两种调用方法:
第一种是从metrics中导入;
第二种是在交叉验证中输入”explained_variance“来调用。

 

调用R^2:

# 第一种 直接从metrics中导入r2_score:
from sklearn.metrics import r2_score
r2_score(yhat,Ytest)

0.3380653761555984

# 第二种 是直接从线性回归LinearRegression的接口score来进行调用:
r2=reg.score(Xtest,Ytest)
r2

0.6043668160178817

# 第三种 在交叉验证中,输入"r2"来调用
cross_val_score(reg,x,y,cv=10,scoring="r2").mean()

0.5110068610524556

为什么不同方式调用的R^2不同?

 

线性回归的大坑二号:相同的评估指标不同的结果。

 

答:因为在第一种方式(直接从metrics中导入r2_score)中,函数规定真实值在前,预测值在后,参数写反了。第三种我不知道。。。

# 更正后的第一种 直接从metrics中导入r2_score:
from sklearn.metrics import r2_score
r2_score(Ytest,yhat)

0.6043668160178817

# 第一种 抑或者可以自己制定参数,就不必在意顺序了:
r2_score(y_true=Ytest,y_pred=yhat)

0.6043668160178817

 

调用EVS:

# 第一种 从metrics中导入:
from sklearn.metrics import explained_variance_score as EVS
EVS(Ytest,yhat)

0.60461026738544

# 第二种 在交叉验证中输入”explained_variance“来调用:

cross_val_score(reg,x,y,cv=10,scoring="explained_variance").mean()

0.5384986901370838

我们观察到,虽然我们在加利福尼亚房子价值数据集上的MSE相当小,但我们的R^2却不高,这证明我们的模型比较好地拟合了数据的数值,却没有能正确拟合数据的分布。

让我们与绘图来看看,究竟是不是这样一回事。

我们可以绘制一张图上的两条曲线,一条曲线是我们的真实标签Ytest,另一条曲线是我们的预测结果yhat,两条曲线的交叠越多,我们的模型拟合就越好:

import matplotlib.pyplot as plt

# 让Ytest从小到大排序
sorted(Ytest)

plt.plot(range(len(Ytest)),sorted(Ytest),c="black",label="Data")
# plot(x轴=索引,y轴=数值,颜色,标签)

plt.plot(range(len(yhat)),sorted(yhat),c="red",label="Predict")
plt.legend()
plt.show()

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

 

注意:

注意到,其实EVS和R^2是异曲同工的,两者都是衡量 1 - 没有捕获到的信息占总信息的比例,EVS和难道不应该相等吗? 

但从我们的结果来看,两者虽然相似,但却并不完全相等,这中间的差值究竟是什么呢? 和EVS有什么不同?

 

线性回归的三号大坑:负的R^2。

 

我们的R^2显示为负的时候,这证明我们的模型对我们的数据的拟合非常糟糕,模型完全不能使用。 所以,一个负的R^2是合理的。

现实应用中,如果你发现你的线性回归模型出现了负的,不代表你就要接受他,首先检查你的建模过程和数据处理过程是否正确,也许你已经伤害了数据本身,也许你的建模过程是存在bug的。如果你检查了所有的代码,也确定了你的预处理没有问题,但你的 也还是负的,那这就证明,线性回归模型不适合你的数据,试试看其他的算法吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值