在以往的分类问题求解当中,我们遇到的问题多为二分类问题,我们常用的评估指标有accuracy, precision, recall_score, f1-score, roc_auc_score等。但是在实际生活中,多分类问题也是大量存在的。这一小节,我们就详细的说明一下多分类问题的评估指标。
我们先来看一下sklearn库中的二分类的评估指标,以recall_score为例。在recall_score方法中,有一个很重要的参数’average’,它的默认值为’binary’。当在默认参数的情况,该评估方法只能求解二分类问题,如果将该评估方法用于多分类问题,则系统会报错。但’average’同时也向我们提供了其他四个用于解决多分类的问题的参数’micro’,‘macro’,‘weighted’,‘samples’。下面我们以鸢尾花数据集为例来对这四个参数进行逐一说明。
[sklearn.metrics.recall_score]('https://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html
')
sklearn.metrics.recall_score(y_true, y_pred, labels=None,
pos_label=1, average='binary', sample_weight=None, zero_division='warn')
我们以recall_score的计算为例,recall_score的计算公式如下:
R e c a l l = T P T P + F N Recall = \frac {TP}{TP + FN} Recall=TP+FNTP
为了计算recall_score,我们必须先计算出TP,FN值。我们采用sklearn中的混淆矩阵来计算TP,FN值。
#导入数据分析的常用工具包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
#导入iris数据集
from sklearn import datasets
iris = datasets.load_iris()
#对iris数据集进行切分
from sklearn.model_selection import train_test_split
X = iris.data
Y = iris.target
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size = 0.3,random_state = 0)
#建立一个基础的逻辑回归模型
from sklearn.linear_model import LogisticRegression
LR = LogisticRegression()
LR.fit(X_train,Y_train)
prediction = LR.predict(X_test)
#计算混淆矩阵
from sklearn.metrics import confusion_matrix
cnf = confusion_matrix(Y_test,prediction,labels = [0,1,2])
print(cnf)
[out]:
array([[16, 0, 0],
[ 0, 13, 5],
[ 0, 0, 11]], dtype=int64)
该分类问题的混淆矩阵如下,列为真实类别,行为预测类别:
class | 0 | 1 | 2 |
---|---|---|---|
0 | 16 | 0 | 0 |
1 | 0 | 13 | 5 |
2 | 0 | 0 | 11 |
混淆矩阵(confusion matrix)说明:
TP(True positive):把正例正确地预测为了正例,如把类别0预测为0的个数有16个。
FN(False negative):把正例错误地预测为了负列,如把类别1预测为2的个数有5个。
FP(False positive):把负例错误地预测为了正例,假设0为正例,错误地把1,2预测为0就是FP。
TN(True negative):把负例正确地预测为了负例,假设0为正例,1,2为负例,正确地把1,2预测为1,2就是TN。
对于混淆矩阵,可以这样理解。第一个字母T/F,表示预测的正确与否;第二个字母P/N,表示预测的结果为正例或者负例。如TP就表示预测对了,预测的结果是正例,那它的意思就是把正例预测为了正例。
Micro:把所有类汇总在一起计算出最终recall值,其计算公式如下:
R e c a l l = T P 0 + T P 1 + T P 2 T P 0 + F N 0 + T P 1 + F N 1 + T P 2 + F N 2 Recall = \frac{TP_0 + TP_1 + TP_2}{TP_0 + FN_0 + TP_1 + FN_1 + TP_2 + FN_2} Recall=TP0+FN0+TP1+FN1+TP2+FN2TP0+TP1+TP2
在使用Micro参数时,其recall_score = (16+13+11)/(16+13+11+5) = 0.89。
使用sklearn.metrics方法计算:
from sklearn.metrics import recall_score
recall_score(Y_test,prediction,average = 'micro')
[out]:0.8888888888888888
从上述计算结果可以看出,两者的计算结果是一致的,均为0.89。
Macro:分别计算出每一类的recall值,再取算数平均值,其计算公式如下:
R e c a l l = ( T P 0 T P 0 + F N 0 + T P 1 T P 1 + F N 1 + T P 2 T P 2 + F N 2 ) ∗ 1 3 Recall =( \frac{TP_0}{TP_0 + FN_0} + \frac{TP_1}{TP_1 + FN_1} + \frac{TP_2}{TP_2 + FN_2}) * \frac{1}{3} Recall=(TP0+FN0TP0+TP1+FN1TP1+TP2+FN2TP2)∗31
在使用Macro参数时,其recall_score = [16/(16+0+0) + 13/(0+13+5) + 11/(11+0+0)] * 1/3 = 0.91
使用sklearn.metrics方法计算:
from sklearn.metrics import recall_score
recall_score(Y_test,prediction,average = 'macro')
[out]:0.9074074074074074
从上述计算结果可以看出,macro参数下的recall值为0.91。
Weighted:分别计算每一类的recall值,再乘以各自的权重,然后求和,其计算公式如下:
R e c a l l = T P 0 T P 0 + F N 0 ∗ W 0 + T P 1 T P 1 + F N 1 ∗ W 1 + T P 2 T P 2 + F N 2 ∗ W 2 Recall =\frac{TP_0}{TP_0 + FN_0} * W_0+ \frac{TP_1}{TP_1 + FN_1} * W_1 + \frac{TP_2}{TP_2 + FN_2} * W_2 Recall=TP0+FN0TP0∗W0+TP1+FN1TP1∗W1+TP2+FN2TP2∗W2
计算各类的权重:
W0,W1,W2 = np.bincount(Y_test) / len(Y_test)
print(W0,W1,W2)
[out]:0.35555555555555557 0.4 0.24444444444444444
在使用weighted参数时,其recall_score = 16/(16+0+0) * 0.356 + 13/(0+13+5) * 0.4 + 11/(11+0+0) * 0.244 = 0.89
使用sklearn.metrics方法计算:
from sklearn.metrics import recall_score
recall_score(Y_test,prediction,average = 'weighted')
[out]:0.8888888888888888
从上述计算结果可以看出,weighted参数下的recall值为0.89。
samples应用于多标签的分类问题,每一个样本拥有一个以上的标签。如一个感染病毒性肺炎的患者,就可以说他既属于病毒性肺炎患者这一类,也可以说他属于肺炎患者类。
小结:
1.对于多分类算法的评估,我们需要将sklearn.metrics.recall_score中的’average’参数修改为’micro’或’macro’或者’weighted’。
2.在这个例子当中,我们以recall来举例,像其他的评估指标precision, roc_auc_score, f1-score都是采用同样的方法。
文章参考:
[1].https://zhuanlan.zhihu.com/p/59862986