如何计算 ROC 曲线?

8
我编写了一个分类器(高斯混合模型)来对五种人类行为进行分类。对于每个观测值,分类器计算属于聚类的后验概率。
我想评估我的系统参数化阈值的性能,阈值从0到100。对于每个阈值值,对于每个观察值,如果属于一个聚类的概率大于阈值,则接受分类器的结果,否则舍弃。
对于每个阈值值,我计算真正,真负,假正,假负的数量。
然后我计算两个函数:敏感度和特异度,如下:
sensitivity = TP/(TP+FN);

specificity=TN/(TN+FP);

在Matlab中:

plot(1-specificity,sensitivity);

我需要绘制ROC曲线,但结果与我的预期不符。

这是一个函数图,它显示了在更改某个操作的阈值时丢弃、错误、正确、灵敏度和特异性的函数。

这是函数图,它显示了在更改某个操作的阈值时丢弃、错误、正确、灵敏度和特异性的函数

这是一个操作的ROC曲线图像 这是ROC曲线图像

这是同一操作的ROC曲线图像 enter image description here

我错了,但我不知道错在哪里。也许我在分类器的结果小于阈值时计算FP、FN、TP、TN等方面出现了问题,因此我有一个丢弃。当有丢弃时,我应该增加什么?


能否展示一些你的代码和数据呢?只看最终产品很难知道发生了什么。顺便说一句,你展示的第一张图似乎不正确(不知道机制是什么,很难说传感器规格是否有误)。 - Rasman
您可以查看下面的示例。 https://www.saedsayad.com/flash/RocGainKS.html 此动画展示了如何计算不同阈值的TPR和FPR,并绘制它们。 - Reja
2个回答

5

背景

我回答这个问题是因为我需要处理这个内容,而这样的问题是一个很好的借口。感谢您提供这个机会。

我使用了内置的Fisher Iris数据: http://archive.ics.uci.edu/ml/datasets/Iris

我还使用了Mathworks教程中的代码片段进行分类和plotroc绘图:

问题描述

在对“setosa”进行分类时,领域内有更清晰的边界,但“versicoloir”与“virginica”之间存在重叠。这是一个二维图,一些其他信息已被丢弃以产生它。在分类边界中的不确定性在这种情况下是有用的。

%load data
load fisheriris

%show raw data
figure(1); clf
gscatter(meas(:,1), meas(:,2), species,'rgb','osd');
xlabel('Sepal length');
ylabel('Sepal width');
axis equal
axis tight
title('Raw Data')

数据显示

分析

假设我们想确定定义“维吉尼亚”与“非维吉尼亚”的线性分类器的界限。我们可以考虑其他类别的“自我 vs. 非自我”,但它们会有自己的。

现在,我们制作一些线性判别式并为它们绘制 ROC 曲线:

%load data
load fisheriris
load iris_dataset

irisInputs=meas(:,1:2)';
irisTargets=irisTargets(3,:);

ldaClass1 = classify(meas(:,1:2),meas(:,1:2),irisTargets,'linear')';
ldaClass2 = classify(meas(:,1:2),meas(:,1:2),irisTargets,'diaglinear')';
ldaClass3 = classify(meas(:,1:2),meas(:,1:2),irisTargets,'quadratic')';
ldaClass4 = classify(meas(:,1:2),meas(:,1:2),irisTargets,'diagquadratic')';
ldaClass5 = classify(meas(:,1:2),meas(:,1:2),irisTargets,'mahalanobis')';

myinput=repmat(irisTargets,5,1);
myoutput=[ldaClass1;ldaClass2;ldaClass3;ldaClass4;ldaClass5];
whos
plotroc(myinput,myoutput)

以下是结果,尽管需要删除对角线上的重复副本: enter image description here 您可以注意到代码中我将“myinput”和“myoutput”堆叠在一起并将它们作为输入馈送到“plotroc”函数中。您应该将分类器的结果作为目标值和实际值,并且可以获得类似的结果。这比较了您的分类器的实际输出与目标值的理想输出。那些是plotroc的输入。
因此,这将为您提供“内置”的ROC,这对于快速工作很有用,但不会使您学习每个步骤的详细信息。
此时您可以问的问题包括:
- 哪个分类器最好? 在这种情况下如何确定最佳? - 分类器的凸包是什么? 是否有一些混合分类器比任何纯方法更具信息性? 也许是Bagging?

-1

您正在尝试绘制精度与召回率曲线,这取决于分类器阈值参数。精度和召回率的定义如下:

Precision = TP/(TP+FP)

Recall = TP/(TP+FN)   

您可以在以下链接中查看这些参数的定义: http://en.wikipedia.org/wiki/Precision_and_recall

这里有一些曲线: http://www.cs.cornell.edu/courses/cs578/2003fa/performance_measures.pdf

您是否将数据集分为训练集、交叉验证集和测试集?(如果您没有划分数据,那么您的精确度-召回率曲线看起来可能很奇怪)

编辑:我认为您的问题有两个可能的来源:

  1. 当您为5个类别训练分类器时,通常需要训练5个不同的分类器。一个分类器用于(类A =类1,类B =类2、3、4或5),然后第二个分类器用于(类A =类2,类B =类1、3、4或5),...第五个分类器用于类A =类5,类B =类1、2、3或4)。

正如你所说,要选择“复合”分类器的输出,你必须通过五个分类器传递你的新(测试)数据点,并选择具有最大概率的那一个。

然后,你应该有5个阈值来定义加权值,以优先选择一个分类器而不是其他分类器。你应该检查matlab实现如何使用这些阈值,但它们的影响是你不会选择具有更高概率的类别,而是选择具有更好加权概率的类别。

如你所说,也许你没有正确计算TP、TN、FP、FN。你的测试数据应该包含所有类别的数据点。然后你有testdata(i,:)和classtestdata(i)是数据点i的特征向量和“真实”类别。当你评估分类器时,你会得到classifierOutput(i)=1或2或3或4或5。然后你应该计算“混淆矩阵”,这是在有多个类别(>2)时计算TP、TN、FP、FN的方法: http://en.wikipedia.org/wiki/Confusion_matrix http://www.mathworks.com/help/stats/confusionmat.html (注意你正在为多类问题计算的TP、TN、FP、FN之间的关系)
我认为你可以从混淆矩阵中获得每个子分类器的TP、TN、FP、FN数据(请记住,即使你没有意识到,你正在计算5个单独的分类器)。我不确定,但你可以为每个子分类器绘制精度召回曲线。

还可以查看这些幻灯片:http://www.slideserve.com/MikeCarlo/multi-class-and-structured-classification

我不知道ROC曲线是什么,但我会去查一下,因为机器学习对我来说是一个非常有趣的主题。

希望这能帮到你,


是的,我将数据集分为训练集、交叉验证集和测试集。正如您所看到的,丢弃、错误和纠正的功能,通过改变一个操作的阈值(图1)是很好的。问题在于另外两个函数的敏感性和特异性。 - Mario Lepore
请再检查一下我的答案。我已经编辑过了,试图回答如何识别多类问题的阈值、TP、TN等。 - jespestana
谢谢,问题在于当分类器的结果小于阈值时,FP、FN、TP、TN 的计算错误。 - Mario Lepore
1
在你的问题中进一步解释解决方案会很好,这可以帮助其他用户。我很高兴你解决了你的问题。 - jespestana
2
初始定义有误。精确度 != 灵敏度,请重新审查。 - Hugues Fontenelle
2
敏感度(Sensitivity)≠精确度(Precision)!!! 1 - 特异度(Specificity)≠召回率(Recall)!!!1 - 特异度被称为假阳性率(False Positive Rate,FPR),而召回率与敏感度相同。 - Celdor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接