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 都要防除零。
- 與多數類基線比較。
- 門檻值根據驗證資料和錯誤代價選擇。
常見問題
準確率還是 F1?
取決於假正例和假負例的代價。應報告多個指標和類別比例,而不是用一個數字掩蓋權衡。
可以用測試集選門檻值嗎?
不可以。決策使用驗證資料,最後再在測試集上報告一次結果。
多少分算好?
沒有通用數字。應與基線、可用的人工表現,以及應用中的錯誤代價比較。
練習模型評估
12 道題,覆蓋資料劃分、混淆矩陣、精準率、召回率、F1、類別不平衡和門檻值。
繼續閱讀: