轉自:http://www.zhizhihu.com/html/y2012/4076.html
分類、檢索中的評價指標很多,Precision、Recall、Accuracy、F1、ROC、PR Curve......
一、歷史
wiki上說,ROC曲線最先在二戰中分析雷達信號,用來檢測敵軍。誘因是珍珠港事件;由於比較有用,慢慢用到了心理學、醫學中的一些檢測等應用,慢慢用到了機器學習、數據挖掘等領域中來了,用來評判分類、檢測結果的好壞。
百科:ROC曲線指受試者工作特征曲線(receiver operating characteristic curve), 是反映敏感性和特異性連續變量的綜合指標,是用構圖法揭示敏感性和特異性的相互關系,它通過將連續變量設定出多個不同的臨界值,從而計算出一系列敏感性和 特異性,再以敏感性為縱坐標、(1-特異性)為橫坐標繪制成曲線,曲線下面積越大,診斷准確性越高。在ROC曲線上,最靠近坐標圖左上方的點為敏感性和特 異性均較高的臨界值。
二、原理
這里就拿最經典的二分類(0、1)問題討論吧,分類器分類之后,往往會得到對每個樣本是哪一類的一個估計,像是LR模型就會將這個估計規范化到 【0,1】,根據這個估計,你選擇一個閾值p_0,就可以將分類結果映射到0,1了;分類效果好不好跟真實的label比比就行了。
所以你手里有decision和label兩個向量,用來做分類結果的評估。
要看ROC的原理,總離不開上面這個表格,ROC繪制的就是在不同的閾值p_0下,TPR和FPR的點圖。所以ROC曲線的點是由不同的p_0所造成的。所以你繪圖的時候,就用不同的p_0采點就行。
Precision-Recall曲線,這個東西應該是來源於信息檢索中對相關性的評價吧,precision就是你檢索出來的結果中,相關的比 率;recall就是你檢索出來的結果中,相關的結果占數據庫中所有相關結果的比率;所以PR曲線要是繪制的話,也是對cutoff進行遍歷,這樣也得到 了不同的precision和recall的點。例如你選擇了一個cutoff,從而根據cutoff判別分類的結果1或0。1就是檢索返回的結果,0就 是沒有返回的結果。
數據庫里有500條記錄,其中50個是相關的(正樣本),你通過一個cutoff,返回了75個1,其中只有45個是真正相關的;
那么在這個cutoff對應下的recall=45/50=0.9,precision=45/75=0.6。坐標就是(0.9,0.6),在這里繪制一個點吧。
可以看出TPR和Recall的形式是一樣的,就是查全率了,FPR就是保證這樣的查全率你所要付出的代價,就是把多少負樣本也分成了正的了。
三、AUC的計算
為了更好的衡量ROC所表達結果的好壞,Area Under Curve(AUC)被提了出來,簡單來說就是曲線右下角部分占正方形格子的面積比例;那么計算這個東西其實就很簡單了,根據reference的 paper,有很多很多計算方法,這里推薦一種近似采樣的方法:采樣。
你的分類器能夠將正例排在負例前面的概率是多少,也就是采樣中正例的decision>負例的decision的概率。
從stackoverflow上看到的代碼,R語言:
auc <- mean(sample(pos.decision,1000,replace=T) > sample(neg.decision,1000,replace=T)) ## or aucs <- replicate(2000,mean(sample(pos.decision,1000,replace=T) > sample(neg.decision,1000,replace=T))) auc2 <- round(mean(aucs),4)
其實這個可以等價於對於不規則圖形的面積的采樣估計了。
四、ROC中最優的p_0的計算
簡單理解下的話,保證TPR同時代價FPR要盡量的小,是不是可以建立max(TPR+(1-FPR))的模型,然后選p_0呢?
paper中有更加詳細的方法。誰給詳細介紹下?
五、ROC和PR曲線之間的關系和不同
當正負樣本差距不大的情況下,ROC和PR的趨勢是差不多的,但是當負樣本很多的時候,兩者就截然不同了,ROC效果依然看似很好,但是PR上反映 效果一般。解釋起來也簡單,假設就1個正例,100個負例,那么基本上TPR可能一直維持在100左右,然后突然降到0.
ROC and precision-recall curves under class skew. (a) ROC curves, 1:1; (b) precision-recall curves, 1:1; (c) ROC curves, 1:10 and (d) precisionrecall
六、具體例子和代碼
(1)數據集
用的libsvm的那個270個樣本的數據集,用LR模型做了一下:
0.688312721844616 1
0.461679176682519 0
0.405016268379421 1
0.693999977303342 0
0.391868684948981 0
0.526391961908057 0
0.570470938139219 1
0.708771207269333 1
0.700976655664182 1
0.713584109310541 1
0.545180177320974 0
0.646156295395112 0
0.347580513944893 0
0.391577777998607 1
....
(2)ROC曲線和PR曲線
R語言的ROCR繪制的圖形:
代碼:
library(ROCR) a=read.table("toy.txt") a <- as.matrix(a) pred <- prediction(a[,1], a[,2]) perf <- performance(pred,"tpr","fpr") auc.tmp <- performance(pred,"auc") auc <- as.numeric(auc.tmp@y.values) auc <- round(auc, 4) plot(perf,colorize=TRUE,lwd=5,xlab="FPR",ylab="TPR", main=paste("AUC=",auc*100,"%")) grid(5, 5, lwd = 1) lines(par()$usr[1:2], par()$usr[3:4], lty=2, lwd=2, col="grey")
自己寫代碼繪制圖像和估算AUC的值,AUC和ROCR包計算的還是很接近的:
a <- read.table("toy.txt") a <- as.matrix(a) label <- a[,2] decision <- a[,1] ngrids <- 100 TPR <- rep(0, ngrids) FPR <- rep(0, ngrids) p0 <- rep(0, ngrids) for(i in 1:ngrids) { p0[i] <- i/ngrids pred_label <- 1*(decision > p0[i]) TPR[i] <- sum(pred_label * label) / sum(label) FPR[i] <- sum(pred_label * (1-label)) / sum(1-label) } ## compute AUC pos.decision <- decision[which(label == 1)] neg.decision <- decision[which(label == 0)] auc <- mean(sample(pos.decision,1000,replace=T) > sample(neg.decision,1000,replace=T)) ## or aucs <- replicate(2000,mean(sample(pos.decision,1000,replace=T) > sample(neg.decision,1000,replace=T))) auc2 <- round(mean(aucs),4) plot(FPR, TPR, col=4,lwd=5, type="l", main=paste("AUC=",auc2*100,"%")) grid(5, 5, lwd = 1) points(c(0,1), c(0,1), type="l", lty=2, lwd=2, col="grey") ## cut.op <- p0[which(TPR-FPR == max(TPR-FPR))]
PR曲線:
</pre> a <- read.table("toy.txt") a <- as.matrix(a) label <- a[,2] decision <- a[,1] ngrids <- 100 P <- rep(0, ngrids) R <- rep(0, ngrids) p0 <- rep(0, ngrids) A <- rep(0, ngrids) for(i in 0:ngrids) { p0[i] <- i/ngrids pred_label <- 1*(decision > p0[i]) R[i] <- sum(pred_label * label) / sum(label) P[i] <- sum(pred_label * label) / sum(pred_label) A[i] <- sum((pred_label == label)*1)/nrow(a) } plot(R, P, col=4,lwd=5, type="l",xlab="Recall",ylab="Precision", main="PR Curve") grid(5, 5, lwd = 1) accuracy <- max(A) <pre>
七、Reference
[1]Tom Fawcett:An introduction to ROC analysis
[2]Jesse Davis,Mark Goadrich:The Relationship Between Precision-Recall and ROC Curves
[3]https://en.wikipedia.org/wiki/Receiver_operating_characteristic
[4]http://baike.baidu.com/view/42249.htm
補充:當正負類樣本差數量距很大時,ROC的就不能很好的反應分類器的真實性能了,這時候PR將是更好的選擇。
證明:當FP的數量有比較大的變化時,FP_rate= FP / N 因為N很大,所以FP_rate不會有很大變化。
但是PR=TP /TP +FP ,它可以捕獲到這個差異,所以效果會更好。