假设你有一些训练好的二元分类器A、B(B的表现几乎和随机猜测差不多等…),以及一个由n个测试样本组成的测试集来与这些分类器一起使用。由于精确度和召回率是针对所有n个样本计算的,这些对应分类器的点是有意义的。
现在有时候人们会谈论ROC曲线,我理解精确度是作为召回率的函数来表达的,或者简单地绘制精确度(召回率)。
我不理解这种变异性从何而来,因为你有一个固定的测试样本数。你是选择测试集的一些子集并找出精确度和召回率来绘制它们,因此有许多离散值(或一条插值线)吗?
回答:
ROC曲线对于以“分数”表达输出的二元分类器来说是明确定义的。这个分数可以是,例如,属于阳性类的概率,或者也可以是两个可能结果的概率分布之间的概率差异(甚至是对数比率)。
通过将这个分数的决策阈值设置在不同的水平,并测量给定该阈值的真正例率和假正例率,得到曲线。
维基百科的“接收者操作特征”页面中有一个这个过程的好例子:
例如,想象一下,患病人和健康人的血液蛋白水平分别以2 g/dL和1 g/dL为均值的正态分布。一个医学测试可能测量血液样本中某蛋白的水平,并将任何高于某一阈值的数值分类为表示疾病。实验者可以调整阈值(图中的黑色垂直线),这反过来会改变假阳性率。增加阈值会导致更少的假阳性(和更多的假阴性),对应于曲线上的左移。曲线的实际形状由两个分布的重叠程度决定。
如果你更喜欢代码,这里是scikit-learn中给定数据集中每个项目的预测计算ROC曲线的代码。基本操作似乎是(直接链接):
desc_score_indices = np.argsort(y_score, kind="mergesort")[::-1]y_score = y_score[desc_score_indices]y_true = y_true[desc_score_indices]# accumulate the true positives with decreasing thresholdtps = y_true.cumsum()fps = 1 + list(range(len(y_true))) - tpsreturn fps, tps, y_score
(我省略了其中处理(常见情况)加权样本和当分类器对多个样本给出近乎相同分数的代码。)基本上,真实标签按照分类器分配给它们的分数以降序排序,然后计算它们的累积和,作为分类器分配的分数的函数,得到真正例率。
这里有一个展示如何使用它的例子:http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html