1、常用的模型分類評價指標#
準確率 Accuracy#
準確率:預測正確的結果占總樣本的百分比
code
from sklearn.metrics import accuracy_score
y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
accuracy_score(y_true, y_pred)
缺點
樣本不平衡時準確率會失效,比如判斷瀏覽購物網站是否會購買,100 個瀏覽用戶也許只有 1 個會購買,那麼模型無腦拍不會購買,準確率有 99%
1️⃣ 處理樣本不平衡 :重採樣、欠採樣、過採樣 等
2️⃣ 更換合適指標: F1-Score ,它不僅考慮模型預測的錯誤數量,還考慮錯誤類型
混淆矩陣#
看對角線
code
import matplotlib.pyplot as plt
import scikitplot as skplt
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
X, y = load_digits(return_X_y=True)
clf = RandomForestClassifier(n_estimators=5, max_depth=5, random_state=1)
clf.fit(X, y)
clf.score(X, y)
pred = clf.predict(X)
skplt.metrics.plot_confusion_matrix(y, pred, normalize=True)
plt.show()
二分類對角線衍生指標#
-
真正例 (True Positive, TP):被模型預測為正的正樣本;
-
假正例 (False Positive, FP):被模型預測為正的負樣本;
-
假負例 (False Negative, FN):被模型預測為負的正樣本;
-
真負例 (True Negative, TN):被模型預測為負的負樣本;
-
精確率 Precision= TP/(TP+FP)
-
召回率 Recall=TP/(TP+FN)
-
F1 score=2*(P * R)/(P+R)
精確率 Precision#
模型預測為 1,真正是 1 所占的百分比
案例:
-
在預測股票的時候,我們更關心精確率,即我們預測升的那些股票裡,真的升了有多少,因為那些我們預測升的股票都是我們投錢的。
-
比如對於罪犯的預測,我們希望預測結果是非常準確的,即使放過了一些真正的罪犯,也不能錯怪一個好人
code
from sklearn.metrics import precision_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
# None 每個類各自精確率(不平均)
precision_score(y_true, y_pred, average=None)
# [0.375 1. ]
# 'macro' 每類精確率的平均(不加權)
precision_score(y_true, y_pred, average='macro')
# (0.375 + 1.)/2 = 0.6875
# 'weighted' 按每類樣本數加權的平均精確率
precision_score(y_true, y_pred, average='weighted')
# 0.375*0.3+1*0.7 = 0.8125
# 'micro' 全部樣本總體精確率
precision_score(y_true, y_pred, average='micro')
# 等於Accuracy 0.5
accuracy_score(y_true, y_pred)
# 0.5
召回率 Recall#
真是 1 的樣本,再次被模型召回的概率,也叫查全率
案例:
-
假如一共發生了 10 次地震,我們情願發出 1000 次警報,這樣能把這 10 次地震都涵蓋進去(此時 recall 是 100%,precision 是 1%),也不要發出 100 次警報,其中有 8 次地震給預測到了,但漏了 2 次(此時 recall 是 80%,precision 是 8%)
-
而在預測病患的場景下,我們更關注召回率,即真的患病的那些人裡我們預測錯了情況應該越少越好,因為真的患病如果沒有檢測出來,結果其實是很嚴重的,之前那個無腦的算法,召回率就是 0。
code
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
recall_score(y_true, y_pred, average=None)
# 3個0都被召回了,7個1只有2個被召回 [1. 0.28571429]
recall_score(y_true, y_pred, average='macro')
# (1. + 0.28571429)/2 = 0.6428571428571428
recall_score(y_true, y_pred, average='weighted')
# 1*0.3+0.28571429*0.7 = 0.5
recall_score(y_true, y_pred, average='micro')
# 等於Accuracy =0.5
accuracy_score(y_true, y_pred)
# 0.5
為什麼 precision 和 recall 矛盾#
1️⃣ 如果想要更高的 recall,那麼就要讓模型的預測能覆蓋到更多的樣本,但是這樣模型就更有可能犯錯,也就是說 precision 會比較低。
2️⃣ 如果模型很保守,只能檢測出它很確定的樣本,那麼其 precision 會很高,但是 recall 會相對低。
F1 score#
調和平均數#
- 什麼是調和平均數?
🔴 由於它是根據變量的倒數計算的,所以又稱倒數平均數
-
一段路程 2 公里,前 1 公里速度 20km/h,後 1 公里速度 10km/h,求平均速度?
簡單平均:
(20+10)/2 = 15按時間加權:
總時間 = (1/20 + 1/10)= 0.15
第一公里時間:1/20=0.05 權重 33%
第二公里時間:1/10=0.1 權重 66%
平均時間 = 20 * 33% + 10 * 66% = 13.33
調和平均
為什麼 F1 要用調和平均數?#
- 如果簡單平均,P=0.8,R=0.8 與 P=0.7,R=0.9 的算術平均一樣都是 0.8,類似預測與召回是可替代的。
- 調和平均相當於添加了懲罰機制:越高的數值給越低的權重(比如上面例子中,20 速度的權重只有 33%)
從而避免在使用算術平均時,出現由於其中一個很高,另一個較低,造成的均值虛高的現象。(假設 p 和 r 一個是 1.0 一個是 0.1, 算術平均會接近 0.5 而調和平均接近 0.2)
F1 值背後的思想就是,precision 和 recall 二者都平平的算法比一個指標巨好另一個指標巨差的算法可靠
總結:兩個好才是真的好
code
from sklearn.metrics import f1_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
f1_score(y_true, y_pred, average=None)
# [0.54545455 0.44444444]
f1_score(y_true, y_pred, average='macro')
# (0.54545455+0.44444444)/2 = 0.4949494949494949
f1_score(y_true, y_pred, average='weighted')
# 0.54545455*0.3+0.44444444*0.7 = 0.47474747474747475
f1_score(y_true, y_pred, average='micro')
# 等於Accuracy 0.5
accuracy_score(y_true, y_pred)
# 0.5