总第96篇
前面的推文中介绍了几种常用的机器学习算法,每个算法都有各自的优劣势,我们应该选择根据每个算法的优劣势去合理的选择适合我们需求的算法,以此达到效果最优,那么什么样的效果才是最优的,用什么来衡量这个效果。这一篇就针对机器学习算法的效果评估指标进行介绍。
在介绍具体每个指标的概念以前,我们先看一个故事:
一位女神被安排了10位男性相亲对象,目前只有这10位男性的照片,女神需要根据照片情况来判断要不要去见面,其中影响见与不见的一个重要指标就是这位男性是否是土豪,该女神就通过每位男性的照片(具体一点就是通过男性穿的什么牌子的衣服、鞋、皮带,戴的什么眼镜、手表哈)来判断哪位是土豪。表中的结果就是女神判断的结果和实际情况对应表。女神的眼力怎么样呢(把女神的眼力当作一个算法看待)?先看一下下图这张表:
实际是土豪 | 实际是非土豪 | |
---|---|---|
被判断为土豪 | 5人 | 2人 |
被判断为非土豪 | 2人 | 1人 |
这张表表示,这10位男士中有7位是真正的土豪,在这7位土豪中有5位被判别出来了,有2位被误判为非土豪(可能穿着比较低调,被误判了哈哈哈);有3位男士是非土豪,在这3位中有2位被误判为土豪(穿着打扮能力很强),只有1位非土豪被判断成非土豪。
这是上面图表直观上传达的意思,我们接下来用不同的量化指标去评判女神的判断效果,并用sklearn库实现。
准确率(accuracy)是指所有被正确划分类别(实际是土豪被判断为土豪人数+实际是非土豪被判断为非土豪的人数)的人数占总人数(所有被判断对象)的比值(5+1)/10=0.6
。
#导入sklearn库
from sklearn.metrics import accuracy_score
#打印出准确率
print(accuracy_score(y_true,y_pred)
#打印出分类正确的个数
print(accuracy_score(y_true,y_pred,normalize=False))
在说精确率(precision)以前,我们需要重申一下女神做判断的目的,就是找出真正的土豪。精确率就是女神找出的真土豪人数(被判断为土豪实际也是土豪的人数)占女神找出所有土豪人数(被判断为土豪的总人数=实际是土豪+实际是非土豪)的比值5/(5+2)=0.71
#导入sklearn库
from sklearn.metrics import precision_score
#打印出精确率
print(precision_score(y_true, y_pred, average='macro'))
召回率(recall)是指被找出的真土豪人数(被判断为土豪实际也是土豪)占实际土豪总人数的比值5/(5+2)=0.71
#导入sklearn库
from sklearn.metrics import recall_score
#打印出召回率
print(recall_score(y_true, y_pred, average='macro'))
F1-score是精确率和召回率的调和平均值,之所以是调和平均是我们可以对精确率和召回率给予不同的权重,默认情况下两者的权重是一样的。计算公式如下:
#导入sklearn库
from sklearn.metrics import f1_score
#打印出召回率
print(f1_score(y_true, y_pred, average='macro'))
交叉报告(classfication_report)是上面几个指标(精确率、召回率、f1-score)的一个汇总情况。
#导入sklearn库
from sklearn.metrics import classification_report
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
#分类标签名
target_names = ['class 0', 'class 1', 'class 2']
#打印出交叉报告
print(classification_report(y_true, y_pred, target_names=target_names))
混淆矩阵(confusion_matrix)是用矩阵的形式来表示分类情况,对角线元素表示预测标签等于真实标签的点的数量,是分类结果的一个绝对量,而不是比值,而非对角线元素是分类器误标记的那些元素。混淆矩阵的对角线值越高越好,表明被正确预测的量越多。
#导入sklearn库
from sklearn.metrics import confusion_matrix
y_true = [2, 0, 2, 2, 0, 2]
y_pred = [0, 0, 2, 2, 0, 2]
#打印出矩阵
print(confusion_matrix(y_true, y_pred))
混淆矩阵的结果也经常被用来可视化成热力图的形式,横坐标表示预测的类别,纵坐标表示实际的类别,对角线依次表示实际是A、B、C类且被预测为A、B、C类的量,颜色越深表示被预测正确的量越多,效果越好。
在说ROC/AUC之前,我们先说一下分类器的输出结果,可以是直接输出具体的类别clf.predict()方法
,也可以输出属于某个类别的概率clf.predict_proba()方法
,对于输出类别的方法,算法会先设定一个默认的阈值,将大于阈值的划分为1类,小于阈值的划分为0类;我们也可以自定义阈值的大小,且阈值是可调整的,不同调整的不同的阈值,使分类准确率达到最大,而ROC曲线就是不同阈值下对应的准确率绘制的一条曲线。ROC曲线越向上,表示模型效果越好。
绘制ROC曲线需要计算两个值,tpr和fpr,tpr是模型在正样本上的预测准确率,是将真土豪分为土豪的概率(被判断为土豪的人数/实际土豪人数),即召回率;fpr是模型在负样本上的预测准确率,表示将非土豪误判为土豪的人数占所有实际非土豪人数的比值(1-被判断为非土豪且实际也是非土豪人数/实际非土豪人数)。
#导入库
from sklearn.metrics import roc_curve, auc
#计算tpr,fpr,auc
fpr, tpr, threshold = roc_curve(y_test, y_proba)
roc_auc = auc(fpr, tpr)
#plot roc_curve
%matplotlib inline
plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange',
lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()
ROC是一个定性指标,无法对模型效果进行量化,所以有了AUC,AUC是ROC曲线下方的面积,通常AUC值在0.5-1.0之间,值越大模型效果越好。
准确率容易受到不平衡数据的影响,比如有在100个测试集中,有99个负样本,1个正样本,模型会把这100个测试集全部划分为负样本,得到的结果如下:
实际是正样本 | 实际是负样本 | |
---|---|---|
预测为正样本 | 0 | 0 |
预测为负样本 | 1 | 99 |
这个模型的的准确率可以高达99%,但是我们的目标是找出正样本,而该模型一个正样本都找不出来,这个准确率是虚高,是带有欺骗性的。所以当正负样本不平衡的时候,准确率是没有评价意义的。
精确率和召回率是相互制约的,一般精确率低的召回率高,精确率搞得召回率低,根据不同的业务场景选择不同的重点。比如公司要通过运营活动(奖励活动)对即将要流失的用户进行挽留,于是针对用户做了两个流失预警模型,一个模型的精确率较高,另一个模型的召回率高,如果选择精确率较高的模型,会漏掉更多的流失用户,降低了挽回用户量;但是如果选择召回率高的,就会把更多的非流失用户判断为流失用户,产生了更多的不必要成本,那么我们应该如何选择这两个模型呢?
这个时候就要具体情况具体分析,如果是运营经费比较宽裕,且挽留回一个用户所带来的价值是非必要支出的很多倍,那么就选择召回率高的模型;如果是运营经费有限,且挽回用户的价值不那么高,那么就选择精确率较高的模型。
F1-score是精确率和召回率两指标的一个综合。
前面说过的所有指标都是针对一个阈值的结果进行计算的,ROC是将模型依次取不同的阈值,并将该阈值对应的tpr和fpr绘制成一条曲线。
AUC是ROC的量化指标,AUC/ROC是最常用的一种评价方式,因为其不受正负样本比例的影响(影响其的两个指标主要是tpr和fpr,这两个指标表示模型分别在正样本和负样本上的表现情况,和两者的比值无关,所以评价结果也无关)。