前面分类问题的评估有提到『8 种评估方法!』,但是它们并不适用于回归问题。
二分类问题的结果最终是一个 是or否 的结果,而回归问题的结果是一个 准确的数值。数值评估起来因为可以计算明显的距离,反倒更简单些。
比如说:0和1的绝对值误差是1,0和1的平方误差也是1,使用绝对值误差和平方误差都可以对这个样本做评估。
但是,回归问题评估的实现存在深坑,请一定小心
正文
回归问题的拟合比较简单,所用到的衡量指标也相对直观。假设 yi 是第 i 个样本的真实值,ŷi 是对第 i 个样本的预测值。
在模型评估中,你可以用平方和误差,通过预测值和真实值之间的平方和大小当做拟合的误差,模型的目的就是尽可能的降低全部样本的预测值和真实值之间的误差。
同样的,在回归问题中,我们一般通过如下方式计算模型拟合的误差:
▶1. 平均绝对误差
平均绝对误差:Mean Absolute Error 通常缩写为 MAE,又被称为 L1 范数损失,公式如下:
MAE 会计算每个样本真实值和预测值之间的绝对值误差,然后在误差和的基础上除以样本总量,得到平均绝对误差。
▶2. 平均平方误差
平均平方误差:Mean Squared Error 通常缩写为 MSE,又被称为 L2 范数损失,公式如下:
MSE 会计算每个样本真实值和预测值之间的平方误差,然后在误差和的基础上除以样本总量,得到平均平方误差。
MSE 一般比较常用些。
在对回归问题进行预测的时候,基于 sklearn 有两种方法可以调用评估指标,一种是直接使用模型评估模块 metrics 里面的类 mean_squared_error 和 mean_absolute_error 即可。
另一种是通过调用交叉验证类 cross_val_score 使用里面的参数 scoring 参数来设置使用平均绝对误差和平均平方误差
metrics 模块的具体使用方法如下:
# 导入相应模块的包
from sklearn.metrics import mean_squared_error as MSE, mean_absolute_error as MAE
y_true = [500, 510, 510, 515, 520]
y_pred = [495, 505, 10, 520, 525]
# 计算误差
print(MSE(y_true, y_pred))
print(MAE(y_true, y_pred))
# 输出
50020.0
104.0
直接使用模型的真实值和预测值,调用想用的误差计算函数即可
cross_val_score 模块的具体使用方法如下:
# 导入相应模块的包
from sklearn import datasets, linear_model
from sklearn.model_selection import cross_val_score
# 设置数据集
diabetes = datasets.load_diabetes()
X = diabetes.data[:150]
y = diabetes.target[:150]
# 选择模型并计算误差
reg = linear_model.LinearRegression()
print(cross_val_score(reg, X, y, cv=3, scoring='neg_mean_squared_error'))
print(cross_val_score(reg, X, y, cv=3, scoring='neg_mean_absolute_error'))
# 输出
-9734.12349421065
-138.43887460355668
仔细看,上面的输出结果对吗?
你会发现,不管是绝对误差还是平方误差,最终的误差结果都是负值?
和我们理解的不一样,sklearn 在计算模型评估指标的时候,会考虑指标本身的性质,既然是误差那肯定是一种损失 Loss。
在 sklearn 中,所有的损失都用负数表示,所以无论是均方误差还是平方误差,都会被计算成负数。而我们真正需要的值需要去掉负号。
在回归模型评估中,还有一个不容忽视的问题:模型是否拟合了足够的信息?
举个例子,如果一个模型在前半段数据上完美拟合,在后半段数据上拟合很差。这个时候,如果你用 MSE 去对模型进行评估的话,MSE 的值因为后半段的巨大差异被分散到整体样本上,所以会比较小。
很明显,这种拟合结果并不是一个很好的结果,如果新的样本特征是处于后半段的,那预测结果会存在很大的偏差。
我们希望的是,模型不但能够对数据有一个准确的预测,还能够尽可能的拟合足够多的样本数据。
这个时候,有一种评估标准就比较有用:R Squared
▶3. R Squared
R Squared 又称 r2 score,也叫做拟合优度,反映的模型对数据上的信息量的捕捉。公式如下:
信息量包括数值大小、数据的规律等。
RSS 其实前面没有提到过,就是预测值和真实值的残差平方和,后面会用到
关于信息量可以进一步理解成任意一个 y 值和样本均值的差异,当差异越大,所带的信息量越大,整体的 r2 也就越大。
以上, r2=1-未捕捉到的信息量占整体比例,所以 r2 越接近于 1,说明模型拟合得越好。
同样的,在 sklearn 中对于 r2 的计算也可以通过几种方式:
- ① 直接从 metrics 中导入 r2_score;
- ② 在线性回归中通过接口 score 进行调用;
- ③ 在交叉验证中 scoring 参数设置 r2 来调用
具体代码如下:
# 导入相应模块的包
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
y_true = [500, 510, 510, 515, 520]
y_pred = [495, 505, 10, 520, 525]
X = diabetes.data[:150]
y = diabetes.target[:150]
# 计算误差
print(r2_score(y_true, y_pred))
print(LinearRegression().fit(X, y).score(X, y))
print(cross_val_score(reg, X, y, cv=3, scoring='r2'))
# 输出结果
-1135.8181818181818
0.5298605010454656
[0.49843203 0.1037956 0.44394338]
仔细看上面的输出结果,发现什么问题没有?
r2 的结果竟然是负数?
你没看错,在 sklearn 里面 均方误差是负的,r2 的结果也是负的。
先来看直观理解:
如果 1 减去那个值大于1,那 r2 的结果不就是负数了嘛。
而且后面那个数如果分子远远大于分母,那上例中的 -1135 也就可以理解了。
继续理解,1 减去的值大于 1 说明什么?
我们知道,分子是真实值和预测值的平方和,分母是真实值和均值的平方和。
如果后面的结果远远大于1,那只能说明:预测值和真实值偏离太多了,换句话说,预测的结果太离谱了。
直白的说,当 r2 结果为负的时候,说明模拟拟合的结果太差了,需要检查一下参数或者重新选择模型了。
关于 r2 为什么可以是负数还有推导公式,个人觉得没必要,了解原因就行了。感兴趣的可以自己补课
总结一下
可以看到,在回归问题中,评估的方法就说了三种:平均绝对误差、平均平方误差和 R Squared
还有一些评估标准没有提到,例如平均均方根误差、平均绝对百分比误差、中位绝对误差等等,有空的可以了解,但是常用的就上面这三。
上面几种指标在使用的时候也是见仁见智,根据样本的具体情况使用,没有标准。