假设有12个样本可被分为A,B, C 三个类别,某个分类器的结果如下:
真实 | 预测 |
---|---|
A | B |
A | A |
A | A |
A | C |
B | B |
B | B |
B | A |
B | C |
C | C |
C | C |
C | A |
C | C |
对于多分类来说,P值,R值,F1值都是针对某个类别来说的。对于A类来说,A类就是正类,其他类别都是负类。
A类的混淆矩阵:
预测为正类 | 预测为负类 | |
---|---|---|
实际为正类 | 2 (TP) | 2 (FN) |
实际为负类 | 2 (FP) | 6 (TN) |
B类的混淆矩阵:
预测为正类 | 预测为负类 | |
---|---|---|
实际为正类 | 2 (TP) | 2 (FN) |
实际为负类 | 1 (FP) | 5 (TN) |
C类的混淆矩阵:
预测为正类 | 预测为负类 | |
---|---|---|
实际为正类 | 3 (TP) | 1 (FN) |
实际为负类 | 2 (FP) | 6 (TN) |
P值
precision 精确率
预测为A类的样本中,实际是A类的样本占比:
预测为B类的样本中,实际是B类的样本占比:
预测为C类的样本中,实际是C类的样本占比:
R值
recall 召回率
实际为A类的样本中,被预测为A类的占比:
实际为B类的样本中,被预测为B类的占比:
实际为C类的样本中,被预测为C类的占比:
F1值
F1值是P值和R值得调和平均数:
这里做一下延伸,F1值计算将P值和R值看得同等重要。若当更关注某一个指标时,公式需要稍作修改:
当时,即是计算的值。时, 更关注P值,时, 更关注R值.
在语法纠错中,一般更关注P值,用F0.5。被分类为错误的类别里面,实际错误的比率要足够高,误判会让人感觉很不好。
Micro-F1
不区分类别。使用总体的P值和R值计算出Micro-F1
P: 预测为ABC类里面真正正确的占比
R: 实际为ABC类里面真正正确的占比
Macro-F1
宏平均有两种计算方式:
- 直接对每个类别的F1值求平均
- 对每一个类别的P值,R值求平均,再计算F1值
sklearn计算的是第一种。
代码验证:
from sklearn.metrics import classification_report
from sklearn.metrics import f1_score
print(classification_report(y_true=["A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C"],
y_pred=["B", "A", "A", "C", "B", "B", "A", "C", "C", "C", "A", "C"],
labels=["A", "B", "C"]))
print(f1_score(y_true=["A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C"],
y_pred=["B", "A", "A", "C", "B", "B", "A", "C", "C", "C", "A", "C"],
labels=["A", "B", "C"], average="micro"))
print(f1_score(y_true=["A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C"],
y_pred=["B", "A", "A", "C", "B", "B", "A", "C", "C", "C", "A", "C"],
labels=["A", "B", "C"], average="macro"))
结果:
precision recall f1-score support
A 0.50 0.50 0.50 4
B 0.67 0.50 0.57 4
C 0.60 0.75 0.67 4
avg / total 0.59 0.58 0.58 12
0.5833333333333334
0.5793650793650794
参考
Macro-F1 Score与Micro-F1 Score