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, R2)結合使用。
總而言之,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^?)=nsamples?1?i=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、R2 等指標一起使用來全面評估模型。
總而言之,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^?)=nsamples?1?i=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} (萬元2)") # 注意單位是平方
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} (萬元2)")
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} (萬元2)")
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)=== 示例 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 (萬元2)=== 示例 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 (萬元2)=== 示例 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 的結果單位是目標變量單位的平方(如 萬元2),這使得它不如 MAE 直觀。為了解決這個問題,通常會使用 RMSE (Root Mean Squared Error, 均方根誤差),即 RMSE = sqrt(MSE),它的單位就和目標變量一致了。
- 對異常值敏感: 由于平方操作,MSE 會受到異常值的極大影響。在數據有明顯異常值時,MSE 可能不是一個好的整體性能指標,此時 MAE 可能更合適。
- 與 MAE 對比: MAE 關注平均誤差,對異常值相對穩健;MSE 關注誤差的平方均值,對大誤差非常敏感。兩者結合使用能更全面地評估模型。
總而言之,mean_squared_error 是一個強大的工具,尤其當你希望模型避免出現大的預測偏差時。記住,高 MSE 往往意味著模型中存在一些預測得非常差的點。