1050 筆資料、少數類只有 50 筆。三行 print 考三件事:macro(各類平權平均)、weighted(按樣本數加權)、recall(少數類抓回幾成)。實跑輸出 0.6465、0.9298、0.4——weighted 被佔 95.2% 的多數類支配,把少數類 F1 只有 0.3333 的慘況遮得乾乾淨淨。下半題考門檻:實跑機率模型從 0.5 降到 0.1,recall 0.271 → 0.712、誤報 3 → 93 筆——升的跟付出的一起看,才是完整的判讀。
少數類別標記為 1。執行下列程式後,輸出與門檻調整的判讀何者正確?
from sklearn.metrics import f1_score, recall_score # 拿出兩把評分尺 y_true = [0]*1000 + [1]*50 # 正解:1000 個 0 接 50 個 1 y_pred = [0]*950 + [1]*50 + [0]*30 + [1]*20 # 預測:四段對四格(下面解剖) print(round(f1_score(y_true, y_pred, average='macro'), 4)) # 各類平權平均 print(round(f1_score(y_true, y_pred, average='weighted'), 4)) # 按樣本數加權 print(round(recall_score(y_true, y_pred), 4)) # 預設只報正類(=1)的 recall
想像兩個班考同一份試:1000 人的大班考 96 分、50 人的小班只考 33 分。「全校表現」怎麼報?各班平權——(96+33)÷2 ≈ 64.65:小班的慘況佔一半版面,藏不住。按人頭平均——大班佔 95.2% 權重,算出來 ≈ 92.98:小班 50 個人被 1000 個人的好成績淹沒。
這正是 macro 與 weighted 的差別。而不平衡任務裡你在乎的通常就是那個小班(詐欺、罕病、流失客戶——少數類標記為 1)——所以本題的三個輸出裡,最誠實的是 macro 的 0.6465 與少數類 recall 的 0.4,最會「報喜」的是 weighted 的 0.9298。
recall_score 二元預設只報正類(pos_label=1)——本題就是少數類抓回幾成:20/50 = 0.4。點擊後出現漸進式說明:白話說明 → 說清楚一點 → 常見錯誤與考點。
點擊後出現漸進式說明。
六行,一行一行走完。右上角的「看位置」可以把這一行放回完整程式裡看。
from sklearn.metrics import f1_score, recall_score # 評估抽屜,一次拿兩件
sklearn.metrics 是評估工具的抽屜——系列第 2 頁(混淆矩陣)、第 3 頁(不平衡陷阱)都來過。這次拿 f1_score(precision 與 recall 的調和平均)與 recall_score(抓回率)。
y_true = [0]*1000 + [1]*50 # 清單乘法+串接:前 1000 筆是 0、後 50 筆是 1
[0]*1000 是清單乘法:把 [0] 複製 1000 份;+ 把兩段串接起來——共 1050 筆,前 1000 筆真實為 0(多數類)、後 50 筆真實為 1(少數類)。1000 : 50 = 20 : 1 的不平衡——題目說「少數類別標記為 1」,指的就是這 50 筆。
y_pred = [0]*950 + [1]*50 + [0]*30 + [1]*20 # 950 TN|50 FP|30 FN|20 TP
把它跟 y_true 逐位置對齊就是解題鑰匙:前 1000 個位置真實為 0——其中 950 筆預測 0(TN)、50 筆預測 1(FP 誤報);後 50 個位置真實為 1——其中 30 筆預測 0(FN 漏抓)、20 筆預測 1(TP 抓到)。四段依序就是 TN、FP、FN、TP——考場 30 秒拆段法,02 節實驗室把四格攤開。
[0]*a + [1]*b + ... 寫法,先把段落長度抄成 2×2。print(round(f1_score(y_true, y_pred, average='macro'), 4)) # (0.9596 + 0.3333) ÷ 2 = 0.6465
先各類算自己的 F1:類 0 是 0.9596、類 1 只有 0.3333;macro 把兩個數平權平均——(0.9596+0.3333)÷2 = 0.6465。小班考砸,全校成績直接被拖下來——藏不住。
print(round(f1_score(y_true, y_pred, average='weighted'), 4)) # 0.952×0.9596 + 0.048×0.3333 = 0.9298
同樣的兩個班級 F1,改用樣本數當權重:類 0 佔 1000/1050 = 95.2%、類 1 只佔 4.8%——0.952 × 0.9596 + 0.048 × 0.3333 = 0.9298。少數類在這個平均裡幾乎沒有發言權——這就是答案 A 說的「weighted F1 受多數類別支配」。
print(round(recall_score(y_true, y_pred), 4)) # 20 ÷ 50 = 0.4:50 個真正例只抓到 20 個
二元的 recall_score 沒指定就只報正類(pos_label=1):真實為 1 的 50 筆裡抓到 20 筆——20/50 = 0.4。分母是「真實為 1」的 50,不是「預測為 1」的 70——把分母搞混,就會算出 20/70 ≈ 0.2857,那是 precision——選項 C 的死因預告。
把第 3 行的四段填進 2×2(本站實跑 confusion_matrix 驗證)。點任一格,看它餵給哪些指標:
| 類別 | precision | recall | F1 | support |
|---|---|---|---|---|
| 類 0(多數) | 0.9694 | 0.9500 | 0.9596 | 1000 |
| 類 1(少數=正類) | 0.2857 | 0.4000 | 0.3333 | 50 |
類 0 的 F1 = 0.9596、類 1 的 F1 = 0.3333——average 參數決定怎麼把兩個數揉成一個:
答案 A 的下半句要親手拉過才有感。本站訓練一個機率模型(1050 筆測試、59 個正例——跟題目同等級的不平衡),把「判為 1」的門檻從 0.9 一路降到 0.05:
選項 D 說「weighted 必定小於 macro,因為正類樣本比較少」。開庭,兩件展品:
這類題目考場上照 SOP 走,30 秒填完四格:
| 步驟 | 動作 | 本題 |
|---|---|---|
| ① 對段落 | y_pred 的段落長度照抄,對齊 y_true 的分界 | 950|50|30|20 |
| ② 填四格 | 真實 0 的段 → TN、FP;真實 1 的段 → FN、TP | TN950 FP50 FN30 TP20 |
| ③ 算類 1 | P=TP/(TP+FP)、R=TP/(TP+FN)、F1=調和 | 0.2857 / 0.4 / 0.3333 |
| ④ 算類 0 | 同法(把 0 當正類) | 0.9694 / 0.95 / 0.9596 |
| ⑤ 揉平均 | macro 平權;weighted 乘 support 佔比 | 0.6465 / 0.9298 |
本頁也是站上不平衡評估三部曲的完結篇:第 2 頁(混淆矩陣與 recall)教四格與兩把尺、第 3 頁(不平衡評估陷阱)教「全猜 0 也有 95% 準確率」的假象與 baseline 紀律、本頁教怎麼把各類成績「揉成一個數」而不騙到自己——macro 誠實、weighted 報喜、micro 就是 accuracy。三頁合體,就是科目二不平衡評估的完整武器庫。
三個數字實跑全中:macro = (0.9596+0.3333)/2 = 0.6465、weighted = 0.952×0.9596+0.048×0.3333 = 0.9298(多數類佔 95.2% 權重——「支配」的數學本體)、recall = 20/50 = 0.4。門檻判讀也對:實跑降門檻 0.5 → 0.1,recall 0.271 → 0.712、誤報 3 → 93 筆——「通常可提高」「可能增加」的措辭嚴謹又符合實測。
實跑三個輸出是 0.6465、0.9298、0.4——沒有一個是 0.95。macro 與 weighted 只有在各類表現一樣好或各類樣本數相同時才會相等;不平衡+表現懸殊的本題,兩者差了 0.28。「永遠相同」與第 3 頁的「準確率 95% 假象」犯同一個錯:拿多數類的太平掩蓋少數類的災情。
兩刀斃命:① 20/70 的 70 是「預測為 1」的筆數——那是 precision(0.2857);recall 的分母是「真實為 1」的 50,答案 0.4。② 降門檻讓更多樣本被判 1——TP 變多、FP 通常漲更兇:實跑 precision 從 1.000 一路掉到 0.177。「一定同時提高」與實測完全相反。
方向整個說反:本題 weighted(0.9298)遠大於 macro(0.6465)——正類樣本少,代表它在 weighted 裡幾乎沒發言權(4.8%),少數類考砸時 weighted 反而被多數類拉高。誰大誰小取決於「哪一類表現好」:小類考好時才會 weighted < macro(實跑 recall 版反例:0.5238 < 0.75)。「必定」二字,兩個方向都站不住。
再看一次同一段程式。這次你知道三個數字各自在報告什麼了。
少數類別標記為 1。執行下列程式後,輸出與門檻調整的判讀何者正確?
y_pred = [0]*950 + [1]*50 + [0]*30 + [1]*20 # TN 950|FP 50|FN 30|TP 20 print(round(f1_score(y_true, y_pred, average='macro'), 4)) # 平權:0.6465(誠實) print(round(f1_score(y_true, y_pred, average='weighted'), 4)) # 按人頭:0.9298(被多數類拉高) print(round(recall_score(y_true, y_pred), 4)) # 正類抓回率:20/50 = 0.4
八題,全部都是本題的延伸。答錯會直接告訴你錯在哪。
「F1 的平均方式」是中級科目二大數據處理分析與應用的高頻考點,常跟門檻調整合併出題。最常見的六種問法:① 給 y_true/y_pred 問三個輸出(本題這種——拆段填四格、逐類算、再揉平均);② 問 macro 與 weighted 的差別(平權 vs 按 support 加權;不平衡+表現懸殊時分歧最大);③ 問哪個指標會被多數類支配(weighted、micro/accuracy);④ 給 20/70 與 20/50 問誰是 precision 誰是 recall(分母口訣);⑤ 問降低門檻的效果(recall 升、precision 通常降、FP 增);⑥ 問在乎少數類時該看什麼(macro、各類分開、PR 曲線)。一句口訣:macro 平權、weighted 按人頭;P 分母是預測、R 分母是真實;降門檻——多抓也多冤。
都從「逐類 F1」出發。macro:各類 F1 直接平均——本題 (0.9596+0.3333)/2 = 0.6465,每類一票,票票等值。weighted:各類 F1 乘上樣本佔比(support 權重)再加總——0.952×0.9596+0.048×0.3333 = 0.9298,人多票多。micro:不先分類別,把全部 TP/FP/FN 加總後直接算——在單標籤情境下恆等於 accuracy(實跑 0.9238)。記法:macro 像「各班平均分再平均」、weighted 像「全校按人頭平均」、micro 像「全校總答對率」。三者在類別均衡且表現一致時會靠攏,不平衡+表現懸殊時分裂——分裂的幅度本身就是「少數類考差」的訊號。
因為權重幾乎全在考得好的那班。類 0 佔 1000/1050 = 95.2% 的權重、F1 高達 0.9596;類 1 只佔 4.8%、F1 慘到 0.3333。weighted = 0.952×0.9596+0.048×0.3333——第二項只貢獻 0.016,等於少數類「幾乎沒投票」。macro 則強迫兩班各佔 50%,0.3333 的災情直接把平均拖到 0.6465。差距 0.28 不是誤差,是訊息:看到 weighted 遠高於 macro,第一反應就該是「少數類出事了」——跟第 3 頁「準確率 95% 但全猜 0」是同一族的假象。
看分母。precision = TP/(TP+FP) = 20/70——分母 70 是「預測為 1」的全部(抓到的 20+冤枉的 50):喊有病的裡面,幾個真的病?→ 0.2857。recall = TP/(TP+FN) = 20/50——分母 50 是「真實為 1」的全部(抓到的 20+漏掉的 30):真的病的裡面,抓到幾個?→ 0.4。選項 C 把 20/70 說成 recall,就是分母抓錯。口訣:P 直欄(預測那一欄)、R 橫列(真實那一列);或「P 問報案準不準、R 問壞人漏不漏」。這對兄弟在第 2 頁有完整動畫,本頁是速記版。
門檻是「機率多高才判 1」的線。降門檻 → 更多樣本被判 1 → 真正例更容易被涵蓋(TP↑、FN↓ → recall 上升),但更多正常樣本也被掃進來(FP↑ → precision 通常下降)。本站實跑(1050 筆、59 正例的機率模型):門檻 0.9→0.5→0.2→0.05,recall 0.068→0.271→0.525→0.797,FP 0→3→32→218,precision 1.000→0.842→0.492→0.177——三條線的方向一目了然。所以答案 A 用「通常可提高 recall、可能增加誤報」是嚴謹的措辭;C 的「一定同時提高 precision」與實測完全相反。極端情況(模型把正例排序得極好)precision 可能短暫持平,但「一定提高」永遠是錯的。
不是。0.5 只是 predict() 的預設值,不是最佳值。實跑本頁的模型:F1 最高點在門檻 0.2(0.508),比 0.5 的 0.410 好一截——因為不平衡資料下正類機率普遍偏低,0.5 太嚴。實務決定門檻看成本:漏抓成本高(詐欺、罕病、設備故障)→ 門檻往低調,用 precision 換 recall;誤報成本高(誤鎖帳戶、騷擾客戶)→ 往高調。工具:PR 曲線/ROC 曲線把所有門檻的表現一次畫出來(站內 PR 曲線、ROC/AUC 頁),或直接用 precision_recall_curve 找 F1 最大的門檻。考點:「調門檻不用重新訓練模型」——只是改判讀 predict_proba 的方式。
都不一定——方向由「哪一類表現好」決定。大類表現好(本題):weighted 被大類拉高 → weighted > macro(0.9298 > 0.6465)。小類表現好:weighted 被大類拉低 → weighted < macro——實跑反例(recall 版):類 0 抓對一半、類 1 全抓到,macro recall = (0.5+1.0)/2 = 0.75,weighted = 0.952×0.5+0.048×1.0 = 0.5238。選項 D 的錯有兩層:方向說反(本題就是活反例)、歸因錯誤(「正類樣本少」只決定權重小,不決定誰大)。考場看到「必定/永遠/一定」,先找反例——本系列第三次用這招殺選項。
三部曲各管一段。第 2 頁(混淆矩陣與 recall):建地基——四格怎麼填、precision/recall 分母口訣、為什麼有兩把尺。第 3 頁(不平衡評估陷阱):立紀律——「全猜 0 也有 95% 準確率」的 baseline 假象、accuracy 在不平衡下不可信、該建立什麼基準。本頁:收尾——各類成績算出來之後,怎麼「揉成一個數」而不騙到自己(macro 誠實、weighted 報喜、micro=accuracy),以及門檻這顆旋鈕怎麼轉。連起來就是科目二不平衡評估的完整答題流程:填四格 → 算兩把尺 → 選對平均 → 需要時調門檻。