sklearn中 F1-micro 与 F1-macro区别和计算原理

二分类使用Accuracy和F1-score,多分类使用宏F1和微F1。

 最近在使用sklearn做分类时候,用到metrics中的评价函数,其中有一个非常重要的评价函数是F1值,

在sklearn中的计算F1的函数为 f1_score ,其中有一个参数average用来控制F1的计算方式,今天我们就说说当参数取micromacro时候的区别

1、查准率,查全率,F1值: 

对于二分类问题,可将样例根据其真实类别和分类器预测类别划分为:

  • 真正例(True Positive,TP):真实类别为正例,预测类别为正例。

  • 假正例(False Positive,FP):真实类别为负例,预测类别为正例。

  • 假负例(False Negative,FN):真实类别为正例,预测类别为负例。

  • 真负例(True Negative,TN):真实类别为负例,预测类别为负例。

然后可以构建混淆矩阵(Confusion Matrix)如下表所示。

真实类别

预测类别

正例

负例

正例

TP

FN

负例

FP

TN

精确率,又称查准率(Precision,P):   

召回率,又称查全率(Recall,R):        

F1值:          

F1的一般形式     

 
  1. #二分类

  2. from sklearn.metrics import precision_score, recall_score, f1_score

  3.  
  4. y_true = [0, 1, 1, 0, 1, 0]

  5. y_pred = [1, 1, 1, 0, 0, 1]

  6.  
  7. Precision = precision_score(y_true, y_pred, average='binary')

  8. recall = recall_score(y_true, y_pred, average='binary')

  9. f1-score = f1_score(y_true, y_pred, average='binary')

如果只有一个二分类混淆矩阵,那么用以上的指标就可以进行评价,没有什么争议,但是当我们在n个二分类混淆矩阵上要综合考察评价指标的时候就会用到宏平均和微平均。 

2、F1_score中关于参数average的用法描述和理解:

'micro':Calculate metrics globally by counting the total true positives, false negatives and false positives.

'micro':通过先计算总体的TP,FN和FP的数量,再计算F1

'macro':Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account.

'macro':分布计算每个类别的F1,然后做平均(各类别F1的权重相同)

通过参数用法描述,想必大家从字面层次也能理解他是什么意思,micro就是先计算所有的TP,FN , FP的个数后,然后再利上文提到公式计算出F1

macro其实就是先计算出每个类别的F1值,然后去平均,比如下面多分类问题,总共有1,2,3,4这4个类别,我们可以先算出1的F1,2的F1,3的F1,4的F1,然后再取平均(F1+F2+F3+F4)/4

y_true  = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4]
y_pred = [1, 1, 1, 0, 0, 2, 2, 3, 3, 3, 4, 3, 4, 3]

3、微平均(Micro-averaging)

  首先计算总TP值,这个很好就算,就是数一数上面有多少个类别被正确分类,比如1这个类别有3个分正确,2有2个,3有2个,4有1个,那TP=3+2+2+1=8

       其次计算总FP值,简单的说就是不属于某一个类别的元数被分到这个类别的数量,比如上面不属于4类的元素被分到4的有1个

    如果还比较迷糊,我们在计算时候可以把4保留,其他全改成0,就可以更加清楚地看出4类别下面的FP数量了,其实这个原理就是 One-vs-All (OvA),把4看成正类,其他看出负类

 

同理我们可以再计算FN的数量

 1类2类3类4类总数
TP32218
FP00314
FN22116

     所以micro的 精确度P 为 TP/(TP+FP)=8/(8+4)=0.666    召回率R TP/(TP+FN)=8/(8+6)=0.571   所以F1-micro的值为:0.6153

     可以用sklearn来核对,把average设置成micro 

 
  1. y_true = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4]

  2. y_pred = [1, 1, 1, 0, 0, 2, 2, 3, 3, 3, 4, 3, 4, 3]

  3. print(f1_score(y_true,y_pred,labels=[1,2,3,4],average='micro'))

  4. #>>> 0.615384615385

4、宏平均(Macro-averaging)

先在各混淆矩阵上分别计算各类的查准率,查全率和F1,然后再计算平均值。

这样就得到“宏查准率”(macro-P)、“宏查全率”(macro-R)、“宏F1”(macro-F1)

正常最终求得就是“宏F1”

   宏查准率      

    宏查全率     

    宏F1              (我们要求的就是宏F1,每个类别的F1值的平均)

 1类2类3类4类总数
TP32218
FP00314
FN22116

macro先要计算每一个类的F1,有了上面那个表,计算各个类的F1就很容易了,比如1类,它的精确率P=3/(3+0)=1  召回率R=3/(3+2)=0.6  F1=2*(1*0.5)/1.5=0.75

可以sklearn,来计算核对,把average设置成macro

 
  1. #average=None,取出每一类的P,R,F1值

  2. p_class, r_class, f_class, support_micro=precision_recall_fscore_support(

  3. y_true=y_true, y_pred=y_pred, labels=[1, 2, 3, 4], average=None)

  4. print('各类单独F1:',f_class)

  5. print('各类F1取平均:',f_class.mean())

  6. #>>>各类单独F1: [ 0.75 0.66666667 0.5 0.5 ]

  7. #>>>各类F1取平均: 0.604166666667

  8.  
  9. #注意这里,输出《宏F》

  10. print(f1_score(y_true,y_pred,labels=[1,2,3,4],average='macro'))

  11. #>>>0.604166666667

5、sklearn实现

注意:分类报告最后一行为加权平均值。0.64就是加权平均F1-score

https://blog.csdn.net/baidu_38945893/article/details/82141975

f1_score (y_truey_predlabels=Nonepos_label=1average=’binary’sample_weight=None)

关键参数是  average: string, [None, ‘binary’ (default), ‘micro’, ‘macro’, ‘weighted’, ‘samples’],This parameter is required for multiclass/multilabel targets.

 ①None:返回每一类各自的f1_score,得到一个array。

②'binary':  只对二分类问题有效,返回由pos_label指定的类的f1_score。

Only report results for the class specified by pos_label. This is applicable only if targets (y_{true,pred}) are binary.

'micro': 设置average='micro'时,Precision = Recall = F1_score = Accuracy。

注意:这是正确的, 微查准率、微查全率、微F1都等于Accuracy。

下例中为什么不等于?因为预测中有几个0,出现错误了。

Note that for “micro”-averaging in a multiclass setting with all labels included will produce equal precision, recall and F_beta.

Calculate metrics globally by counting the total true positives, false negatives and false positives.

④'macro': 对每一类别的f1_score进行简单算术平均(unweighted mean), with assumption that all classes are equally important。

Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account.

⑤'weighted': 对每一类别的f1_score进行加权平均,权重为各类别数在y_true中所占比例。

Calculate metrics for each label, and find their average, weighted by support (the number of true instances for each label). This alters ‘macro’ to account for label imbalance; it can result in an F-score that is not between precision and recall.

⑥'samples':

Calculate metrics for each instance, and find their average (only meaningful for multilabel classification where this differs from accuracy_score).
 

 
  1.  
  2. from sklearn import metrics

  3.  
  4. y_test = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4]

  5. y_predict = [1, 1, 1, 0, 0, 2, 2, 3, 3, 3, 4, 3, 4, 3]

  6.  
  7. print('准确率:', metrics.accuracy_score(y_test, y_predict)) #预测准确率输出

  8.  
  9. print('宏平均精确率:',metrics.precision_score(y_test,y_predict,average='macro')) #预测宏平均精确率输出

  10. print('微平均精确率:', metrics.precision_score(y_test, y_predict, average='micro')) #预测微平均精确率输出

  11. print('加权平均精确率:', metrics.precision_score(y_test, y_predict, average='weighted')) #预测加权平均精确率输出

  12.  
  13. print('宏平均召回率:',metrics.recall_score(y_test,y_predict,average='macro'))#预测宏平均召回率输出

  14. print('微平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测微平均召回率输出

  15. print('加权平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测加权平均召回率输出

  16.  
  17. print('宏平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='macro'))#预测宏平均f1-score输出

  18. print('微平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='micro'))#预测微平均f1-score输出

  19. print('加权平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='weighted'))#预测加权平均f1-score输出

  20.  
  21. print('混淆矩阵输出:\n',metrics.confusion_matrix(y_test,y_predict))#混淆矩阵输出

  22. print('分类报告:\n', metrics.classification_report(y_test, y_predict))#分类报告输出

  23.  
  24.  
  25. 准确率: 0.5714285714285714

  26. 宏平均精确率: 0.58

  27. 微平均精确率: 0.5714285714285714

  28. 加权平均精确率: 0.7999999999999999

  29. 宏平均召回率: 0.4533333333333333

  30. 微平均召回率: 0.5714285714285714

  31. 加权平均召回率: 0.5714285714285714

  32. 宏平均F1-score: 0.6041666666666666

  33. 微平均F1-score: 0.6153846153846153

  34. 加权平均F1-score: 0.6369047619047619

  35. 混淆矩阵输出:

  36. [[0 0 0 0 0]

  37. [2 3 0 0 0] #[1,0]为2,即1类预测为0的为2。[1,1]为3,则1类预测为1的为3。

  38. [0 0 2 2 0]

  39. [0 0 0 2 1]

  40. [0 0 0 1 1]]

  41. 分类报告:

  42. precision recall f1-score support

  43.  
  44. 0 0.00 0.00 0.00 0

  45. 1 1.00 0.60 0.75 5

  46. 2 1.00 0.50 0.67 4

  47. 3 0.40 0.67 0.50 3

  48. 4 0.50 0.50 0.50 2

  49.  
  50. avg / total 0.80 0.57 0.64 14

上例有点问题,因为怎么可能预测为0呢?

 
  1. from sklearn import metrics

  2.  
  3. y_test = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4]

  4. y_predict = [1, 1, 1, 3, 3, 2, 2, 3, 3, 3, 4, 3, 4, 3]

  5.  
  6. print('准确率:', metrics.accuracy_score(y_test, y_predict)) #预测准确率输出

  7.  
  8. print('宏平均精确率:',metrics.precision_score(y_test,y_predict,average='macro')) #预测宏平均精确率输出

  9. print('微平均精确率:', metrics.precision_score(y_test, y_predict, average='micro')) #预测微平均精确率输出

  10. print('加权平均精确率:', metrics.precision_score(y_test, y_predict, average='weighted')) #预测加权平均精确率输出

  11.  
  12. print('宏平均召回率:',metrics.recall_score(y_test,y_predict,average='macro'))#预测宏平均召回率输出

  13. print('微平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测微平均召回率输出

  14. print('加权平均召回率:',metrics.recall_score(y_test,y_predict,average='micro'))#预测加权平均召回率输出

  15.  
  16. print('宏平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='macro'))#预测宏平均f1-score输出

  17. print('微平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='micro'))#预测微平均f1-score输出

  18. print('加权平均F1-score:',metrics.f1_score(y_test,y_predict,labels=[1,2,3,4],average='weighted'))#预测加权平均f1-score输出

  19.  
  20. print('混淆矩阵输出:\n',metrics.confusion_matrix(y_test,y_predict,labels=[1,2,3,4]))#混淆矩阵输出

  21. print('分类报告:\n', metrics.classification_report(y_test, y_predict,labels=[1,2,3,4]))#分类报告输出

  22.  
  23.  
  24. 输出:

  25. 准确率: 0.571428571429

  26. 宏平均精确率: 0.696428571429

  27. 微平均精确率: 0.571428571429

  28. 加权平均精确率: 0.775510204082

  29. 宏平均召回率: 0.566666666667

  30. 微平均召回率: 0.571428571429

  31. 加权平均召回率: 0.571428571429

  32. 宏平均F1-score: 0.579166666667

  33. 微平均F1-score: 0.571428571429

  34. 加权平均F1-score: 0.615476190476

  35. 混淆矩阵输出:

  36. [[3 0 2 0]

  37. [0 2 2 0]

  38. [0 0 2 1]

  39. [0 0 1 1]]

  40. 分类报告:

  41. precision recall f1-score support

  42.  
  43. 1 1.00 0.60 0.75 5

  44. 2 1.00 0.50 0.67 4

  45. 3 0.29 0.67 0.40 3

  46. 4 0.50 0.50 0.50 2

  47.  
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值