banner
Fight4354

Fight4354

AI,Chem,Science,Study,Share,Hobby,LLM,Life,Sport

模型評價指標

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()

image

二分類對角線衍生指標#

image

  • 真正例 (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#

Precision=TPTP+FPPrecision =\frac{\mathrm{TP}}{\mathrm{TP}+\mathrm{FP}}

image

模型預測為 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#

Recall=TPTP+FNRecall =\frac{\mathrm{TP}}{\mathrm{TP}+\mathrm{FN}}

image

真是 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#

1F1=12(1 precision +1 recall )\frac{1}{F 1}=\frac{1}{2}\left(\frac{1}{\text { precision }}+\frac{1}{\text { recall }}\right)
F1=21precision+1recallF 1 =\frac{2}{\frac{1}{precision}+\frac{1}{recall}}

調和平均數#

  • 什麼是調和平均數?
H=n1x1+1x2++1xnH=\frac{n}{\frac{1}{x_{1}}+\frac{1}{x_{2}}+\ldots+\frac{1}{x_{n}}}

🔴 由於它是根據變量的倒數計算的,所以又稱倒數平均數

  • 一段路程 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

    調和平均

平均速度=總路程總時間平均速度 = \frac{總路程}{總時間}
平均速度=2120+110=13.33平均速度 = \frac{2}{\frac{1}{20}+\frac{1}{10}}=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
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。