專項練習 · 10 分鐘閱讀

Python 模型評估練習:不只看準確率

評估是模型與決策相遇的地方。一個準確率數字可能掩蓋「永遠找不到關心類別」的分類器。這些練習先計算混淆矩陣,再從中推導指標。

先劃分,再看結果

在選擇特徵或門檻值前留出樣本。固定劃分容易復現;對有序資料,帶固定種子的打亂劃分通常更好。絕不要在測試集上調參。

rows = list(range(10))
cut = 7
train, test = rows[:cut], rows[cut:]
print(len(train), len(test))
print(test)

固定的留出集

構造混淆矩陣

根據真實和預測標籤統計真正例、真負例、假正例和假負例。計算比例前先列印計數;例外的指標往往由一個格子解釋。

actual = [1, 1, 0, 0]
predicted = [1, 0, 0, 1]
tp = sum(a == 1 and p == 1 for a, p in zip(actual, predicted))
tn = sum(a == 0 and p == 0 for a, p in zip(actual, predicted))
fp = sum(a == 0 and p == 1 for a, p in zip(actual, predicted))
fn = sum(a == 1 and p == 0 for a, p in zip(actual, predicted))
print(tp, tn, fp, fn)

先看四個格子

推導精準率、召回率和 F1

精準率是 tp / (tp + fp),召回率是 tp / (tp + fn),F1 是兩者的調和平均。使用防除零的輔助函式,避免「沒有預測正例」的分類器讓報告崩潰。

tp, fp, fn = 8, 2, 4
precision = tp / (tp + fp) if tp + fp else 0.0
recall = tp / (tp + fn) if tp + fn else 0.0
f1 = 2 * precision * recall / (precision + recall) if precision + recall else 0.0
print(round(precision, 2), round(recall, 2), round(f1, 2))

三個相關數字

與簡單基線比較

類別不平衡時,全部預測為負也可能有高準確率。把模型與該基線比較,並檢查每個類別的召回率。一個從不預測少數類的模型,不會因為 95% 準確率就有用。

actual = [0] * 95 + [1] * 5
predicted = [0] * 100
accuracy = sum(a == p for a, p in zip(actual, predicted)) / len(actual)
print(round(accuracy, 2))
print(sum(1 for a, p in zip(actual, predicted) if a == 1 and p == 1))

準確率不夠

移動門檻值,觀察權衡

分類器分數只有在門檻值之後才變成標籤。提高門檻值通常減少假正例、增加假負例。門檻值應根據驗證資料和真實錯誤代價選擇。

scores = [0.9, 0.6, 0.4, 0.3]
for threshold in (0.5, 0.7):
    predicted = [1 if score >= threshold else 0 for score in scores]
    print(threshold, predicted)

這是決策,不是事實

你的練習清單

常見問題

準確率還是 F1?

取決於假正例和假負例的代價。應報告多個指標和類別比例,而不是用一個數字掩蓋權衡。

可以用測試集選門檻值嗎?

不可以。決策使用驗證資料,最後再在測試集上報告一次結果。

多少分算好?

沒有通用數字。應與基線、可用的人工表現,以及應用中的錯誤代價比較。

練習模型評估

12 道題,覆蓋資料劃分、混淆矩陣、精準率、召回率、F1、類別不平衡和門檻值。

打開練習

繼續閱讀: