晨间日记

ROC AUC 代价曲线

Tsukinousag

1.049

·

字数 933 · 阅读 44

2021-02-02 17:14

1.ROC(Receiver Operation Characteristic)

我们根据学习器的预测结果对样例进行排序,按此顺序逐个把样本作为正例进行预测,每次计算出两个重要量的值,与P—R曲线的使用查准率与查全率为纵,横轴不同,ROC曲线的纵轴是“真正例率(TPR,True Positive Rate)”,横轴是“假正例率(False Positive Rate)”.

2.AUC(Area Under ROC Curve)与rank—loss

进行学习器比较时,与P—R图相似,若一个学习器的ROC曲线被另一个学习器的曲线完全“包住”,则可以断言后者的性能优于前者;若两个学习器的ROC曲线发生交叉,则难以一般性地断言两者孰优孰劣,此时如果一定要进行比较,则较为合理的判断依据是比较ROC曲线下的面积,即AUC.

形象化地看,AUC考虑的是样本预测的排序质量,因此它与排序误差有紧密联系

若正例的预测值小于反例,则记1个罚分,若相等则记0.5个罚分(可以理解成线代里面的逆序对数量),那么rank—loss对应的是ROC曲线之上的面积

3.cost curve(代价曲线)

明确参数 : p=m+/m

目的:对于一个模型,根据p不同,找到使得代价总期望最小的模型的阈值

横轴:归一化的正概率代价期望

纵轴:归一化的总代价期望

大致过程:给定p,给定模型根据归一化代价期望的最小值

确定混淆矩阵的成分比例,阈值决定了这个比例,那如果这个比例确定了,阈值也就确定了,所以这时模型的阈值也对应确定下来了,也就是模型固定下来了

同时模型的综合考量指标P,R,F1,Fbeta等都确定下来了

4 .实例

4.1一个阈值对应一条直线

4.1.1 引入模型:

下面我们用实例来说明一个阈值对应一条直线,我们的例子是一个二分类问题,它是五还是不是五,样本是如图所示的十二张图片进入该分类器后,给其打分

评判标准:得分越高的越是五,得分越低的越不是五

4.1.2 代码试验:

import pandas as pd

import matplotlib as pml

import  matplotlib.pyplot as plt

#函数输出打分,从左到右分数依次增高

#1 2 3 4 5 6 7 8 9 10 11

output_score=list(range(12))

#正确分类,是五还是不是五

y=[0,0,0,0,1,0,1,1,0,1,1,1]

#p为样例是正例的概率(实际情况的正例率),取值范围[0,1],集合中正例的比例(m+/m),此时刚好为顺序排列

p=list(range(0,100,10))

p=[i/100 for i in p]

#[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]

#设定代价

c01=3

c02=2

#一个阈值

theta=6.5

#根据阈值和打分情况判断是5还是不是5,0代表是5,1代表是5

def calculate_output_result(output_score,theta):

    output_result=[]

    for i in range(len(output_score)):

        if output_score[i]

            output_result.append(0)#小于theta记为0

        else:

            output_result.append(1)#大于theta记为1

    return output_result

#output_result为我们自己的判断

output_result=calculate_output_result(output_score,theta)

#统计y中的正例(m+),反例(m-)个数

def calculate_m_positive_negtive(y):

#value_counts确认数据出现的频率。

    result = pd.value_counts(y)

    m_positive=result[0]

    m_negative=result[1]

    return m_positive,m_negative

m_positive,m_negative=calculate_m_positive_negtive(y)

#m_positive=6,m_negative=6

#output_result为[0,0,0,0,0,0,0,1,1,1,1,1]为预测分类

#y为[0,0,0,0,1,0,1,1,0,1,1,1]为正确分类

#然后根据我们预测的值去计算混淆矩阵

def calculate_confusion(y,output_result):

    TP=0

    FN=0

    FP=0

    TN=0

    for i in range(len(y)):

        if y[i]==1:

            if y[i]==output_result[i]:

                TP+=1

            else:

                FN+=1

        else:

            if y[i]==output_result[i]:

                TN+=1

            else:

                FP+=1

    return TP,FN,FP,TN

TP,FN,FP,TN=calculate_confusion(y,output_result)

#计算得TP,FN,FP,TN分别为4 2 1 5

#求几个比例,保留四位小数

def calculate_FNR_FPR(TP,FN,FP,TN):

    FNR=round(FN/(FN+TP),4)

    FPR=round(FP/(FP+TN),4)

    return FNR,FPR

FNR,FPR=calculate_FNR_FPR(TP,FN,FP,TN)

#FNR为0.333 FTR为0.1667

#计算 正概率代价(横轴)

def calculate_Pcost(p,c01,c02):

    Pcosts=[]

    for i in range(len(p)):

        Pcost=round(p[i]*c01/(p[i]*c01+(1-p[i])*c02),4)

        Pcosts.append(Pcost)

    return Pcosts

Pcosts=calculate_Pcost(p,c01,c02)

#Pcosts为:[0.0, 0.1429, 0.2727, 0.3913, 0.5, 0.6, 0.6923, 0.7778, 0.8571, 0.931]

#计算 归一化总概率(纵轴)

def calculate_cost_norm(p,c01,c02,FNR,FPR):

    costs_norm=[]

    for i in range(len(p)):

        cost_norm=round((FNR*p[i]*c01+FPR*(1-p[i])*c02)/(p[i]*c01+(1-p[i])*c02),4)

        costs_norm.append(cost_norm)

    return  costs_norm

costs_norm=calculate_cost_norm(p,c01,c02,FNR,FPR)

#costs_norm为:[0.1667, 0.1905, 0.2121, 0.2319, 0.25, 0.2667, 0.282, 0.2963, 0.3095, 0.3218]

#画出图像,对比两种不同的横轴下的图像

def plot_lines(X,Y,color):

    plt.plot(X,Y,color)

    return

plot_lines(Pcosts,costs_norm,'r')

plot_lines(p,costs_norm,"b:")

plt.show()

4.1.3 实验结果:

4.1.4 反思:

1.如果我们使用Pcosts作为横轴,得出的是红色直线,而以p作为横轴,得出的是紫色弯曲虚线,不是一个线性关系,虽然我们想要的就是已知某一个p,我们到底应该对应哪一条曲线的θ值更好,但是不能拿p当横轴,因为其返回曲线是非线性的,不利于我们分析。

2.当p等于0时Pcosts等于0,cost_norm=FPR;当p等于1时Pcosts等于1,cost_norm=FNR

3.p的含义:连接两点的线段如何用参数方程表示?假设两点分别是A,B,如果想表示AB连线所有点的集合用λA+(1-λ)B,λ∈[0,1],通过λ的变化,我们可以得到线段AB。、

4.2 多条直线围成代价敏感曲线

生成多个阈值下的曲线

4.2.1代码实验

import pandas as pd

import matplotlib as pml

import  matplotlib.pyplot as plt

#函数输出打分,从左到右分数依次增高

#1 2 3 4 5 6 7 8 9 10 11

output_score=list(range(12))

#正确分类,是五还是不是五

y=[0,0,0,0,1,0,1,1,0,1,1,1]

#p为样例是正例的概率(实际情况的正例率),取值范围[0,1],集合中正例的比例(m+/m),此时刚好为顺序排列

p=list(range(0,100,10))

p=[i/100 for i in p]

#[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]

#设定代价

c01=3

c02=2

#根据阈值和打分情况判断是5还是不是5,0代表是5,1代表是5

def calculate_output_result(output_score,theta):

    output_result=[]

    for i in range(len(output_score)):

        if output_score[i]

            output_result.append(0)#小于theta记为0

        else:

            output_result.append(1)#大于theta记为1

    return output_result

#统计y中的正例(m+),反例(m-)个数

def calculate_m_positive_negtive(y):

#value_counts确认数据出现的频率。

    result = pd.value_counts(y)

    m_positive=result[0]

    m_negative=result[1]

    return m_positive,m_negative

def calculate_confusion(y,output_result):

    TP=0

    FN=0

    FP=0

    TN=0

    for i in range(len(y)):

        if y[i]==1:

            if y[i]==output_result[i]:

                TP+=1

            else:

                FN+=1

        else:

            if y[i]==output_result[i]:

                TN+=1

            else:

                FP+=1

    return TP,FN,FP,TN

#求几个比例,保留四位小数

def calculate_FNR_FPR(TP,FN,FP,TN):

    FNR=round(FN/(FN+TP),4)

    FPR=round(FP/(FP+TN),4)

    return FNR,FPR

#计算 正概率代价(横轴)

def calculate_Pcost(p,c01,c02):

    Pcosts=[]

    for i in range(len(p)):

        Pcost=round(p[i]*c01/(p[i]*c01+(1-p[i])*c02),4)

        Pcosts.append(Pcost)

    return Pcosts

#计算 归一化总概率(纵轴)

def calculate_cost_norm(p,c01,c02,FNR,FPR):

    costs_norm=[]

    for i in range(len(p)):

        cost_norm=round((FNR*p[i]*c01+FPR*(1-p[i])*c02)/(p[i]*c01+(1-p[i])*c02),4)

        costs_norm.append(cost_norm)

    return  costs_norm

######################################################

#生成多个θ的时候

thetas=list(range(12))

thetas=[i+0.5 for i in thetas]

#生成12个θ:[0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5]

#计算每个θ对应的点的函数,并存在列表里

def calculate_Pcost_cost_norm(thetas,output_score,y,calculate_Pcost,calculate_cost_norm):

    Pcosts_n=[]

    costs_norm_n=[]

    theta_FPR_FNR={}

    for i in range(len(thetas)):

        theta=thetas[i]

        #计算输出结果

        output_result=calculate_output_result(output_score,theta)

        #统计正反例个数

        m_positive,m_negative=calculate_m_positive_negtive(y)

        #计算混淆矩阵

        TP,FN,FP,TN=calculate_confusion(y,output_result)

        #计算FNR,FPR

        FNR,FPR=calculate_FNR_FPR(TP,FN,FP,TN)

        theta_FPR_FNR[theta]=[FNR,FPR]

        #正概率代价

        Pcosts=calculate_Pcost(p,c01,c02)

        Pcosts_n.append(Pcosts)

        #归一化总概率

        costs_norm=calculate_cost_norm(p,c01,c02,FNR,FPR)

        costs_norm_n.append(costs_norm)

    return Pcosts_n,costs_norm_n,theta_FPR_FNR

#调用函数计算每个θ对应的点

Pcosts_n,costs_norm_n,theta_FNR_FPR=calculate_Pcost_cost_norm(thetas,output_score,y,calculate_Pcost,calculate_cost_norm)

#画图

def plot_lines(X,Y,color):

    plt.plot(X,Y,color)

    return

for i in range(len(Pcosts_n)):

    plot_lines(Pcosts_n[i],costs_norm_n[i],'r')

plt.show()

4.2.2 实验结果

机器学习

2

谢谢老板

赞赏支持

相关推荐

GSEA背后的统计学原理

阅读 284

PCA分析中的PC1指代什么

阅读 170

理解DESeq2的标准化步骤

阅读 755

【转录组07】样本表达分布、相关性分析&差异表达分析

阅读 722

相关性分析 | R语言 -- 相关性矩阵及可视化

阅读 654

你可能感兴趣的:(列表,python,机器学习,深度学习,人工智能)