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
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。