女朋友的毕业论文,做到了图像分割性能的评价,看到了需要用到AUC和ROC,请教大佬们,博后周师兄给出了他的解释和程序实现,非常感谢,后来查看了几个大V写的博客,感觉非常好,自己学习整理了一下,在这里总结给大家。
A大牛说,面试的时i候,一句话说明AUC的本质和计算规则:
AUC:一个正例,一个负例,预测为正的概率值比预测为负的概率值还要大的可能性。
所以根据定义:我们最直观的有两种计算
AUC的方法
1:绘制ROC曲线,ROC曲线下面的面积就是AUC的值
2:假设总共有(m+n)个样本,其中正样本m个,负样本n个,总共有m*n个样本对,计数,正样本预测为正样本的概率值大于负样本预测为正样本的概率值记为1,累加计数,然后除以(m*n)就是AUC的值
PS:百度百科,随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值。这里的score值就是预测为正的概率的值,排在前面表示的是正样本的预测为正的概率值大于负样本的预测为正的概率值
一、roc曲线
1、roc曲线:接收者操作特征(receiveroperating characteristic),roc曲线上每个点反映着对同一信号刺激的感受性。
横轴:负正类率(false postive rate FPR)特异度,划分实例中所有负例占所有负例的比例;(1-Specificity)
纵轴:真正类率(true postive rate TPR)灵敏度,Sensitivity(正类覆盖率)
2针对一个二分类问题,将实例分成正类(postive)或者负类(negative)。但是实际中分类时,会出现四种情况.
(1)若一个实例是正类并且被预测为正类,即为真正类(True Postive TP)
(2)若一个实例是正类,但是被预测成为负类,即为假负类(False Negative FN)
(3)若一个实例是负类,但是被预测成为正类,即为假正类(False Postive FP)
(4)若一个实例是负类,但是被预测成为负类,即为真负类(True Negative TN)
TP:正确的肯定数目
FN:漏报,没有找到正确匹配的数目
FP:误报,没有的匹配不正确
TN:正确拒绝的非匹配数目
列联表如下,1代表正类,0代表负类:
从列联表引入两个新名词。其一是真正类率(true positive rate ,TPR), 计算公式为TPR=TP/ (TP+ FN),刻画的是分类器所识别出的 正实例占所有正实例的比例。另外一个是假正类率(false positive rate, FPR),计算公式为FPR= FP / (FP + TN),计算的是分类器错认为正类的负实例占所有负实例的比例。还有一个真负类率(True Negative Rate,TNR),也称为specificity,计算公式为TNR=TN/ (FP+ TN) = 1-FPR。
在一个二分类模型中,对于所得到的连续结果,假设已确定一个阀值,比如说 0.6,大于这个值的实例划归为正类,小于这个值则划到负类中。如果减小阀值,减到0.5,固然能识别出更多的正类,也就是提高了识别出的正例占所有正例 的比类,即TPR,但同时也将更多的负实例当作了正实例,即提高了FPR。为了形象化这一变化,在此引入ROC,ROC曲线可以用于评价一个分类器。
Receiver Operating Characteristic,翻译为"接受者操作特性曲线",够拗口的。曲线由两个变量1-specificity 和 Sensitivity绘制. 1-specificity=FPR,即假正类率。Sensitivity即是真正类率,TPR(True positive rate),反映了正类覆盖程度。这个组合以1-specificity对sensitivity,即是以代价(costs)对收益(benefits)。 此外,ROC曲线还可以用来计算“均值平均精度”(mean average precision),这是当你通过改变阈值来选择最好的结果时所得到的平均精度(PPV). 下表是一个逻辑回归得到的结果。将得到的实数值按大到小划分成10个个数 相同的部分。
横轴FPR:1-TNR,1-Specificity,FPR越大,预测正类中实际负类越多。纵轴TPR:Sensitivity(正类覆盖率),TPR越大,预测正类中实际正类越多。理想目标:TPR=1,FPR=0,即图中(0,1)点,故ROC曲线越靠拢(0,1)点,越偏离45度对角线越好,Sensitivity、Specificity越大效果越好。
二 如何画roc曲线
假设已经得出一系列样本被划分为正类的概率,然后按照大小排序,下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率。
接下来,我们从高到低,依次将“Score”值作为阈值threshold,当测试样本属于正样本的概率大于或等于这个threshold时,我们认为它为正样本,否则为负样本。举例来说,对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。每次选取一个不同的threshold,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。这样一来,我们一共得到了20组FPR和TPR的值,将它们画在ROC曲线的结果如下图:
AUC(Area under Curve):Roc曲线下的面积,介于0.1和1之间。Auc作为数值可以直观的评价分类器的好坏,值越大越好。首先AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。
二、AUC计算
1. 最直观的,根据AUC这个名称,我们知道,计算出ROC曲线下面的面积,就是AUC的值。事实上,这也是在早期 Machine Learning文献中常见的AUC计算方法。由于我们的测试样本是有限的。我们得到的AUC曲线必然是一个阶梯状的。因此,计算的AUC也就是这些阶梯 下面的面积之和。这样,我们先把score排序(假设score越大,此样本属于正类的概率越大),然后一边扫描就可以得到我们想要的AUC。但是,这么 做有个缺点,就是当多个测试样本的score相等的时候,我们调整一下阈值,得到的不是曲线一个阶梯往上或者往右的延展,而是斜着向上形成一个梯形。此 时,我们就需要计算这个梯形的面积。由此,我们可以看到,用这种方法计算AUC实际上是比较麻烦的。
2. 一个关于AUC的很有趣的性质是,它和Wilcoxon-Mann-Witney Test是等价的。这个等价关系的证明留在下篇帖子中给出。而Wilcoxon-Mann-Witney Test就是测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。有了这个定义,我们就得到了另外一中计 算AUC的办法:得到这个概率。我们知道,在有限样本中我们常用的得到概率的办法就是通过频率来估计之。这种估计随着样本规模的扩大而逐渐逼近真实值。这 和上面的方法中,样本数越多,计算的AUC越准确类似,也和计算积分的时候,小区间划分的越细,计算的越准确是同样的道理。具体来说就是统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score。当二元组中正负样本的 score相等的时候,按照0.5计算。然后除以MN。实现这个方法的复杂度为O(n^2)。n为样本数(即n=M+N) 3. 第三种方法实际上和上述第二种方法是一样的,但是复杂度减小了。它也是首先对score从大到小排序,然后令最大score对应的sample 的rank为n,第二大score对应sample的rank为n-1,以此类推。然后把所有的正类样本的rank相加,再减去M-1种两个正样本组合的情况。得到的就是所有的样本中有多少对正类样本的score大于负类样本的score。然后再除以M×N。即
公式解释:
1、为了求的组合中正样本的score值大于负样本,如果所有的正样本score值都是大于负样本的,那么第一位与任意的进行组合score值都要大,我们取它的rank值为n,但是n-1中有M-1是正样例和正样例的组合这种是不在统计范围内的(为计算方便我们取n组,相应的不符合的有M个),所以要减掉,那么同理排在第二位的n-1,会有M-1个是不满足的,依次类推,故得到后面的公式M*(M+1)/2,我们可以验证在正样本score都大于负样本的假设下,AUC的值为1
2、根据上面的解释,不难得出,rank的值代表的是能够产生score前大后小的这样的组合数,但是这里包含了(正,正)的情况,所以要减去这样的组(即排在它后面正例的个数),即可得到上面的公式 另外,特别需要注意的是,再存在score相等的情况时,对相等score的样本,需要 赋予相同的rank(无论这个相等的score是出现在同类样本还是不同类的样本之间,都需要这样处理)。具体操作就是再把所有这些score相等的样本 的rank取平均。然后再使用上述公式。
最后给出实现matlab代码如下:
计算PRF的代码:
function [TPR, FPR, PRE] = CalPRF(FG, GT, thresholds)
%
GT = im2double(GT);
if size(GT,3)>1
GT = GT(:,:,1);
end
FG = im2double(FG);
if size(FG, 3)>1
FG = FG(:,:,1);
end
if size(GT,1)~=size(FG,1) || size(GT,2)~=size(FG,2)
FG = imresize(FG, [size(GT,1), size(GT,2)]);
end
% [0,1]
FG = (FG - min(FG(:))) ./ (max(FG(:)) - min(FG(:)));
GT = (GT - min(GT(:))) ./ (max(GT(:)) - min(GT(:)));
TPR = zeros(1,length(thresholds));
FPR = zeros(1,length(thresholds));
PRE = zeros(1,length(thresholds));
for k = 1:length(thresholds)
tt = thresholds(k);
TP = sum(sum((FG>=tt) & (GT>0.1))); % 正样本数目(分的正确的像素数目)
FP = sum(sum((FG>=tt) & (GT<=0.1))); % 被判成正样本的负样本数目
% 1表示正样本,0表示负样本
P = sum(sum(GT>0.1)); % 总的正样本数目
N = sum(sum(GT<=0.1)); % 总的负样本数目
if P ~= 0 && N ~= 0
TPR(k) = TP/P;
FPR(k) = FP/N;
PRE(k) = TP/(TP+FP);
elseif P == 0 && N ~= 0
TPR(k) = 0;
FPR(k) = FP/N;
elseif P ~= 0 && N == 0
TPR(k) = TP/P;
FPR(k) = 0;
else
TPR(k) = 0;
FPR(k) = 0;
end
end
end
计算曲线图代码:
function [TPR, FPR, PRE, F] = CalPRFCurve(algPath, algSuffix, gtPath, gtSuffix, thresholds)
%
algFiles = dir(fullfile(algPath, strcat('*', algSuffix)));
gtFiles = dir(fullfile(gtPath, strcat('*', gtSuffix)));
if length(algFiles) ~= length(gtFiles)
error('the number of files is mismatching');
end
% thresholds = 1;
imgTPR = zeros(length(gtFiles), length(thresholds));
imgFPR = zeros(length(gtFiles), length(thresholds));
imgPRE = zeros(length(gtFiles), length(thresholds));
parfor i = 1:length(gtFiles)
algImgName = algFiles(i).name;
gtImgName = strrep(algImgName, algSuffix, gtSuffix);
if strfind(algImgName(1:strfind(algImgName,'.')-1), gtImgName(1:strfind(gtImgName,'.')-1) )
% get ground truth
GT = imread(fullfile(gtPath,gtImgName));
% get foreground map
FG = im2double(imread(fullfile(algPath,algImgName)));
% thresholds = sum(FG(:))/20000; % 自适应阈值
% thresholds = graythresh(FG); % OTSU
% compute precision and recall
[imgTPR(i,:), imgFPR(i,:), imgPRE(i,:)] = CalPRF(FG, GT, thresholds);
else
error('Img name is mismatching.');
end
end
TPR = mean(imgTPR, 1);
FPR = mean(imgFPR, 1);
PRE = mean(imgPRE, 1);
F = (1.3.*PRE.*TPR)./(0.3.*PRE+TPR);
% TPR(256)=0;
% plot(TPR, PRE, 'linewidth', 2);
% axis([0 1 0 1]);
% xlabel('Recall'),
% ylabel('Precision'),
% title('Precision-Recall Curve');
%
% figure,
% plot(FPR, TPR,'linewidth', 2);
% axis([0 1 0 1]);
% xlabel('False Positive Rate'),
% ylabel('True Positive Rate'),
% title('False Positive Rate-True Positive Rate Curve');
%
% figure,
% plot(F,'linewidth', 2);
% axis([0 255 0 1]);
% xlabel('Threshold'),
% ylabel('F-Measure'),
% title('F-Measure Curve');
end
最后给出的效果图如下:
参考:
http://blog.csdn.net/abcjennifer/article/details/7359370