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使用的简单示例: ```python 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() ``` 结果: ```python === 示例 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\]函数的小例子: ```python 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]) # 最后一个预测为 300 me_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|=50 print(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() ``` 结果: ```python === 示例 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函数的小例子: ```python 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]) # 最后一个预测为 300 mae_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() ``` 结果: ```python === 示例 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函数的小例子: ```python 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]) # 最后一个预测为 300 mse_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() ``` 结果: ```python === 示例 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 往往意味着模型中存在一些预测得非常差的点。