线性回归+评价指标
引入误差
在回归任务中不需要归一化的操作,本身就是寻找出权重的过程,不需要将各维度进行统一约束
找出特征和特征权重之间的一种组合,从而来预测对应的结果,误差的存在是必然的,回归的问题不像分类的问题,回归是一个连续值的预测,分类而是离散值的确定,那我们如何处理回归的误差?
-
回归算法是一个迭代算法。所谓的迭代就好比是系统版本的迭代,迭代后的系统要比迭代前的系统更好。
- 当开始训练线性回归模型的时候,是逐步的将样本数据带入模型对其进行训练的。
- 训练开始时先用部分的样本数据训练模型生成一组w和b,对应的直线和数据对应散点的误差比较大,通过不断的带入样本数据训练模型会逐步的迭代不好(误差较大)的w和b从而使得w和b的值更加的精准。
-
官方解释:迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
误差的大小线性回归方程中的系数w是有直系关联的
- w(权重)的不同会导致误差大小的不同
- 那么最终的问题就转化成了,【如何去求解方程中的w使得误差可以最小】
L范式介绍
- L0,L1和L2范式:
- L0是指向量中非0的元素的个数。
- L1是指向量中各个元素绝对值之和。
- L2是指向量各元素的平方和然后求平方根
我们的y和y^分别是我们的真实标签和预测值,也就是说,这个损失函数实在计算我们的真实标 签和预测值之间的距离。因此,我们认为这个损失函数衡量了我们构造的模型的预测结果和真实标签的差异,因此我 们固然希望我们的预测结果和真实值差异越小越好。所以我们的求解目标就可以转化为:
-
SSE&RSS:
- 其中右下角的2表示向量y-Xw的L2范式,也就是我们的损失函数所代表的含义。在L2范式上开平方,就是我们的损失函数。我们往往称呼这个式子为SSE(Sum of Sqaured Error,误差平方和)或者RSS(Residual Sum of Squares 残差平方和)。
-
最小二乘法
- 现在问题转换成了求解让RSS最小化的参数向量w,这种通过最小化真实值和预测值之间的RSS来求解参数的方法叫做最小二乘法。
- 求解极值(最小值)的第一步往往是求解一阶导数并让一阶导数等于0,最小二乘法也不能免俗。因此,我们现在在残差平方和RSS上对参数向量w求导。
最后的求导结果就是:
sklearn-线性回归
import sklearn.datasets as datasets
boston = datasets.load_boston()
feature = boston['data']
target = boston['target']
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2021)
#导入线性回归算法模型的工具类
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
linner = LinearRegression(normalize=True)
linner.fit(x_train,y_train)
w_array = linner.coef_ #返回每一个维度特征的权重系数
b = linner.intercept_ #截距
linner.score(x_test,y_test) # 0.6352336167833799
LinearRegression中包含一些参数,默认的会拟合截距
评价指标
这里提及三个评价指标:mse、mae、r2
1、MSE
- 在sklearn当中,我们有两种方式调用这个评估指标:
- 一种是使用sklearn专用的模型评估模块metrics里的类mean_squared_error
- 另一种是调用 交叉验证的类cross_val_score并使用里面的scoring参数来设置为:neg_mean_squared_error使用均方误差。
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import sklearn.datasets as datasets
from sklearn.metrics import mean_squared_error as MSE
data = datasets.fetch_california_housing(data_home='./datasets') # 加利福尼亚房屋数据
feature = data['data']
target = data['target']
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.1,random_state=2021)
linner = LinearRegression()
linner.fit(x_train,y_train)
y_pred = linner.predict(x_test)
MSE(y_test,y_pred) # 0.5253224455144776,越小越好
交叉验证
k折交叉
from sklearn.model_selection import cross_val_score
linner = LinearRegression()
cross_val_score(linner,x_train,y_train,cv=5,scoring='neg_mean_squared_error') # array([-0.52365303, -0.54918597, -0.54178747, -0.51412348, -0.5136022 ])
2、MAE
- 其表达的概念与均方误差完全一致,不过在真实标签和预测值之间的差异外我们使用的是L1范式(绝对值)。现实使 用中,MSE和MAE选一个来使用就好了。
- 在sklearn当中,我们使用命令
- from sklearn.metrics import mean_absolute_error来调用MAE,
- 同时,我们也可以使用交叉验证中的
- scoring = “neg_mean_absolute_error”, 以此在交叉验证时调用MAE。
- 在sklearn当中,我们使用命令
3、r2
红色线是我们的真实标签,而蓝色线是我们模型预测的值。这是一种比较极端,但的确可能发生的情况。这张图像上,前半部分的拟合非常成功,看上去我们的真实标签和我们的预测结果几乎重合,但后半部分的拟合却非常糟糕,模型向着与真实标签完全相反的方向去了。
-
分母其实可以表示称为样本的潜在规律,分子为模型的误差(损失),那么样本数据潜在的规律是不变的,则误差越小则分子分母表达式返回的结果越小,则r2越接近1.
-
可以使用三种方式来调用
- 一种是直接从metrics中导入r2_score,输入预测值和真实值后打分。
- 第二种是直接从 线性回归LinearRegression的接口score来进行调用。
- 第三种是在交叉验证中,输入"r2"来调用。
from sklearn.metrics import r2_score
data = datasets.fetch_california_housing(data_home='./datasets')
feature = data.data
target = data.target
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2021)
linner = LinearRegression()
linner.fit(x_train,y_train)
# linner.score(x_test,y_test)
#使用均方误差进行模型评估
y_true = y_test
y_pred = linner.predict(x_test)
r2_score(y_true,y_pred),linner.score(x_test,y_test) # (0.6196263393628889, 0.6196263393628889)
# 交叉验证
linner = LinearRegression()
cross_val_score(linner,x_test,y_test,cv=5,scoring='r2') # array([-8.39672596, 0.61600585, 0.6102257 , 0.64494468, 0.61964029])
多项式回归和过拟合欠拟合处理
欠拟合和过拟合的差别:训练出的模型在训练集有很好的效果,但在测试集并没有很好的效果,是过拟合;训练出的模型在训练集和测试集都没有很好的效果,是欠拟合。
- 欠拟合和过拟合的解决
- 欠拟合:
- 原因:模型学习到样本的特征太少
- 解决:增加样本的特征数量(多项式回归)
- 过拟合:
- 原因:原始特征过多,存在一些嘈杂特征。
- 解决:
- 进行特征选择,消除关联性大的特征(很难做)
- 正则化之岭回归(掌握)
- 欠拟合:
欠拟合的处理-多项式回归
- 为了解决欠拟合的情 经常要提高线性的次数(高次多项式)建立模型拟合曲线,次数过高会导致过拟合,次数不够会欠拟合。
- y = w*x + b 一次多项式函数
- y = w1x^2 + w2x + b 二次多项式函数
- y = w1x^3 + w2x^2 + w3*x + b 三次多项式函数
- 高次多项式函数的表示为曲线
这里拿二次多项式进行举例:
- 建立二次多项式线性回归模型进行预测
- 根据二次多项式公式可知,需要给原始特征添加更高次的特征数据x^2.
- y=w1x∧2+w2x+b
- 如何给样本添加高次的特征数据呢?
- 使用sklearn.preprocessing.PolynomialFeatures来进行更高次特征的构造
- 它是使用多项式的方法来进行的,如果有a,b两个特征,那么它的2次多项式为(1,a,b,a^2,ab, b^2)
- PolynomialFeatures有三个参数
- degree:控制多项式的度
- interaction_only: 默认为False,如果指定为True,上面的二次项中没有a2和b2。
- include_bias:默认为True。如果为False的话,那么就不会有上面的1那一项
- 使用sklearn.preprocessing.PolynomialFeatures来进行更高次特征的构造
- 根据二次多项式公式可知,需要给原始特征添加更高次的特征数据x^2.
# 示例
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
# 样本的训练数据,特征和目标值
x_train = [[6], [8], [10], [14], [18]] #大小
y_train = [[7], [9], [13], [17.5], [18]]#价格
from sklearn.preprocessing import PolynomialFeatures
p = PolynomialFeatures(degree=2,include_bias=False) # degree:控制多项式的度,也就是次数
p2_x_train = p.fit_transform(x_train)
# 用维度增加的数据进行训练模型
linear.fit(p2_x_train,y_train)
y_pred = linear.predict(p2_x_train)
plt.scatter(x_train,y_train)
plt.plot(x_train,y_pred) # 图像如下
过拟合处理-正则化
将过拟合的曲线的凹凸幅度减少就可以将过拟合曲线趋近于拟合曲线了。那么过拟合曲线的凹凸肯定是由y=wx**2+x**3+x**4中的高次项导致的,那么正则化就可以通过不断的尝试发现高次项的特征然后这些特征的权重w调小到0,则高次项的特征没有了,那么凹凸幅度就减少了,就越趋近于拟合曲线了!
可以使得高次项的w权重减小,趋近于0.
LinnerRegression是没有办法进行正则化的,所以该算法模型容易出现过拟合,并且无法解决。
-
L2正则化:
- 使用带有正则化算法的回归模型(Ridge岭回归)处理过拟合的问题。
-
API:from sklearn.linear_model import Ridge
-
Ridge(alpha=1.0):
- alpha:正则化的力度,力度越大,则表示高次项的权重w越接近于0,导致过拟合曲线的凹凸幅度越小。
- 取值:0-1小数或者1-10整数
- coef_:回归系数
- alpha:正则化的力度,力度越大,则表示高次项的权重w越接近于0,导致过拟合曲线的凹凸幅度越小。
-
使用岭回归可以通过控制正则化力度参数alpha降低高次项特征的权重
from sklearn.linear_model import Ridge
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
house = datasets.load_boston()
feature = house['data'][:,4:10] # 选取6列模型
target = house['target']
r = Ridge(alpha=1) # alpha数值越大,正则化力度越大
r.fit(feature,target)
r.coef_ # w值:array([-7.27044571, 7.65235494, -0.07212532, -1.05017594, 0.05775603,-0.01653923])