机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线

1 混淆矩阵 机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

淆矩阵的作用:
1)用于观察模型在各个类别上的表现,可以计算模型对应各个类别的准确率,召回率;
2)通过混淆矩阵可以观察到类别直接哪些不容易区分,比如A类别中有多少被分到了B类别,这样可以有针对性的设计特征等,使得类别更有区分性;
2 ROC 机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

ROC曲线的横坐标为false positive rate(FPR),纵坐标为true positive rate(TPR)
3 AUC AUC(Area Under Curve)被定义为ROC曲线下的面积,这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。为什么呢,因为ROC曲线越接近左上角,AUC面积就越大,分类器性能就越好。
auc指标含义的理解 机器学习实践中分类器常用的评价指标就是auc,不想搞懂,简单用的话,记住一句话就行
auc取值范围[0.5,1],越大表示越好,小于0.5的把结果取反就行。
想搞懂的,看An introduction to ROC analysis (Tom Fawcett)这篇论文把。我把这篇论文的要点整理了一下。
引子
假设有下面两个分类器,哪个好?
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

测试样本中有A类样本90个,B 类样本10个。
分类器C1把所有的测试样本都分成了A类(比如分类器的输出只是一句代码 printf ("A") ),
分类器C2把A类的90个样本分对了70个,B类的10个样本分对了5个。
则C1的分类精度为 90%,C2的分类精度为75%,但直觉上,我们感觉C2更有用些。
我们需要一个评价指标,能客观反映对正样本、负样本综合预测的能力,还要考虑消除样本倾斜的影响(其实就是归一化之类的思想,实际中很重要,比如pv总是远远大于click),这就是auc指标能解决的问题。
啥是auc
roc曲线下的面积就是auc,所以要先搞清楚roc。
【机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线】先看二分类问题,预测值跟实际值有4种组合情况,见下面的列联表
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

我们让:
纵坐标是true positive rate(TPR)= TP / (TP+FN=P) (分母是横行的合计)直观解释:实际是1中,猜对多少
横坐标是false positive rate(FPR) = FP / (FP+TN=N)直观解释:实际是0中,错猜多少

机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

所以评估标准改成离左上角近的是好的分类器。(考虑了正负样本的综合分类能力)
如果一个分类器能输出score,调整分类器的阈值,把对应的点画在图上,连成线这条线就是roc,曲线下的面积就是auc(Area under the Curve of ROC )
有啥特点

  • 1 roc上的点,越靠近左上角越好。(tp rate is higher, fp rateis lower,or both )
  • 2 y = x这条对角线代表随机猜测的结果。比如用投掷硬币结果来猜测,点在(0.5, 0.5) ;假设硬币不均匀,90%概率向上,那就是(0.9, 0.9) (正例中,90%能猜对;反例中,90%猜错)
  • 3 auc范围[0.5, 1],小于0.5的分类器把结果取反一下。
  • 4 分类器不一定要输出概率,输出可比较的score也行。
  • 5 画roc曲线的时候,threshold采样点是有限的离散化点,其实就用score,毕竟score是有限的。Any ROCcurve generated from a finite set of instances is actually a step function。画曲线需要两个值TP/P和FP/N。P和N可以先扫描一遍找出来,后面不会变的。把score排一下序,从高到底,依次作为threshold(>=threshold的我们预测为p,其他为n)。TP判断class为P的加一就行,FP判断class为N的也加一就行。变得很简单了。
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

这里就有一个细节问题了,score相同的点怎么处理?

机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

论文里给出一个直观的图,先累加正样本和先累加负样本的差异(先加TP往上走,还是FP往右走)。结论就是score相同的样本一起算,不要一个样本就输出一个采样点。
  • 6. auc的直观含义是任意取一个正样本和负样本,正样本得分大于负样本的概率。TheROC curve shows the ability of the classifier to rank the positive instances relative to the negative instances, and it is indeed perfect in this ability.(想想这个组合问题的概率怎么求?对每一个负样本,把分数大于这个负样本的正样本个数累加起来,最后除以总的组合数P*N,前面算roc curve是不是也类似这样累加?除了P或者N先除了。还不确定看下面的代码实现,代码里为了平滑,求的是小梯形的面积,而不是矩形,稍微有些差别。)论文里举了个例子,auc算出来是1,但是可以发现预测结果不是完全对的(7和8就预测错了)。但实际上只是threshold选择得不好而已,threshold选0.7这里就行了。
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

  • 7 容忍样本倾斜的能力。ROC curves have an attractive property: they are insensitive to changes in class distribution. 看看公式TP/P 和FP/N本身就包含了归一化的思想(上面的表格每一行乘以常数C,TPR和FPR不变的),比如负样本*10的话 : FPR = (FP*10)/(N*10),不变的。
再看看precision和recall就不行了,因为一个表格里是竖行,一个是横行。
precision=tp/(tp+fp),recall=tp/(tp+fn)
负样本*10的话 :
precision=tp/(tp+fp*10),recall=tp/(tp+fn)
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片


具体代码实现 求一个个小的梯形的面积。
机器学习|混淆矩阵 confusion matrix ROC曲线 AUC曲线
文章图片

搞到一个scoreKDD.py的代码
#!/usr/local/bin/python def scoreAUC(labels,probs): i_sorted = sorted(range(len(probs)),key=lambda i: probs[i], reverse=True) auc_temp = 0.0 TP = 0.0 TP_pre = 0.0 FP = 0.0 FP_pre = 0.0 P = 0; N = 0; last_prob = probs[i_sorted[0]] + 1.0for i in range(len(probs)): if last_prob != probs[i_sorted[i]]: auc_temp += (TP+TP_pre) * (FP-FP_pre) / 2.0 TP_pre = TP FP_pre = FP last_prob = probs[i_sorted[i]] if labels[i_sorted[i]] == 1: TP = TP + 1 else: FP = FP + 1 auc_temp += (TP+TP_pre) * (FP-FP_pre) / 2.0 auc = auc_temp / (TP * FP) return aucdef read_file(f_name):f = open(f_name) labels = [] probs = [] for line in f: line = line.strip().split() try: label = int(line[2]) prob = float(line[3]) except ValueError: # skip over header continue labels.append(label) probs.append(prob) return (labels, probs) def main(): import sys if len(sys.argv) != 2: print("Usage: python scoreKDD.py file") sys.exit(2) labels, probs = read_file(sys.argv[1]) auc = scoreAUC(labels, probs) print("%f" % auc) if __name__=="__main__": main()


    推荐阅读