ROC曲线 1
ROC曲線
http://www.datakit.cn/blog/2015/02/03/ROC_curve.html
在分類預測中,我們一般比較關注準確率,但是,混淆矩陣也是非常重要的。尤其是當我們都其中的某一類別特別感興趣的時候,通常要單獨的看這個類別的召回率和精度,比如在癌癥診斷過程中,我們寧愿錯誤的認為一個人是癌癥,也不愿意把一個癌癥錯誤的認為是正常人。本文以二元分類為例,分析ROC曲線及相關知識。
目錄
- 1、混淆矩陣
- 2、ROC曲線
- 3、ROC代碼
1、混淆矩陣
混淆矩陣如下圖所示,就是把實際的類別和預測類別做一一對應,看看各個類別下正確預測了多少,錯誤預測了多少。在一些不平衡數據集中,一般認為稀有類別更有意義,通常計為正類,比如根據一系列指標,判斷一個人是否是癌癥,這種數據集中,癌癥的人數是少數,即稀有類,標為正類。
在混淆矩陣中,有一些比較常用的量,但是不同的教材翻譯也不一樣,我一般都直接使用英文來理解混淆矩陣里的量,中文翻譯里,我用的比較多的是召回率和精度。這個矩陣也比較容易記憶,就是預測的結果是P(positive)和N(negative),如果符合實際值就是T(True),不符合實際值就是F(False)。因此FN是指false negative,也就是錯誤預測為負樣本的數(實際應該是正樣本)。所以,組合成了里面的各個字符,比如TP,TN等等。那么準確率就是分類正確(即以T開頭的)的除以總數,即(TP + TN)/(FP + TN + FP + FN)。這里額外說一些指標,也方便復習。
- 特指度(specificity),即真負率(true negative rate) TNP = TN / (TN+FP), 是指被模型正確預測的負樣本比例。
- 召回率(recall) r = TP / (TP + FN),度量了被分類器正確預測的正樣本比例。
- 精度(precision) p = TP / (TP + FP),指在分類器斷言為正類的樣本中實際為正類的比例。
在分類過程中,我們通常都可以通過調整閾值來調整這些值。比如還是癌癥的例子,假設實際患癌癥的比例是1%,使用貝葉斯分類,一般認為是癌癥的比例大于0.5,就認為他是癌癥。這樣雖然準確率達到了最大,但是,對我們的目標而已,沒有任何作用,比如我們都預測樣本是非患者,那么準確率就是99%了。我們更關注癌癥患者的召回率,即提高癌癥患者的召回率,也就是能夠把所有的癌癥患者全部給預測出來。那么我們就需要降低閾值,即認為如果一個患癌癥的概率大于0.1 或者0.01時,就認為他是癌癥患者。這樣,就會導致大量的非癌癥患者被認定為癌癥患者,但是同時也不容易漏掉一些真正的癌癥患者。連接到混淆矩陣,就是我們提高了預測為positive的比例,使得TP和FP的都提升了,這樣獲得了高的召回率(小于1的正分數,分子分母都加一個正整數,分數值增大),犧牲了準確率(多數情況下,也犧牲了精度)。同樣,在垃圾郵件中,我們可能會選擇提供閾值,這樣可以達到盡可能的不把正常的郵件認定為垃圾郵件。
我們希望構建的模型,具有很高的召回率和精度的分類模型。另外,我們也有一個度量可以把這兩個指標合并在一起,即$$F_1 = \frac{2rp}{r + p} = \frac{1}{\frac{1}{r} + \frac{1}{p}},是召回率和精度的調和平均值,會傾向于比較小的那個數。
2、ROC曲線
ROC曲線(receiver operating characteristic curve,受試者工作特征曲線)是顯示分類器真正率(TPR)和假正率(FPR)之間折中的一種圖形化方法。一個好的分類模型應該盡可能的靠近ROC曲線的左上角如果隨機猜測的話,那么TPR和FPR會一直相等,最終曲線是主對角線。另外,我們也可以用曲線下的面積,來表示一個模型的平均表現。
那么我們如何繪制ROC曲線呢?思路比較簡單,就是把得到的概率值和類別按照概率值排序。之后不斷的調整閾值(從高到低,1到0),看看每個閾值對應的TPR和FPR,之后繪圖就可以了。當然,直接使用概率值作為閾值是為了繪圖的連續性。我們也可以選擇閾值為0-0.1…-1.0一共11個閾值,之后計算這些閾值對應的TPR和FPR,得到十一個點,進行繪圖。這里我做了兩個roc的代碼。第一個里面是把準確率計算在內了,這樣方面我們確定最高準確率對應的閾值,當然我是想看看所有的閾值對應的準確率,所以最后用了排序。如果只是為了得到最好的,那么過程中,增加一個比較就可以了。第二個里面,純粹是為了得到roc曲線。注意,有些時候,為了方便查看,繪圖的時候坐標軸也不是非要在0和1,也可以設定為0.1-0.3等等區間。進行對比。
3、ROC代碼
def roc1(scores):# scores[0][1] is predict# scores[0][0] is the targetm = len(scores)pos_num = sum([i[0] for i in scores])neg_num = m - pos_numfp, tp = [], []FP, TP = 0, 0# decent the scores scores = sorted(scores, key=lambda x:x[1], reverse=True)accs = []for n,s in enumerate(scores):TP = len([i for i in scores[0:n] if i[0] == 1])TN = len([i for i in scores[n:] if i[0] == 0])FP = len([i for i in scores[0:n] if i[0] == 0])accs.append([float(TP+TN)/m, s[1]]) fp.append(float(FP) / neg_num)tp.append(float(TP) / pos_num)fp.append(1)tp.append(1)# get the best thesholdaccs = sorted(accs, reverse=True) return fp, tp, accs[0]def roc2(scores):# scores[0][1] is predict# scores[0][0] is the targetm = len(scores)pos_num = sum([i[0] for i in scores])neg_num = m - pos_numfp, tp = [], []FP, TP = 0, 0# decent the scores scores = sorted(scores, key=lambda x:x[1], reverse=True)threshold = 1.0for s in scores: if s[1] < threshold:fp.append(float(FP) / neg_num)tp.append(float(TP) / pos_num)if s[0] == 1:TP += 1else:FP += 1fp.append(1)tp.append(1)return fp, tp scores = [[1, 0.2], [1, 0.8], [1,0.89], [1, 0.98],[0, 0.1], [0, 0.3], [0,0.34], [0, 0.56]]fp1, tp1, accs1 = roc1(scores) fp2, tp2 = roc2(scores)總結
- 上一篇: python使用esmre代替ahoco
- 下一篇: 自动摘要算法