线性回归+回归算法的评价指标
- 回归问题的判定
- 目标值是连续性的值,而分类问题的目标值是离散型的值。
- 回归处理的问题为预测:
- 预测房价
- 销售额的预测
- 设定贷款额度
- 总结:上述案例中,可以根据事物的相关特征预测出对应的结果值
- 线性回归在生活中的映射(现实生活中就有线性回归):生活案例【预测学生的期末成绩】:
- 期末成绩的制定:0.7*考试成绩+0.3平时成绩,则该例子中,特征值为考试成绩和平时成绩,目标值为总成绩。
- 回归算法预测出来的结果其实就是经过相关的算法计算出来的结果值!
- 每一个特征需要有一个权重的占比,这个权重的占比明确后,则就可以得到最终的计算结果,也就是获取了最终预测的结果了。
- 那么这个特征对应的权重如何获取或者如何制定呢?
- 期末成绩的制定:0.7*考试成绩+0.3平时成绩,则该例子中,特征值为考试成绩和平时成绩,目标值为总成绩。
#现在有一组售房的数据
import numpy as np
import pandas
from pandas import DataFrame
import matplotlib.pylab as plt
dic = {
'面积':[55,76,80,100,120,150],
'售价':[110,152,160,200,240,300]
}
df = DataFrame(data=dic)
df
#输出结果:
面积 售价
0 55 110
1 76 152
2 80 160
3 100 200
4 120 240
5 150 300
对售房数据的分布情况进行展示
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
plt.scatter(df['面积'],df['售价'])
plt.xlabel('面积')
plt.ylabel('售价')
plt.title('面积和价钱的分布图')
散点图:
plt.scatter(df['面积'],df['售价'])
plt.xlabel('面积')
plt.ylabel('售价')
plt.title('面积和价钱的分布图')
plt.scatter(np.linspace(0,180,num=100),np.linspace(0,180,num=100)*2,alpha=0.3)
情况1:散点在所有直线上
线性方程图:y=2*x
线性回归的作用:找出特征和目标之间存在的某种趋势
该趋势表示形式:线性方程
线性方程y = wx就可以表示一条唯一的直线
标准的线性方程式为:y = wx + b,w为斜率,b为截距
何时带b: 加b的目的是为了使得趋势对应的直线更加具有通用性
分情况: 目标值有可能为0(直线过原点),带b,否则不带b
-
房价受影响的因素除了面积了,加入了采光率和楼层了,特征变成3种。在原始的线性方程y=wx+b中只可以有一个特征,则该方程不具备通用性。
标准线性关系模型为:
售价 = (w1面积+w2采光率+w3楼层)+ b==》y = (w1x1w2x2+wn*xn)+b
w叫做权重。
-
b可以变换成w0*x0,x0=1
- y = w0x0+w1x1+w2x2+wnxn
-
权重向量(行向量):w0,w1,...wn
- 行向量的转置就是列向量。行向量是一个 n×1 的矩阵,即矩阵由一个含有n个元素的行所组成。
行向量乘以行向量的转置为一个常数
线性回归
- 找出特征和特征权重之间的一种组合,预测对应的结果
- 线性方程式:
- 真实结果和预测结果是否会存在误差
若在房价预测案例中,特征与目标之间的分布规律不是线性的,也可以使用一条直线表示特征和目标之间的趋势,但是要保证直线距离所有的散点距离最近,该直线还是可以在一定程度上表示非线性分布散点之间的分布规律。但是该规律会存在误差
-
处理误差:
-
回归算法
回归算法是一个迭代算法。迭代就好比是系统版本的迭代,迭代后的系统要比迭代前的系统更好。
- 回归算法就是在不断的自身迭代的减少误差来使得回归算法的预测结果可以越发的逼近真实结果
- 官方解释:迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
误差的处理方法
回归算法就是在不断的自身迭代的减少误差来使得回归算法的预测结果可以越发的逼近真实结果
损失函数 来表示误差
-
- yi:为第i个训练样本的真实值
- hw(xi):预测值
损失函数:
![损失函数.png](https://upload-images.jianshu.io/upload_images/20605284-d2d60973738b85a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
又称为SSE(Sum of Sqaured Error,误差平方和)或者RSS(Residual Sum of Squares 残差平方和)
由上式知,误差的大小线性回归方程中的系数w是有直系关联的:w(权重)的不同会导致误差大小的不同
- L0,L1和L2范式:
- L0是指向量中非0的元素的个数。
- L1是指向量中各个元素绝对值之和。
- L2是指向量各元素的平方和然后求平方根
- 本质是就是欧式距离,即是两个向量上的每个点对应相减后的平方和再开平方
- 损失函数:欧式距离的平方
损失函数是在计算真实标签和预测值之间的距离,差异越小越好 ,故求:
![L2范式.png](https://upload-images.jianshu.io/upload_images/20605284-750eacb89f941ac7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最小二乘法 :通过最小化真实值和预测值之间的RSS来求解参数的方法 。 求解极值(最小值)就是求解一阶导数并让一阶导数等于0
L2范式求导
参考点:
1.两个向量(y&Xw)的平方就等于两个向量的转置乘以两个向量本身
2.处理转置乘法和减法
- 在矩阵求导中如果小a为常数项,A为矩阵则
-
API
最小二乘(正规方程):from sklearn.linear_model import LinearRegression
最小二乘法 : 参数中并没有一个是必填的
sklearn中的线性回归可以处理多标签问题,只需要在fit的时候输入多维度标签就可以了
normalize参数:如果为True,则会对特征数据进行归一化处理,如果想对特征数据进行标准化处理则需要在训练模型前调用相关工具类对其进行标准化处理。
- 使用最小二乘对加利福尼亚房屋进行预测
- 特征介绍:
- AveBedrms:该街区平均的卧室数目
- Population:街区人口
- AveOccup:平均入住率
- Latitude:街区的纬度
- Longitude:街区的经度
- MedInc:街区住户收入的中位数
- HouseAge:房屋使用年数中位数
- AveRooms:街区平均房屋的数量
from sklearn.linear_model import LinearRegression
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
#获取数据
house = datasets.fetch_california_housing(data_home='./datasets')
#样本数据提取
feature = house.data
target = house.target
feature.shape #(20640, 8)
#回归模型一般情况下不需要做特征的预处理,如果最终模型预测效果不好,可以适当考虑加上预处理
#数据集的切分
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)
#最小二乘
linner = LinearRegression(normalize=True,copy_X=False)
linner.fit(x_train,y_train)
#查看特征的权重系数
linner.coef_
#输出结果:
array([ 4.40832770e-01, 9.61642244e-03, -1.14781227e-01, 6.75973842e-01,
-5.10337874e-06, -3.47558983e-03, -4.19478386e-01, -4.32477249e-01])
#截距
linner.intercept_ #-36.77944310594463
#获取特征名称
feature_names = house.feature_names
#将系数和特征名称结合在一起查看
[*zip(feature_names,linner.coef_)]
#输出结果:
[('MedInc', 0.4408327703951707),
('HouseAge', 0.009616422444042731),
('AveRooms', -0.11478122746959658),
('AveBedrms', 0.6759738423151275),
('Population', -5.1033787395895275e-06),
('AveOccup', -0.003475589832443694),
('Latitude', -0.41947838567694423),
('Longitude', -0.4324772490416935)]
#预测
linner.score(x_test,y_test) #0.6077878946185034
回归模型的评价指标
- 回归类与分类型算法的模型评估都有相似的法则— —找真实标签和预测值的差异。只不过在分类型算法中,这个差异只有一种角度来评判,那就是是否预测到了正确的分类,而在回归类算法中,有两种不同的角度来看待回归的效果:
- 第一,是否预测到了正确或者接近正确的数值(因为误差的存在)。
- 第二,是否拟合到了足够的信息。(是否模型预测的结果线性和样本真实的结果的线性更加吻合)
- 这两种角度,分别对应着不同的模型评估指标。
1.是否预测到了正确的数值
- RSS残差平方和 ,本质是预测值与真实值之间的差异
致命缺点: 它是一个无界的和,可以无限地大或者无限的小
-
MSE 均方误差
本质是在RSS的基础上除以样本总量,得到每个样本量上的平均误差
查看这个错误有多严重 :比较平均误差和标签的取值范围(最大值和最小值) ( 最大值和最小值可以表示标签的一个分部情况 )
- 在sklearn当中,有两种方式调用这个评估指标:
- 一种是使用sklearn专用的模型评估模块metrics里的类mean_squared_error
- 另一种是调用交叉验证的类cross_val_score并使用里面的scoring参数来设置为:neg_mean_squared_error使用均方误差。
方式1:
from sklearn.metrics import mean_squared_error as MSE
#y_true:测试数据的真实标签
#y_pred:使用模型对测试集的预测结果
y_pred = linner.predict(x_test)
MSE(y_test,y_pred) #0.5313973307052253
y_test.min(),y_test.max() #(0.14999, 5.00001)
方式2:
from sklearn.model_selection import cross_val_score
cross_val_score(linner,x_train,y_train,cv=5,scoring='neg_mean_squared_error').mean() #-0.5309250456411233
交叉验证求得的均方误差为负值
均方误差的计算公式中求得的均方误差的值不可能为负。但是sklearn中的参数scoring下,均方误差作为评判标准时,却是计算”负均方误差“(neg_mean_squared_error)。这是因为sklearn在计算模型评估指标的时候,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失(loss)。在sklearn当中,所有的损失都使用负数表示,因此均方误差也被显示为负数了。真正的均方误差MSE的数值,其实就是neg_mean_squared_error去掉负号的数字。
-
绝对值误差(了解)
- 除了MSE,我们还有与MSE类似的MAE(Mean absolute error,绝对均值误差):
-
其表达的概念与均方误差完全一致,不过在真实标签和预测值之间的差异外我们使用的是L1范式(绝对值)。现实使用中,MSE和MAE选一个来使用就好了。
- 在sklearn当中,我们使用命令:from sklearn.metrics import mean_absolute_error来调用MAE
- 同时,我们也可以使用交叉验证中的scoring = "neg_mean_absolute_error", 以此在交叉验证时调用MAE。
2.是否拟合到了足够的信息
红色线是真实标签,蓝色线是模型预测的值
前半部分的拟合非常成功 , 但后半部分的拟合却非常糟糕
方差来衡量数据上的信息量 , 如果方差越大,代表数据上的信息量越多,而这个信息量(数据潜在的规律)不仅包括了数值的大小,还包括了我们希望模型捕捉的那些规律。R2:衡量模型对数据上的信息量的捕捉
1-我们的模型没有捕捉到的信息量占真实标签中所带的信息量的比例
分母是不变的,则误差越小则分子分母表达式返回的结果越小,则r2越接近1.
-
可以使用三种方式来调用
- 一种是直接从metrics中导入r2_score,输入预测值和真实值后打分。
- 第二种是直接从 线性回归LinearRegression的接口score来进行调用。
- 第三种是在交叉验证中,输入"r2"来调用。
from sklearn.metrics import r2_score
r2_score(y_test,y_pred) #0.6077878946185034
- 绘制拟合图
%matplotlib inline
import matplotlib.pyplot as plt
y_pred = linner.predict(x_test)
plt.plot(range(len(y_test)),sorted(y_test),c="black",label= "y_true")
plt.plot(range(len(y_pred)),sorted(y_pred),c="red",label = "y_predict")
plt.legend()
plt.show()
可见,虽然我们的大部分数据被拟合得比较好,但是图像的开头和结尾处却又着较大的拟合误差。如果我们在图像右侧分布着更多的数据,我们的模型就会越来越偏离我们真正的标签。这种结果类似于我们前面提到的,虽然在有限的数据集上将数值预测正确了,但却没有正确拟合数据的分布,如果有更多的数据进入我们的模型,那数据标签被预测错误的可能性是非常大的。
实战
- 房地产估价数据集数据集(house.xlsx)
- 数据集信息:
- 房地产估值的市场历史数据集来自台湾新北市新店区。“房地产估价” 是一个回归问题。
- 属性信息:
- 输入如下:
- X1 =交易日期(例如,2013.250 = 2013年3月,2013.500 = 2013年6月,等等)
- X2 =房屋年龄(单位:年)
- X3 =到最近的捷运站的距离(单位:米) )
- X4 =步行生活圈中的便利店的数量(整数)
- X5 =地理坐标,纬度。(单位:度)
- X6 =地理坐标,经度。(单位:度)
- 输出结果如下:
- Y =单位面积的房价(10000新台币/ Ping,其中Ping是本地单位,1 Ping = 3.3米平方)
- 输入如下:
- 数据集信息: