模型评价 ROC AUC python实现

ROC曲线:

    在逻辑回归里面,我们会设一个阈值,大于这个值的为正类,小于这个值为负类。如果我们减小这个阀值,那么更多的样本会被识别为正类。这会提高正类的识别率,但同时也会使得更多的负类被错误识别为正类。为了形象化这一变化,在此引入 ROC ,ROC 曲线可以用于评价一个分类器好坏。


模型评价 ROC AUC python实现_第1张图片
ROC.png

如何绘制的呢

横坐标: false positive rate (TPR = TP/(TP+FN)) 表示(实际负样本预测为正样本个数)/(实际样本中负样本个数)
例如:3个样本(0.4,0)(0.2,0)(0.8,1) 0 代表负样本 1正样本, 如果设置阈值0.4,则(0.4,0) 实际负样本预测为正样本,(0.2,0)实际负样本预测为负样本 ,(0.8,1)实际正样本预测为正样本,false positive rate=1/2=0.5

纵坐标:true positive rate (FPR = FP/(TN+FP))表示(实际正样本预测为正样本个数)/(实际样本中正样本个数)
上面例子中 true positive rate = 1/1 = 1

详细计算过程

例给出的数据如下

y = np.array([0, 0, 1, 1])
scores = np.array([0.1, 0.4, 0.35, 0.8])

score即各个样本属于正例的概率。

针对score,将数据排序

样本 预测属于P的概率(score) 真实类别
y[0] 0.1 N
y[2] 0.3 P
y[1] 0.4 N
y[3] 0.8 P

阈值依次取score值

依次取值为0.1,0.3,0.4,0.8时,计算ROC曲线横纵坐标的结果。

阈值为0.1

只要score>=0.1,它的预测类别就是正例。
此时,因为4个样本的score都大于等于0.1,所以,所有样本的预测类别都为P。
TPR = TP/(TP+FN) = 1
FPR = FP/(TN+FP) = 1
横纵坐标均为1

阈值为0.3

只要score>=0.3,它的预测类别就是P。
此时,因为4个样本的score有3个大于等于0.3。所以,所有样本的预测类有3个为P(2个预测正确,1一个预测错误),1个样本被预测为N(预测正确)。
TPR = TP/(TP+FN) = 1
FPR = FP/(TN+FP) = 0.5

阈值为0.4

只要score>=0.4,它的预测类别就是P。
此时,因为4个样本的score有2个大于等于0.4。所以,所有样本的预测类有2个为P(1个预测正确,1一个预测错误);2个样本被预测为N(1个预测正确,1一个预测错误)。
TPR = TP/(TP+FN) = 0.5
FPR = FP/(TN+FP) = 0.5

阈值为0.8

说明只要score>=0.8,它的预测类别就是P。所以,所有样本的预测类有1个为P(1个预测正确);3个样本被预测为N(2个预测正确,1一个预测错误)
TPR = TP/(TP+FN) = 0.5
FPR = FP/(TN+FP) = 0

python 实现

#读数据,用db保存带正负标签数据,pos统计正样本个数,neg统计负样本个数
#举例 line 格式 [0.3,0] 则db处理成[0.3,1,0]  第db[1],db[2]位分别代表是否正负样本,为后面get_roc计算准备
def read_file(file_path, accuracy=2):
    db = []  #(score,nonclk,clk)
    pos, neg = 0, 0 #正负样本数量
    #读取数据
    with open(file_path,'r') as fs:
        for line in fs:
            temp = eval(line)
            #精度可控
            #score = '%.1f' % float(temp[0])
            score = float(temp[0])
            trueLabel = int(temp[1])
            sample = [score, 0, 1] if trueLabel == 1 else [score, 1, 0]
            score,nonclk,clk = sample
            pos += clk #正样本
            neg += nonclk #负样本
            db.append(sample)
    return db, pos, neg

def get_roc(db, pos, neg):
    #按照输出概率,从大到小排序
    db = sorted(db, key=lambda x:x[0], reverse=True)
    file=open('data.txt','w')
    file.write(str(db))
    file.close()
    #计算ROC坐标点
    xy_arr = []
    tp, fp = 0., 0.

#已经从大到小排序   i表示以第i个数作为阈值, tp表示第i个数前面实际为正样本预测为正样本个数,fp表示第i个数前面实际为负样本预测为正样本个数
    for i in range(len(db)): 
        tp += db[i][2]
        fp += db[i][1]
        xy_arr.append([fp/neg,tp/pos])#计算出横纵坐标
    return xy_arr

def get_AUC(xy_arr):
    #计算曲线下面积
    auc = 0.
    prev_x = 0
    for x,y in xy_arr:
        if x != prev_x:
            auc += (x - prev_x) * y
            prev_x = x
    return auc

def draw_ROC(xy_arr):
    x = [_v[0] for _v in xy_arr]
    y = [_v[1] for _v in xy_arr]
    pl.title("ROC curve of %s (AUC = %.4f)" % ('clk',auc))
    pl.xlabel("False Positive Rate")
    pl.ylabel("True Positive Rate")
    pl.plot(x, y)# use pylab to plot x and y
    pl.show()# show the plot on the screen
image.png

你可能感兴趣的:(模型评价 ROC AUC python实现)