美文网首页
模型评价 ROC AUC python实现

模型评价 ROC AUC python实现

作者: Mrcwx | 来源:发表于2018-06-28 19:57 被阅读0次

    ROC曲线:

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


    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实现

          本文链接:https://www.haomeiwen.com/subject/aklnyftx.html