《sklearn机器学习——回归指标1》
skearn.metrics模块实现一些损失函数,评分,并且应用函数去测度回归标签。其中一些已经改进,可以处理多指标案例:mean_squared_error,mean_absolute_error,explained_variance_score和r2_score。
这些函数使用关键参数multioutout,它指定计算方式,每一个标签的得分或损失都会被平均。初始值是“uniform_average”,它指定给所有输出均匀权重,计算所有输出的平均值。如果一个ndarray的形状(n_outputs,)被传入,它的各条目会被解释为权重,同时返回相应的加权平均值。如果multioutput的值指定为“raw_values”,则所有未改变的得分或损失将会被返回,并以数组形式返回(n_outputs,)。
r2_score和explained_variance_score接受一个额外的值"variance_weighted"给multioutput参数。这个选项是每一个得分的权重通过与目标变量相一致的方差得到。这个设置量化全局捕捉未缩放的方差。如果目标变量是不同的比例,那么这个分数就会将更多的重点放到解释较高方差的变量上。对于向后兼容,r2_score的初始值是multioutput = “variance_weighted”。这个值将会在未来变为uniform_average。
可解释的方差分数
explained Variance Score 参数与返回值
参数
explained_variance_score
函数通常包含以下参数:
-
y_true: array-like, 必需
实际目标值。这是一组你想要模型预测的真实数值。 -
y_pred: array-like, 必需
预测目标值。这是由模型生成的预测数值,长度需要与y_true
相同。 -
sample_weight: array-like, 可选 (默认=None)
样本权重。如果指定,则根据这些权重来计算解释方差分数。 -
multioutput: string in [‘raw_values’, ‘uniform_average’] or array-like, 可选 (默认=‘uniform_average’)
定义如何处理多输出数据的情况。‘raw_values’ 返回每个输出的误差得分,‘uniform_average’ 返回所有输出误差得分的平均值。
返回值
- score: float or ndarray of floats
解释方差分数。对于单目标回归问题,返回一个浮点数。对于多目标回归问题,如果multioutput='raw_values'
,则返回一个浮点数组,其中每个元素代表对应输出的解释方差分数;否则,返回这些分数的平均值作为一个浮点数。
explained_variance_score内部计算的数学形式
[explained_variance_score]计算explained variance regression score。
如果y^\hat{y}y^是标签估计值,yyy是与之相一致(正确)的标签输出,并且Var是[Variance],标准差的平方,则可解释的方法计算如下:
explained_variance(y,y^)=1−Var{y−y^}Var{y}\begin{aligned} explained\_variance(y, \hat{y}) = 1 - \frac{Var\{y - \hat{y}\}}{Var\{y\}} \end{aligned}explained_variance(y,y^)=1−Var{y}Var{y−y^}
最好的可能取值是1.0,值越低越不好。
如下是一个使用[explained_variane_score]函数的小例子:
以下是一个explained_variance_score使用的简单示例:
import numpy as np
from sklearn.metrics import explained_variance_score
import matplotlib.pyplot as plt# --- 示例 1: 好的模型预测 ---
print("=== 示例 1: 模型预测效果很好 ===")# 真实值 (例如: 房价)
y_true_good = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (非常接近真实值,只有微小误差)
y_pred_good = np.array([101, 119, 141, 159, 181, 199, 221, 239])# 计算可解释方差得分
evs_good = explained_variance_score(y_true_good, y_pred_good)
print(f"真实值: {y_true_good}")
print(f"预测值: {y_pred_good}")
print(f"可解释方差得分: {evs_good:.4f}") # 非常接近 1.0
print()# --- 示例 2: 差的模型预测 ---
print("=== 示例 2: 模型预测效果很差 ===")# 真实值 (相同)
y_true_bad = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (与真实值相差很大,预测不稳定)
y_pred_bad = np.array([80, 150, 120, 190, 140, 230, 200, 270])# 计算可解释方差得分
evs_bad = explained_variance_score(y_true_bad, y_pred_bad)
print(f"真实值: {y_true_bad}")
print(f"预测值: {y_pred_bad}")
print(f"可解释方差得分: {evs_bad:.4f}") # 远低于 1.0,甚至可能为负
print()# --- 示例 3: 模型只是预测均值 (基线) ---
print("=== 示例 3: 模型只是预测均值 (最差情况之一) ===")y_true_mean = np.array([100, 120, 140, 160, 180, 200, 220, 240])
# 模型没有学习,只是对所有样本都预测真实值的平均值
mean_prediction = np.mean(y_true_mean)
y_pred_mean = np.full_like(y_true_mean, mean_prediction) # [170, 170, ..., 170]evs_mean = explained_variance_score(y_true_mean, y_pred_mean)
print(f"真实值: {y_true_mean}")
print(f"预测值: {y_pred_mean}")
print(f"可解释方差得分: {evs_mean:.4f}") # 应该是 0.0
print()# --- 示例 4: 预测比均值还差 ---
print("=== 示例 4: 模型预测比均值还差 ===")y_true_worse = np.array([100, 120, 140, 160, 180, 200, 220, 240])
# 预测值引入了比真实值方差还大的噪声
y_pred_worse = y_true_worse + np.random.normal(0, 50, size=y_true_worse.shape) # 加入大噪声evs_worse = explained_variance_score(y_true_worse, y_pred_worse)
print(f"真实值: {y_true_worse}")
print(f"预测值: {y_pred_worse.round(1)}")
print(f"可解释方差得分: {evs_worse:.4f}") # 可能小于 0
print()# --- 可视化 ---
plt.figure(figsize=(12, 8))# 子图 1: 好的预测
plt.subplot(2, 2, 1)
plt.scatter(y_true_good, y_pred_good, color='green', alpha=0.7)
plt.plot([y_true_good.min(), y_true_good.max()], [y_true_good.min(), y_true_good.max()], 'r--', lw=2)
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'好模型 (EVS = {evs_good:.4f})')
plt.grid(True, alpha=0.3)# 子图 2: 差的预测
plt.subplot(2, 2, 2)
plt.scatter(y_true_bad, y_pred_bad, color='red', alpha=0.7)
plt.plot([y_true_bad.min(), y_true_bad.max()], [y_true_bad.min(), y_true_bad.max()], 'r--', lw=2)
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'差模型 (EVS = {evs_bad:.4f})')
plt.grid(True, alpha=0.3)# 子图 3: 预测均值
plt.subplot(2, 2, 3)
plt.scatter(y_true_mean, y_pred_mean, color='orange', alpha=0.7)
plt.plot([y_true_mean.min(), y_true_mean.max()], [y_true_mean.min(), y_true_mean.max()], 'r--', lw=2)
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'预测均值 (EVS = {evs_mean:.4f})')
plt.grid(True, alpha=0.3)# 子图 4: 更差的预测
plt.subplot(2, 2, 4)
plt.scatter(y_true_worse, y_pred_worse, color='purple', alpha=0.7)
plt.plot([y_true_worse.min(), y_true_worse.max()], [y_true_worse.min(), y_true_worse.max()], 'r--', lw=2)
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'更差模型 (EVS = {evs_worse:.4f})')
plt.grid(True, alpha=0.3)plt.tight_layout()
plt.show()
结果:
=== 示例 1: 模型预测效果很好 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [101 119 141 159 181 199 221 239]
可解释方差得分: 0.9898=== 示例 2: 模型预测效果很差 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [ 80 150 120 190 140 230 200 270]
可解释方差得分: 0.5714=== 示例 3: 模型只是预测均值 (最差情况之一) ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [170 170 170 170 170 170 170 170]
可解释方差得分: 0.0000=== 示例 4: 模型预测比均值还差 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [103.7 138.8 135.6 205.2 216.5 204.6 215.5 299.7]
可解释方差得分: -0.9950
关键点总结
- 高分 (接近 1.0): 预测值紧密围绕对角线分布,误差小且稳定(示例 1)。
- 中等分数 (如 0.57): 预测值分散,误差较大,模型解释能力一般(示例 2)。
- 零分 (0.0): 模型的预测效果等同于直接用真实值的均值来预测,完全没有“解释”数据中的方差(示例 3)。
- 负分 (< 0): 模型的预测引入了比使用均值预测更大的方差,表现极差(示例 4)。
最大误差
Max Error 函数
参数
max_error
函数通常包含以下参数:
-
y_true: array-like of shape (n_samples,) or (n_samples, n_outputs)
实际目标值。这是一组你希望模型预测的真实数值。 -
y_pred: array-like of shape (n_samples,) or (n_samples, n_outputs)
预测目标值。这是由模型生成的预测数值,其形状需要与y_true
相匹配。 -
sample_weight: array-like of shape (n_samples,), optional
样本权重。如果提供,则使用这些权重来计算最大误差。
返回值
- max_error: float
最大绝对误差,即所有样本中实际值与预测值之间绝对差异的最大值。
内部的数学形式
如果y^i\hat{y}_iy^i是第iii个样本的预测值,yiy_iyi是与之相一致的真实值,最大误差定义如下:
MaxError(y,y^)=max(∣yi−y^i∣)\begin{aligned} MaxError(y, \hat{y}) = max(|y_i - \hat{y}_i|) \end{aligned}MaxError(y,y^)=max(∣yi−y^i∣)
如下是使用[max_error]函数的小例子:
import numpy as np
from sklearn.metrics import max_error
import matplotlib.pyplot as plt# --- 示例 1: 模型预测效果很好 ---
print("=== 示例 1: 模型预测效果很好 ===")# 真实值 (例如: 房价, 单位: 万元)
y_true_good = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (非常接近真实值,误差很小)
y_pred_good = np.array([101, 119, 141, 159, 181, 199, 221, 239])# 计算最大误差
me_good = max_error(y_true_good, y_pred_good)print(f"真实值: {y_true_good}")
print(f"预测值: {y_pred_good}")
print(f"最大误差: {me_good}") # 应该是 2 (例如 |141-140|=1, |239-240|=1, 最大是 1? 等等,检查一下)
# 让我们手动计算一下: |100-101|=1, |120-119|=1, |140-141|=1, |160-159|=1, |180-181|=1, |200-199|=1, |220-221|=1, |240-239|=1
# 所有误差都是 1,所以最大误差是 1。
# 修正预测值,让其中一个误差变大
y_pred_good = np.array([101, 119, 141, 159, 181, 199, 221, 235]) # 最后一个预测为 235
me_good = max_error(y_true_good, y_pred_good)
print(f"修正后预测值: {y_pred_good}")
print(f"最大误差: {me_good}") # |240 - 235| = 5
print()# --- 示例 2: 模型预测效果很差 (有一个很大的离群误差) ---
print("=== 示例 2: 模型预测效果很差 (有离群点) ===")y_true_bad = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型对大部分预测得不错,但有一个样本预测严重错误
y_pred_bad = np.array([101, 119, 141, 159, 181, 199, 221, 300]) # 最后一个预测为 300me_bad = max_error(y_true_bad, y_pred_bad)
print(f"真实值: {y_true_bad}")
print(f"预测值: {y_pred_bad}")
print(f"最大误差: {me_bad}") # |240 - 300| = 60
print()# --- 示例 3: 比较两个模型 ---
print("=== 示例 3: 比较两个模型 ===")# 假设有两个模型对同一组数据的预测y_true = np.array([50, 60, 70, 80, 90, 100])# 模型 A: 预测比较稳定,误差小
y_pred_A = np.array([52, 58, 71, 79, 88, 102])
me_A = max_error(y_true, y_pred_A)
print(f"模型 A 预测: {y_pred_A}")
print(f"模型 A 最大误差: {me_A}") # 最大是 |100-102|=2 或 |50-52|=2# 模型 B: 大部分预测很准,但有一个预测严重错误
y_pred_B = np.array([51, 59, 70, 81, 89, 150]) # 最后一个预测为 150
me_B = max_error(y_true, y_pred_B)
print(f"模型 B 预测: {y_pred_B}")
print(f"模型 B 最大误差: {me_B}") # |100-150|=50print(f"\n结论: 虽然模型 B 在前 5 个样本上预测得比模型 A 好,但由于第 6 个样本的预测错误极大 (50),")
print(f"其最大误差 (50) 远大于模型 A 的最大误差 (2)。这说明模型 B 在最坏情况下的表现非常不可靠。")
print()# --- 可视化 ---
plt.figure(figsize=(12, 5))# 子图 1: 好模型
plt.subplot(1, 2, 1)
plt.scatter(y_true_good, y_pred_good, color='green', alpha=0.7, label='样本')
plt.plot([y_true_good.min(), y_true_good.max()], [y_true_good.min(), y_true_good.max()], 'r--', lw=2, label='完美预测线')
# 标出最大误差的点 (最后一个点)
max_idx_good = np.argmax(np.abs(y_true_good - y_pred_good))
plt.plot([y_true_good[max_idx_good], y_true_good[max_idx_good]], [y_true_good[max_idx_good], y_pred_good[max_idx_good]], 'b-', linewidth=2, label=f'最大误差 ({me_good})')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 1: 最大误差 = {me_good}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 2: 差模型 (有离群点)
plt.subplot(1, 2, 2)
plt.scatter(y_true_bad, y_pred_bad, color='red', alpha=0.7, label='样本')
plt.plot([y_true_bad.min(), y_true_bad.max()], [y_true_bad.min(), y_true_bad.max()], 'r--', lw=2, label='完美预测线')
# 标出最大误差的点 (最后一个点)
max_idx_bad = np.argmax(np.abs(y_true_bad - y_pred_bad))
plt.plot([y_true_bad[max_idx_bad], y_true_bad[max_idx_bad]], [y_true_bad[max_idx_bad], y_pred_bad[max_idx_bad]], 'b-', linewidth=2, label=f'最大误差 ({me_bad})')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 2: 最大误差 = {me_bad}')
plt.legend()
plt.grid(True, alpha=0.3)plt.tight_layout()
plt.show()
结果:
=== 示例 1: 模型预测效果很好 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [101 119 141 159 181 199 221 239]
修正后预测值: [101 119 141 159 181 199 221 235]
最大误差: 5=== 示例 2: 模型预测效果很差 (有离群点) ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [101 119 141 159 181 199 221 300]
最大误差: 60=== 示例 3: 比较两个模型 ===
模型 A 预测: [ 52 58 71 79 88 102]
模型 A 最大误差: 2
模型 B 预测: [ 51 59 70 81 89 150]
模型 B 最大误差: 50结论: 虽然模型 B 在前 5 个样本上预测得比模型 A 好,但由于第 6 个样本的预测错误极大 (50),
其最大误差 (50) 远大于模型 A 的最大误差 (2)。这说明模型 B 在最坏情况下的表现非常不可靠。
关键点总结
- 关注最坏情况: max_error 告诉你模型可能犯的最大错误是多少。在对安全性或风险要求极高的场景(如自动驾驶、医疗诊断),了解这个“最坏情况”至关重要。
- 对异常值敏感: 即使只有一个样本预测得非常差,max_error 的值也会变得很大,从而反映出模型的潜在风险。
- 简单直观: 结果是一个具体的数值(与目标变量同单位),易于理解和解释。
- 不能反映整体性能: 它完全忽略了其他所有样本的预测精度。一个 max_error 很小的模型,其平均误差(如 MAE, RMSE)可能仍然很大。因此,它通常与其他指标(如 MAE, MSE, R²)结合使用。
总而言之,max_error 是一个非常有用的“风险警示”指标,它能快速告诉你模型预测的误差范围的上限。
平均绝对误差(mean_absolute_error函数
)
mean_absolute_error函数计算mean absolute error,一个与绝对误差损失或者-正则损失相一致的风险指标。
Mean Absolute Error 参数与返回值
函数简介
mean_absolute_error
是一个用于计算预测值与实际值之间平均绝对误差的函数。它常用于回归模型性能的评估。
参数
-
y_true: array-like of shape (n_samples,) or (n_samples, n_outputs)
实际目标值。这是一组你希望模型预测的真实数值。 -
y_pred: array-like of shape (n_samples,) or (n_samples, n_outputs)
预测目标值。这是由模型生成的预测数值,其形状需要与y_true
相匹配。 -
sample_weight: array-like of shape (n_samples,), optional
样本权重。如果提供,则使用这些权重来加权平均绝对误差。 -
multioutput: {‘raw_values’, ‘uniform_average’} or array-like of shape (n_outputs,), optional
定义如何在多输出(multi-output)情况下聚合错误。默认为’uniform_average’,它将对所有输出的误差进行平均。如果是’raw_values’,则返回每个输出的误差。如果提供了array-like,则其长度必须与输出数量相匹配,并指定每个输出的权重。
返回值
- loss: float or ndarray of floats
平均绝对误差损失。对于单个输出或当multioutput
设置为’uniform_average’时返回float。否则,当multioutput='raw_values'
时返回各输出误差组成的ndarray。
内部的数学形式
如果y^i\hat{y}_iy^i是第iii个样本的预测值,且yiy_iyi是与之相一致的真实值,nsamplesn_{samples}nsamples样本的平均绝对误差(MAE)定义如下:
MAE(y,y^)=1nsamples∑i=0nsamples−1∣yi−y^i∣.\begin{aligned} MAE(y, \hat{y}) = \frac{1}{n_{samples}} \sum_{i=0}^{n_{samples}-1} |y_i - \hat{y}_i|. \end{aligned}MAE(y,y^)=nsamples1i=0∑nsamples−1∣yi−y^i∣.
如下是使用mean_absolute_error函数的小例子:
import numpy as np
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt# --- 示例 1: 模型预测效果很好 ---
print("=== 示例 1: 模型预测效果很好 ===")# 真实值 (例如: 房价, 单位: 万元)
y_true_good = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (非常接近真实值)
y_pred_good = np.array([102, 118, 142, 158, 182, 198, 222, 238])# 计算平均绝对误差
mae_good = mean_absolute_error(y_true_good, y_pred_good)print(f"真实值: {y_true_good}")
print(f"预测值: {y_pred_good}")
print(f"绝对误差: {np.abs(y_true_good - y_pred_good)}") # 计算每个样本的绝对误差
print(f"平均绝对误差 (MAE): {mae_good:.2f} 万元")
print()# --- 示例 2: 模型预测效果一般 ---
print("=== 示例 2: 模型预测效果一般 ===")y_true_fair = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (与真实值有一定差距)
y_pred_fair = np.array([90, 130, 130, 170, 170, 210, 210, 250])mae_fair = mean_absolute_error(y_true_fair, y_pred_fair)
print(f"真实值: {y_true_fair}")
print(f"预测值: {y_pred_fair}")
print(f"绝对误差: {np.abs(y_true_fair - y_pred_fair)}")
print(f"平均绝对误差 (MAE): {mae_fair:.2f} 万元")
print()# --- 示例 3: 模型预测效果很差 (有异常值) ---
print("=== 示例 3: 模型预测效果很差 (有异常值) ===")y_true_poor = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型对大部分预测得还行,但有一个样本预测严重错误
y_pred_poor = np.array([102, 118, 142, 158, 182, 198, 222, 300]) # 最后一个预测为 300mae_poor = mean_absolute_error(y_true_poor, y_pred_poor)
print(f"真实值: {y_true_poor}")
print(f"预测值: {y_pred_poor}")
print(f"绝对误差: {np.abs(y_true_poor - y_pred_poor)}")
print(f"平均绝对误差 (MAE): {mae_poor:.2f} 万元")
print()# --- 示例 4: 比较不同模型 ---
print("=== 示例 4: 比较两个模型 ===")y_true = np.array([50, 60, 70, 80, 90, 100])# 模型 A: 预测稳定,误差较小
y_pred_A = np.array([52, 58, 71, 79, 88, 102])
mae_A = mean_absolute_error(y_true, y_pred_A)
print(f"模型 A 预测: {y_pred_A}")
print(f"模型 A MAE: {mae_A:.2f}")# 模型 B: 大部分预测很准,但有一个大误差
y_pred_B = np.array([51, 59, 70, 81, 89, 150]) # 最后一个预测为 150
mae_B = mean_absolute_error(y_true, y_pred_B)
print(f"模型 B 预测: {y_pred_B}")
print(f"模型 B MAE: {mae_B:.2f}")print(f"\n结论: 模型 A 的 MAE ({mae_A:.2f}) 小于模型 B 的 MAE ({mae_B:.2f}),")
print(f"说明模型 A 的平均预测误差更小,整体表现更好。")
print(f"注意: MAE 对异常值 (如模型 B 的 150) 有影响,但不像 MSE 那样被平方放大。")
print()# --- 可视化 ---
plt.figure(figsize=(15, 10))# 子图 1: 好模型
plt.subplot(2, 3, 1)
plt.scatter(y_true_good, y_pred_good, color='green', alpha=0.7, label='样本')
plt.plot([y_true_good.min(), y_true_good.max()], [y_true_good.min(), y_true_good.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 1: MAE = {mae_good:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 2: 一般模型
plt.subplot(2, 3, 2)
plt.scatter(y_true_fair, y_pred_fair, color='orange', alpha=0.7, label='样本')
plt.plot([y_true_fair.min(), y_true_fair.max()], [y_true_fair.min(), y_true_fair.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 2: MAE = {mae_fair:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 3: 差模型 (有异常值)
plt.subplot(2, 3, 3)
plt.scatter(y_true_poor, y_pred_poor, color='red', alpha=0.7, label='样本')
plt.plot([y_true_poor.min(), y_true_poor.max()], [y_true_poor.min(), y_true_poor.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 3: MAE = {mae_poor:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 4: 绝对误差分布 (好模型)
plt.subplot(2, 3, 4)
errors_good = np.abs(y_true_good - y_pred_good)
plt.bar(range(len(errors_good)), errors_good, color='green', alpha=0.7)
plt.axhline(y=mae_good, color='blue', linestyle='-', label=f'MAE = {mae_good:.2f}')
plt.xlabel('样本索引')
plt.ylabel('绝对误差')
plt.title('绝对误差分布 (好模型)')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 5: 绝对误差分布 (一般模型)
plt.subplot(2, 3, 5)
errors_fair = np.abs(y_true_fair - y_pred_fair)
plt.bar(range(len(errors_fair)), errors_fair, color='orange', alpha=0.7)
plt.axhline(y=mae_fair, color='blue', linestyle='-', label=f'MAE = {mae_fair:.2f}')
plt.xlabel('样本索引')
plt.ylabel('绝对误差')
plt.title('绝对误差分布 (一般模型)')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 6: 绝对误差分布 (差模型)
plt.subplot(2, 3, 6)
errors_poor = np.abs(y_true_poor - y_pred_poor)
plt.bar(range(len(errors_poor)), errors_poor, color='red', alpha=0.7)
plt.axhline(y=mae_poor, color='blue', linestyle='-', label=f'MAE = {mae_poor:.2f}')
plt.xlabel('样本索引')
plt.ylabel('绝对误差')
plt.title('绝对误差分布 (差模型)')
plt.legend()
plt.grid(True, alpha=0.3)plt.tight_layout()
plt.show()
结果:
=== 示例 1: 模型预测效果很好 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [102 118 142 158 182 198 222 238]
绝对误差: [2 2 2 2 2 2 2 2]
平均绝对误差 (MAE): 2.00 万元=== 示例 2: 模型预测效果一般 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [ 90 130 130 170 170 210 210 250]
绝对误差: [10 10 10 10 10 10 10 10]
平均绝对误差 (MAE): 10.00 万元=== 示例 3: 模型预测效果很差 (有异常值) ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [102 118 142 158 182 198 222 300]
绝对误差: [ 2 2 2 2 2 2 2 60]
平均绝对误差 (MAE): 10.25 万元=== 示例 4: 比较两个模型 ===
模型 A 预测: [ 52 58 71 79 88 102]
模型 A MAE: 2.00
模型 B 预测: [ 51 59 70 81 89 150]
模型 B MAE: 9.17结论: 模型 A 的 MAE (2.00) 小于模型 B 的 MAE (9.17),
说明模型 A 的平均预测误差更小,整体表现更好。
注意: MAE 对异常值 (如模型 B 的 150) 有影响,但不像 MSE 那样被平方放大。
关键点总结
- 直观易懂: MAE 的结果与目标变量同单位,可以直接解释为“平均预测偏差了 X 单位”。例如,MAE=2.00 万元,就是平均差了 2 万元。
- 衡量平均性能: 它反映的是模型在所有样本上的平均水平。MAE 越小,模型整体预测越准确。
- 对异常值相对稳健: 虽然异常值会影响 MAE(如示例 3 中一个 60 的误差把 MAE 从 2 拉到了 10.25),但因为它用的是绝对值而不是平方,所以影响程度比 MSE/RMSE 要小。MSE 会把大误差(如 60)平方成 3600,极大地拉高整体得分。
- 常用指标: MAE 是回归问题中最基础、最常用的评估指标之一,常与 MSE、RMSE、R² 等指标一起使用来全面评估模型。
总而言之,mean_absolute_error 是一个简单、强大且易于解释的工具,能快速告诉你模型的预测平均偏离真实值有多远。
均方误差(mean_squared_error函数)
mean_squared_error函数计算mean square error,平方(二次的)误差或损失的期望值相一致的风险指标。
Mean Squared Error 参数与返回值
函数简介
mean_squared_error
是用于计算预测值与实际值之间均方误差的函数。它广泛应用于回归分析中,作为评估模型性能的一个标准。
参数
-
y_true: array-like of shape (n_samples,) or (n_samples, n_outputs)
实际目标值。表示你希望模型预测的真实数值。 -
y_pred: array-like of shape (n_samples,) or (n_samples, n_outputs)
预测目标值。由模型生成的预测数值,其形状需要与y_true
相匹配。 -
sample_weight: array-like of shape (n_samples,), optional
样本权重。如果提供,则使用这些权重来加权平均平方误差。 -
multioutput: {‘raw_values’, ‘uniform_average’} or array-like of shape (n_outputs,), optional
定义如何在多输出(multi-output)情况下聚合错误。默认为’uniform_average’,它将对所有输出的误差进行平均。如果是’raw_values’,则返回每个输出的误差。如果提供了array-like,则其长度必须与输出数量相匹配,并指定每个输出的权重。 -
squared: bool, default=True
如果为True,则返回的是均方误差;如果为False,则返回均方根误差。
返回值
- loss: float or ndarray of floats
均方误差或均方根误差损失。对于单个输出或当multioutput
设置为’uniform_average’时返回float。如果squared=False
,则返回的是均方根误差(RMSE);如果squared=True
(默认),则返回的是均方误差(MSE)。当multioutput='raw_values'
时,返回各输出误差组成的ndarray。
内部的数学形式
如果y^i\hat{y}_iy^i是第iii个样本的预测值,yiy_iyi是与之相一致的真实值,均方误差(MSE)对nsamplesn_{samples}nsamples的估计值被定义如下:
MSE(y,y^)=1nsamples∑i=0nsamples−1(yi−y^i)2.\begin{aligned} MSE(y, \hat{y}) = \frac{1}{n_{samples}} \sum_{i=0}^{n_{samples}-1} (y_i - \hat{y}_i)^2. \end{aligned}MSE(y,y^)=nsamples1i=0∑nsamples−1(yi−y^i)2.
如下是一个使用mean_squared_error函数的小例子:
import numpy as np
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt# --- 示例 1: 模型预测效果很好 ---
print("=== 示例 1: 模型预测效果很好 ===")# 真实值 (例如: 房价, 单位: 万元)
y_true_good = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (非常接近真实值)
y_pred_good = np.array([102, 118, 142, 158, 182, 198, 222, 238])# 计算均方误差
mse_good = mean_squared_error(y_true_good, y_pred_good)print(f"真实值: {y_true_good}")
print(f"预测值: {y_pred_good}")
print(f"误差: {y_true_good - y_pred_good}") # 计算每个样本的误差
print(f"误差平方: {(y_true_good - y_pred_good)**2}") # 计算误差的平方
print(f"均方误差 (MSE): {mse_good:.2f} (万元²)") # 注意单位是平方
print()# --- 示例 2: 模型预测效果一般 ---
print("=== 示例 2: 模型预测效果一般 ===")y_true_fair = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型预测值 (与真实值有一定差距)
y_pred_fair = np.array([90, 130, 130, 170, 170, 210, 210, 250])mse_fair = mean_squared_error(y_true_fair, y_pred_fair)
print(f"真实值: {y_true_fair}")
print(f"预测值: {y_pred_fair}")
print(f"误差平方: {(y_true_fair - y_pred_fair)**2}")
print(f"均方误差 (MSE): {mse_fair:.2f} (万元²)")
print()# --- 示例 3: 模型预测效果很差 (有异常值) ---
print("=== 示例 3: 模型预测效果很差 (有异常值) ===")y_true_poor = np.array([100, 120, 140, 160, 180, 200, 220, 240])# 模型对大部分预测得还行,但有一个样本预测严重错误
y_pred_poor = np.array([102, 118, 142, 158, 182, 198, 222, 300]) # 最后一个预测为 300mse_poor = mean_squared_error(y_true_poor, y_pred_poor)
print(f"真实值: {y_true_poor}")
print(f"预测值: {y_pred_poor}")
print(f"误差平方: {(y_true_poor - y_pred_poor)**2}")
print(f"均方误差 (MSE): {mse_poor:.2f} (万元²)")
print()# --- 示例 4: 与 MAE 对比 (突出对异常值的敏感性) ---
print("=== 示例 4: MSE vs MAE (对异常值的敏感性) ===")y_true = np.array([50, 60, 70, 80, 90, 100])# 模型 A: 预测稳定,误差较小
y_pred_A = np.array([52, 58, 71, 79, 88, 102])
mse_A = mean_squared_error(y_true, y_pred_A)
mae_A = mean_absolute_error(y_true, y_pred_A) # 需要导入 mean_absolute_error
print(f"模型 A 预测: {y_pred_A}")
print(f"模型 A - MSE: {mse_A:.2f}, MAE: {mae_A:.2f}")# 模型 B: 大部分预测很准,但有一个大误差 (异常值)
y_pred_B = np.array([51, 59, 70, 81, 89, 150]) # 最后一个预测为 150
mse_B = mean_squared_error(y_true, y_pred_B)
mae_B = mean_absolute_error(y_true, y_pred_B)
print(f"模型 B 预测: {y_pred_B}")
print(f"模型 B - MSE: {mse_B:.2f}, MAE: {mae_B:.2f}")print(f"\n结论:")
print(f" - MAE: 模型B ({mae_B:.2f}) > 模型A ({mae_A:.2f}),但差距相对温和。")
print(f" - MSE: 模型B ({mse_B:.2f}) >> 模型A ({mse_A:.2f}),差距被显著放大!")
print(f"这是因为 MSE 将模型 B 的大误差 (|100-150|=50) 平方成了 2500,")
print(f"极大地拉高了整体 MSE 值,从而更强烈地惩罚了这种大错误。")
print()# --- 可视化 ---
plt.figure(figsize=(15, 10))# 子图 1: 好模型
plt.subplot(2, 3, 1)
plt.scatter(y_true_good, y_pred_good, color='green', alpha=0.7, label='样本')
plt.plot([y_true_good.min(), y_true_good.max()], [y_true_good.min(), y_true_good.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 1: MSE = {mse_good:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 2: 一般模型
plt.subplot(2, 3, 2)
plt.scatter(y_true_fair, y_pred_fair, color='orange', alpha=0.7, label='样本')
plt.plot([y_true_fair.min(), y_true_fair.max()], [y_true_fair.min(), y_true_fair.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 2: MSE = {mse_fair:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 3: 差模型 (有异常值)
plt.subplot(2, 3, 3)
plt.scatter(y_true_poor, y_pred_poor, color='red', alpha=0.7, label='样本')
plt.plot([y_true_poor.min(), y_true_poor.max()], [y_true_poor.min(), y_true_poor.max()], 'r--', lw=2, label='完美预测线')
plt.xlabel('真实值')
plt.ylabel('预测值')
plt.title(f'示例 3: MSE = {mse_poor:.2f}')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 4: 误差平方分布 (好模型)
plt.subplot(2, 3, 4)
squared_errors_good = (y_true_good - y_pred_good)**2
plt.bar(range(len(squared_errors_good)), squared_errors_good, color='green', alpha=0.7)
plt.axhline(y=mse_good, color='blue', linestyle='-', label=f'MSE = {mse_good:.2f}')
plt.xlabel('样本索引')
plt.ylabel('误差平方')
plt.title('误差平方分布 (好模型)')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 5: 误差平方分布 (一般模型)
plt.subplot(2, 3, 5)
squared_errors_fair = (y_true_fair - y_pred_fair)**2
plt.bar(range(len(squared_errors_fair)), squared_errors_fair, color='orange', alpha=0.7)
plt.axhline(y=mse_fair, color='blue', linestyle='-', label=f'MSE = {mse_fair:.2f}')
plt.xlabel('样本索引')
plt.ylabel('误差平方')
plt.title('误差平方分布 (一般模型)')
plt.legend()
plt.grid(True, alpha=0.3)# 子图 6: 误差平方分布 (差模型)
plt.subplot(2, 3, 6)
squared_errors_poor = (y_true_poor - y_pred_poor)**2
plt.bar(range(len(squared_errors_poor)), squared_errors_poor, color='red', alpha=0.7)
plt.axhline(y=mse_poor, color='blue', linestyle='-', label=f'MSE = {mse_poor:.2f}')
plt.xlabel('样本索引')
plt.ylabel('误差平方')
plt.title('误差平方分布 (差模型)')
plt.legend()
plt.grid(True, alpha=0.3)plt.tight_layout()
plt.show()
结果:
=== 示例 1: 模型预测效果很好 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [102 118 142 158 182 198 222 238]
误差: [-2 2 -2 2 -2 2 -2 2]
误差平方: [4 4 4 4 4 4 4 4]
均方误差 (MSE): 4.00 (万元²)=== 示例 2: 模型预测效果一般 ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [ 90 130 130 170 170 210 210 250]
误差平方: [100 100 100 100 100 100 100 100]
均方误差 (MSE): 100.00 (万元²)=== 示例 3: 模型预测效果很差 (有异常值) ===
真实值: [100 120 140 160 180 200 220 240]
预测值: [102 118 142 158 182 198 222 300]
误差平方: [ 4 4 4 4 4 4 4 3600]
均方误差 (MSE): 455.00 (万元²)=== 示例 4: MSE vs MAE (对异常值的敏感性) ===
模型 A 预测: [ 52 58 71 79 88 102]
模型 A - MSE: 4.00, MAE: 2.00
模型 B 预测: [ 51 59 70 81 89 150]
模型 B - MSE: 416.83, MAE: 9.17结论:- MAE: 模型B (9.17) > 模型A (2.00),但差距相对温和。- MSE: 模型B (416.83) >> 模型A (4.00),差距被显著放大!
这是因为 MSE 将模型 B 的大误差 (|100-150|=50) 平方成了 2500,
极大地拉高了整体 MSE 值,从而更强烈地惩罚了这种大错误。
关键点总结
- 核心指标: MSE 是回归问题的基石。许多回归算法(如线性回归)的优化目标就是最小化 MSE(或其变种)。
- 惩罚大误差: MSE 的核心特点是对大误差进行平方放大。一个 10 的误差贡献 100 到 MSE,而一个 50 的误差贡献 2500!这使得 MSE 非常适合需要避免大错误的场景。
- 单位是平方: MSE 的结果单位是目标变量单位的平方(如 万元²),这使得它不如 MAE 直观。为了解决这个问题,通常会使用 RMSE (Root Mean Squared Error, 均方根误差),即 RMSE = sqrt(MSE),它的单位就和目标变量一致了。
- 对异常值敏感: 由于平方操作,MSE 会受到异常值的极大影响。在数据有明显异常值时,MSE 可能不是一个好的整体性能指标,此时 MAE 可能更合适。
- 与 MAE 对比: MAE 关注平均误差,对异常值相对稳健;MSE 关注误差的平方均值,对大误差非常敏感。两者结合使用能更全面地评估模型。
总而言之,mean_squared_error 是一个强大的工具,尤其当你希望模型避免出现大的预测偏差时。记住,高 MSE 往往意味着模型中存在一些预测得非常差的点。