在一般认知中,用模型对测试集进行分类预测,结果应该是X或者X'(也可以说是或者否)。根据混淆矩阵算出TP、FP、TN、FN,进一步算出TPR、FPR。一个测试集只会有一对TPR/FPR值,那么ROC曲线就只会有一个点,何谈曲线之说?难道是用多个测试集得到多对TPR/FPR值,来绘制ROC曲线吗?实则不然。
ROC曲线,一般适用于分类器输出一个“概率值”,即这个样本属于某个类的概率是多少。在计算的时候会依次用所有样本的概率值作为阈值, 用阀值和所有样本的预测值进行比较,大于这个阈值的样本预测为正类,小于这个阈值的样本预测为负类。从而,对于每个阈值都能得到对应的TPR/FPR, 也就是ROC曲线上的一个点。样本数量n=>阀值数量n=>点数量n(不考虑去重),最终构成ROC曲线。
计算示例
测试集7个样本ABCDEFG的分类真实值:[0, 0, 0, 0, 1, 1, 1]
模型预测为1的概率分别是:[0.3, 0.2, 0.7, 0.5, 0.4, 0.9, 0.6]
1.以0.3为阀值,预测值[1, 0, 1, 1, 1, 1, 1]. TP、FP、TN、FN=3、3、1、0, TPR、FPR=3/3、3/4.
2.以0.2为阀值,预测值[1, 1, 1, 1, 1, 1, 1]. TP、FP、TN、FN=3、4、0、0, TPR、FPR=3/3、4/4.
3.以0.7为阀值,预测值[0, 0, 1, 0, 0, 1, 0]. TP、FP、TN、FN=1、1、3、2, TPR、FPR=1/3、1/4.
4.以0.5为阀值,预测值[0, 0, 1, 1, 0, 1, 1]. TP、FP、TN、FN=2、2、2、1, TPR、FPR=2/3、2/4.
5.以0.4为阀值,预测值[0, 0, 1, 1, 1, 1, 1]. TP、FP、TN、FN=3、2、2、0, TPR、FPR=3/3、2/4.
6.以0.9为阀值,预测值[0, 0, 0, 0, 0, 1, 0]. TP、FP、TN、FN=1、0、4、2, TPR、FPR=1/3、0/4.
7.以0.6为阀值,预测值[0, 0, 1, 0, 0, 1, 1]. TP、FP、TN、FN=2、1、3、1, TPR、FPR=2/3、1/4.
8.按照横FPR纵TPR坐标从小到大排序坐标点:(0,0.33)(0.25,0.33)(0.25,0.67)(0.5,0.67)(0.5,1)(0.75,1)(1,1)
9.根据上述坐标点绘制曲线,计算曲线包围的面积,即AUC的值
代码示例
import numpy as np
from sklearn import metrics
import matplotlib.pyplot as plt
test_true = np.array([0, 0, 0, 0, 1, 1, 1])
test_pre = np.array([0.3, 0.2, 0.7, 0.5, 0.4, 0.9, 0.6])
fpr, tpr, thresholds = metrics.roc_curve(test_true, test_pre, pos_label=1)
print fpr
print tpr
print thresholds
plt.plot(fpr,tpr,marker = 'o')
plt.show()
auc = metrics.auc(fpr, tpr)
print auc
'''
值得关注的函数,注意pos_label的设置
fpr, tpr, thresholds=sklearn.metrics.roc_curve(y_true,y_score,pos_label=None)
pos_label : int or str, default=None,Label considered as positive and others are considered negative.
'''
关于阀值
最后说明一点,用每个概率结果作为阀值是计算ROC曲线的一个度量元素。没有业务语义。不用过多思考。
但在实际项目中,如何用概率结果判断业务分类,就需要思考阀值的具体设定了。不能想当然的用0.5一刀切,可以参考:http://blog.sina.com.cn/s/blog_13a4bb3270102w1om.html