National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 13

分類的評估

混淆矩陣、精確率、召回率與 ROC
Interaction實作 30 minute(s)

Learning Objectives

  • 用 numpy 算出混淆矩陣的四個數字,再算精確率、召回率與 F1
  • 把模型的準確率和「全猜最多的類別」比較,說明準確率為什麼可能騙人
  • 調整閾值,說明精確率與召回率怎麼互相牽動,並依錯誤的代價選擇閾值
  • 讀懂 ROC 曲線與 AUC,說明它們和閾值的關係

準確率 85%,算好嗎?

假設學校想提早找出「這學期可能需要學業輔導」的同學,模型的準確率是 85%。聽起來不錯,但如果只有 15% 的同學真的需要輔導,那麼一個人都不抓、全部猜「不需要」,準確率也是 85%。

分類的錯誤有兩種,而且代價通常不一樣:

  • 漏抓:真的需要協助的同學,模型說不需要。
  • 誤報:不需要協助的同學,模型說需要。

準確率把這兩種錯誤混在一起算,看不出模型到底錯在哪裡。這一課要把它們拆開:先親手數出四個數字,再看怎麼用它們評估模型、怎麼選擇判定的門檻。

逐步看:用 numpy 數出四個數字

十位同學,1 表示「需要輔導」,我們稱它為正類(positive)。注意 tp、fn、fp、tn 每一行都是兩個布林陣列做 &(而且),再數有幾個 True。

混淆矩陣與三個指標

把四個數字排成表,就是混淆矩陣(confusion matrix)。scikit-learn 的 confusion_matrix 輸出的排法是這樣(列是實際、欄是判定,類別由小到大):

判定 0 判定 1
實際 0 TN FP(誤報)
實際 1 FN(漏抓) TP
指標 公式 回答的問題
精確率(precision) TP/(TP+FP) 模型說「是」的那些,有多少真的是?
召回率(recall) TP/(TP+FN) 真的是的那些,模型抓到多少?
F1 2×精確率×召回率/(精確率+召回率) 想要一個數字同時反映兩者時用

要記住精確率和召回率的差別,就看分母:精確率的分母是模型判定的人,召回率的分母是實際符合的人。

正類是誰由你決定:同一份資料,把「需要輔導」當正類或把「不需要」當正類,這三個數字都會不同。scikit-learn 的二元分類預設把標籤 1 當正類(pos_label=1)。

逐步看:準確率和基準比一比

這裡用 risk.csv:1000 位同學的學業與生活紀錄,at_risk 是 1 表示需要輔導(程式產生的模擬資料,不是任何學校的真實資料)。看輸出的兩個準確率,再看混淆矩陣和報告。

閾值:判定的門檻可以調

羅吉斯迴歸輸出的是機率,predict 只是用 0.5 當門檻把它變成 0 或 1。這個門檻叫閾值(threshold),0.5 只是預設值,不是一定要用它。

  • 閾值調低:比較容易判定為正類。漏抓變少(召回率上升),但誤報通常變多(精確率通常下降)。
  • 閾值調高:只有很有把握才判定。誤報變少,但漏抓變多。

沒有一個閾值同時對兩者都最好,要看哪一種錯誤的代價比較高。學業預警如果只是多一封關心的信,漏抓的代價就比誤報高,閾值可以低一些;如果每次判定都要安排老師面談一小時,誤報的代價就不小。

逐步看:同一個模型,換閾值

模型完全不用重新訓練,只是用不同的門檻看同一批機率。注意每一輪的判定人數、精確率、召回率怎麼變。

互動練習:拉閾值,看錯誤怎麼交換

資料就是上面的 250 筆測試資料,分數是同一個羅吉斯迴歸算出來的機率。上方長條的橫軸是分數,往上是實際高風險的同學、往下是實際沒有風險的同學,縱向尺度相同,所以看得出兩邊人數差很多。

這裡為了看懂指標,直接在測試資料上拉閾值;真的要決定閾值時要用驗證資料或交叉驗證,第 15 課有範例。

ROC 曲線與 AUC

每個閾值都對應一組結果。把所有閾值的結果一次畫出來,就是 ROC 曲線:

  • 橫軸是假陽性率(false positive rate)=FP/(FP+TN):沒事的人被誤報的比例。
  • 縱軸是召回率:需要協助的人被抓到的比例。

曲線越往左上角越好。隨機亂猜會落在對角線上。AUC 是曲線下的面積:它等於「隨機抽一位正類、一位負類,模型給正類的分數比較高」的機率。AUC 0.5 是亂猜,1.0 是可以完全分開。

AUC 不用先決定閾值,適合比較模型能不能把兩類排開;但實際上線時還是要選一個閾值,AUC 高不代表在你選的閾值下召回率或精確率就夠用。

逐步看:畫 ROC 曲線

roc_curve 要的是分數(機率),不是 0 或 1 的判定,這是最常見的錯誤。

實作:寫一個 metrics 函數

完成 metrics(y_true, y_pred):用 numpy 算出 TP、FP、FN,回傳 (精確率, 召回率, F1),每個數字四捨五入到小數 3 位。

分母是 0 時(例如沒有人被判定為 1)要回傳 0.0,不可以出現除以零的錯誤。第三個測試就是這種情況。

你的輸出
預期輸出

小測驗:分類的評估

1.

下面程式會印出什麼?

import numpy as np
y = np.array([1, 1, 0, 0, 0, 1])
p = np.array([1, 0, 0, 1, 0, 1])
tp = ((y == 1) & (p == 1)).sum()
fp = ((y == 0) & (p == 1)).sum()
print(int(tp), int(fp))
2.

資料裡 95% 是負類,模型的準確率是 95%。最恰當的解讀是?

3.

垃圾郵件過濾器把垃圾郵件當正類。使用者最不能接受「正常信被丟進垃圾桶」,你最該盯著哪個指標?

4.

其他都不變,把閾值從 0.5 調低到 0.2,下面哪一個一定成立?

5.

confusion_matrix 印出 [[204, 8], [29, 9]]。模型漏抓了幾位實際是正類的人?

6.

模型的 AUC 是 0.5,代表什麼?

第 1 次作答

重點整理

  • 準確率一定要和基準(全猜最多的類別)比較;資料不平衡時,它可能幾乎沒有資訊。
  • 混淆矩陣拆出 TP、FP、FN、TN。精確率看模型判定的人裡有多少對,召回率看實際符合的人被抓到多少,F1 是兩者的調和平均。
  • 閾值可以調:調低時召回率上升、精確率通常下降。要用哪個閾值,看兩種錯誤的代價。
  • ROC 曲線畫出所有閾值的結果,AUC 衡量排序能力,兩者都要傳分數而不是判定結果。
  • 這一課的數字都來自切一次的測試資料,250 筆裡差一兩筆就會讓指標變動不少。下一課用交叉驗證得到更穩定的估計,也解決第 8 課留下的問題:不能用測試資料挑超參數。
這一課完成了!
Next lesson:交叉驗證與超參數搜尋
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。