简述
直观地说,精确率是指分类器不将负样本标记为正样本的能力,召回率是指分类器查找所有正样本的能力。
而F值(F1F_1F1和FβF_{\beta}Fβ值)则可以解释为精确率和召回率的加权调和平均值。
FβF_{\beta}Fβ值的取值范围为[0,1],在1处表示模型效果最好,在0处表示模型效果最差。
当β=1\beta =1β=1时,F1F_1F1和FβF_{\beta}Fβ等价,表示精确率和召回率同等重要。
关于精确率、召回率和F值的详细内容,请参考我的另一篇博文:十分钟掌握分类算法的评估指标。
precision_recall_curve:根据真实标签和分类器通过改变决策阈值给出的分数,计算精度率-召回率曲线。
average_precision_score:根据预测分数计算平均精确率(AP),该值介于 0 和 1 之间,越高越好。 AP被定义为
AP=∑n(Rn−Rn−1)Pn\text{AP} = \sum_n (R_n - R_{n-1}) P_nAP=n∑(Rn−Rn−1)Pn
其中,PnP_nPn 和 RnR_nRn 是第 n 个阈值的准确率和召回率。
这种实现是没有插值的,不同于用梯形规则计算precision-recall曲线下的面积,后者使用线性插值,可能过于乐观。
注意:此实现仅限于二分类任务或多标签分类任务。
以下几个函数允许您计算精确率、召回率和F值分数:
函数 | 说明 |
average_precision_score (y_true, y_score, *) |
根据预测分数计算平均精确率 (AP) |
f1_score (y_true, y_pred, *[, labels, …]) |
计算F1值 |
fbeta_score (y_true, y_pred, *, beta[, …]) |
计算F-beta值 |
precision_recall_curve (y_true, probas_pred, *) |
计算不同概率阈值下的精确率召回率对 |
precision_recall_fscore_support (y_true, …) |
计算每个类的精确率、召回率、F值和真实值的标签数量 |
precision_score (y_true, y_pred, *[, labels, …]) |
计算精确率 |
recall_score (y_true, y_pred, *[, labels, …]) |
计算召回率 |
注意:
precision_recall_curve
函数仅限于二分类场景。average_precision_score
函数仅适用于二分类和多标签分类场景。
二分类场景
在二分类任务中,术语“正”和“负”是指分类器的预测,术语“真”和“假”是指该预测结果是否对应于外部(实际值)判断, 鉴于这些定义,我们可以制定下表:
在这种情况下,精确率、召回率和 F值的公式如下:
precision=tptp+fp,\text{precision} = \frac{tp}{tp + fp},precision=tp+fptp,
recall=tptp+fn,\text{recall} = \frac{tp}{tp + fn},recall=tp+fntp,
Fβ=(1+β2)precision×recallβ2precision+recall.F_\beta = (1 + \beta^2) \frac{\text{precision} \times \text{recall}}{\beta^2 \text{precision} + \text{recall}}.Fβ=(1+β2)β2precision+recallprecision×recall.
示例代码:
from sklearn import metrics import numpy as np import pprint y_pred = [0, 1, 0, 0] y_true = [0, 1, 0, 1] # average参数的默认值为binary, "binary"表示用于二分类 print(metrics.precision_score(y_true, y_pred)) print(metrics.precision_score(y_true, y_pred, average='binary')) print(metrics.recall_score(y_true, y_pred)) print(metrics.recall_score(y_true, y_pred, average='binary')) print(metrics.f1_score(y_true, y_pred)) print(metrics.f1_score(y_true, y_pred, average='binary')) print(metrics.fbeta_score(y_true, y_pred, beta=0.5)) print(metrics.fbeta_score(y_true, y_pred, beta=1)) print(metrics.fbeta_score(y_true, y_pred, beta=2)) print("------------------") pprint.pprint(metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5)) print("------------------") y_true = np.array([0, 0, 1, 1]) y_scores = np.array([0.1, 0.4, 0.35, 0.8]) # PR曲线实则是以precision(精准率)和recall(召回率)这两个为变量而做出的曲线,其中recall为横坐标,precision为纵坐标。 # 设定一系列阈值,计算每个阈值对应的recall和precision,即可计算出PR曲线各个点。 precision, recall, threshold = metrics.precision_recall_curve(y_true, y_scores) print("", precision, "\n",recall,"\n", threshold) # 其中,y_true是正确标签,y_score是概率输出值,thresholds是阈值, # 当y_score>=thresholds,则预测为正样本,当y_score<thresholds,则预测为负样本。 # 注意,输出的precision和recall最后一个值分别为1和0,并且没有对应的阈值。 # 该例子中,在实际的数据集中,正样本实际数量为2个,负样本实际数量为2个。 # 当index=0,thresholds[index]=0.35,此时预测的标签为[0,1,1,1], # tp=2,fp=1,fn=0,所以precision=0.67,recall=1 # 当index=1,thresholds[index]=0.4,此时预测的标签为[0,1,0,1], # tp=1,fp=1,fn=1,所以precision=0.5,recall=0.5 # 当index=2,thresholds[index]=0.8,此时预测的标签为[0,0,0,1], # tp=1,fp=0,fn=1,所以precision=1,recall=0.5 print("------------------") print(metrics.average_precision_score(y_true, y_scores)) 复制代码
运行结果:
1.0 1.0 0.5 0.5 0.6666666666666666 0.6666666666666666 0.8333333333333334 0.6666666666666666 0.5555555555555556 ------------------ (array([0.66666667, 1. ]), array([1. , 0.5]), array([0.71428571, 0.83333333]), array([2, 2])) ------------------ [0.66666667 0.5 1. 1. ] [1. 0.5 0.5 0. ] [0.35 0.4 0.8 ] ------------------ 0.8333333333333333 复制代码
多分类与多标签场景
在多分类和多标签分类任务中,精确率、召回率和F值的概念可以独立应用于每个标签。
这里有几种遍历标签组合结果方法,由average_precision_score
(仅限多标签)、f1_score
、fbeta_score
、precision_recall_fscore_support
、precision_score
和recall_score
函数的average
(平均)参数指定。 请注意,如果包含所有标签,则多类设置中的“微”平均将产生精度、召回率,并且这些都与准确度相同。 另请注意,“加权”平均可能会产生不在精度和召回率之间的 F 分数。
请注意:如果包含所有标签,则多分类场景中设置的“micro”平均,产生的精确率、召回率和F值,这些都与准确率相同。
同时也请注意:“weighted”平均可能会产生不在精度和召回率之间的F分数。
为了使这更加清晰,请参考以下符号:
- yyy表示预测对(sample,label)(sample, label)(sample,label)的集合(分类器的预测值)
- y^\hat{y}y^表示真实对(sample,label)(sample, label)(sample,label)的集合(实际值)
- LLL表示标签集
- SSS表示样本集
- ysy_sys表示yyy的子集,样本sss
- yly_lyl表示yyy的子集,标签lll
- 同样的,y^s\hat{y}_sy^s和y^l\hat{y}_ly^l是y^\hat{y}y^的子集
- P(A,B):=∣A∩B∣∣A∣P(A, B) := \frac{\left| A \cap B \right|}{\left|A\right|}P(A,B):=∣A∣∣A∩B∣ ,表示精确率,其中B为真实为正的集合,A为预测为正的集合
- R(A,B):=∣A∩B∣∣B∣R(A, B) := \frac{\left| A \cap B \right|}{\left|B\right|}R(A,B):=∣B∣∣A∩B∣,表示召回率,其中B为真实为正的集合,A为预测为正的集合
- Fβ(A,B):=(1+β2)P(A,B)×R(A,B)β2P(A,B)+R(A,B)F_\beta(A, B) := \left(1 + \beta^2\right) \frac{P(A, B) \times R(A, B)}{\beta^2 P(A, B) + R(A, B)}Fβ(A,B):=(1+β2)β2P(A,B)+R(A,B)P(A,B)×R(A,B)
指标定义如下表所示:
average 参数 |
Precision | Recall | F_beta |
"micro" |
P(y,y^)P(y, \hat{y})P(y,y^) | R(y,y^)R(y, \hat{y})R(y,y^) | Fβ(y,y^)F_\beta(y, \hat{y})Fβ(y,y^) |
"samples" |
1S∑s∈SP(ys,y^s)\frac{1}{S} \sum_{s \in S} P(y_s, \hat{y}_s)S1∑s∈SP(ys,y^s) | 1S∑s∈SR(ys,y^s)\frac{1}{S} \sum_{s \in S} R(y_s, \hat{y}_s)S1∑s∈SR(ys,y^s) | 1S∑s∈SFβ(ys,y^s)\frac{1}{S} \sum_{s \in S} F_\beta(y_s, \hat{y}_s)S1∑s∈SFβ(ys,y^s) |
"macro" |
1L∑l∈LP(yl,y^l)\frac{1}{L} \sum_{l \in L} P(y_l, \hat{y}_l)L1∑l∈LP(yl,y^l) | 1L∑l∈LR(yl,y^l)\frac{1}{L} \sum_{l \in L} R(y_l, \hat{y}_l)L1∑l∈LR(yl,y^l) | 1L∑l∈LFβ(yl,y^l)\frac{1}{L} \sum_{l \in L} F_\beta(y_l, \hat{y}_l)L1∑l∈LFβ(yl,y^l) |
"weighted" |
1∑l∈Ly^l∑l∈Ly^lP(yl,y^l)\frac{1}{\sum_{l \in L} \hat{y}_l} \sum_{l \in L} \hat{y}_l P(y_l, \hat{y}_l)∑l∈Ly^l1∑l∈Ly^lP(yl,y^l) | 1∑l∈Ly^l∑l∈Ly^lR(yl,y^l)\frac{1}{\sum_{l \in L} \hat{y}_l} \sum_{l \in L} \hat{y}_l R(y_l, \hat{y}_l)∑l∈Ly^l1∑l∈Ly^lR(yl,y^l) | 1∑l∈Ly^l∑l∈Ly^lFβ(yl,y^l)\frac{1}{\sum_{l \in L} \hat{y}_l} \sum_{l \in L} \hat{y}_l F_\beta(y_l, \hat{y}_l)∑l∈Ly^l1∑l∈Ly^lFβ(yl,y^l) |
None |
⟨P(yl,y^l),l∈L⟩\langle P(y_l, \hat{y}_l) , l \in L \rangle⟨P(yl,y^l),l∈L⟩ | ⟨R(yl,y^l),l∈L⟩\langle R(y_l, \hat{y}_l), l \in L \rangle⟨R(yl,y^l),l∈L⟩ | ⟨Fβ(yl,y^l),l∈L⟩\langle F_\beta(y_l, \hat{y}_l) , l \in L \rangle⟨Fβ(yl,y^l),l∈L⟩ |
备注:
关于分类评估指标(精确率、召回率和F值)的详细说明,请参考我的另一篇博客:十分钟掌握分类算法的评估指标
关于
average
参数的详细说明,请参考我的另一篇博客::sklearn中针对不同分类场景模型评估指标函数概述
示例代码:
from sklearn import metrics import pprint y_true = [0, 1, 2, 0, 1, 2] y_pred = [0, 2, 1, 0, 0, 1] print(metrics.precision_score(y_true, y_pred, average='macro')) print(metrics.recall_score(y_true, y_pred, average='micro')) print(metrics.f1_score(y_true, y_pred, average='weighted')) print(metrics.fbeta_score(y_true, y_pred, average='macro', beta=0.5)) print("++++++++++++") # 对于具有“负类”的多分类,可以排除一些标签: # 比如,排除0之后,没有标签被正确召回的情况 print(metrics.recall_score(y_true, y_pred, labels=[1, 2], average='micro')) # 数据样本中不存在的标签可能会在宏观平均中考虑在内。 print(metrics.precision_score(y_true, y_pred, labels=[0, 1, 2, 3], average='macro')) print("------------") # 计算精确率、召回率、F值、真实值数据集中每个标签的数量 pprint.pprint(metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5, average=None)) print("------------") # 计算指定标签,每个标签的指标 print(metrics.precision_score(y_true, y_pred, average=None, labels=[0, 2])) print(metrics.recall_score(y_true, y_pred, average=None, labels=[0, 2])) print("------------") # 计算所有标签,每个标签的指标 print(metrics.precision_score(y_true, y_pred, average=None)) print(metrics.recall_score(y_true, y_pred, average=None)) print("------------") # 计算指定标签的宏平均 print(metrics.precision_score(y_true, y_pred, average='macro', labels=[0, 2])) print(metrics.recall_score(y_true, y_pred, average='macro', labels=[0, 2])) 复制代码
运行结果:
0.2222222222222222 0.3333333333333333 0.26666666666666666 0.23809523809523805 ++++++++++++ 0.0 0.16666666666666666 ------------ (array([0.66666667, 0. , 0. ]), array([1., 0., 0.]), array([0.71428571, 0. , 0. ]), array([2, 2, 2])) ------------ [0.66666667 0. ] [1. 0.] ------------ [0.66666667 0. 0. ] [1. 0. 0.] ------------ 0.3333333333333333 0.5 复制代码
在多分类标签场景下,微平均的示例代码如下所示:
from sklearn import metrics y_true = [0, 1, 2, 0, 4, 2, 3] y_pred = [0, 1, 1, 0, 4, 1, 2] print(metrics.recall_score(y_true, y_pred, average='micro')) print(metrics.f1_score(y_true, y_pred, average='micro')) print(metrics.precision_score(y_true, y_pred, average='micro')) print(metrics.accuracy_score(y_true, y_pred)) 复制代码
运行结果:
0.5714285714285714 0.5714285714285714 0.5714285714285714 0.5714285714285714 复制代码
总结
在二分类场景时,average
参数为"binary"; 在多分类场景时,average
参数通常为"micro","macro","weighted"; 在多标签分类场景时,average
参数为"samples"。