Python 这个ROC曲线有意义吗?

Python 这个ROC曲线有意义吗?,python,deep-learning,statistics,roc,auc,Python,Deep Learning,Statistics,Roc,Auc,此代码返回并基于预测值和真值绘制真阳性率、假阳性率、真阳性计数、假阳性计数: def get_all_stats(y_true , y_pred) : def perf_measure(y_true, y_pred): TP = 0 FP = 0 TN = 0 FN = 0 for i in range(len(y_true)): if y_true[i] == 1 and

此代码返回并基于预测值和真值绘制真阳性率、假阳性率、真阳性计数、假阳性计数:

def get_all_stats(y_true , y_pred) : 

    def perf_measure(y_true, y_pred):

        TP = 0
        FP = 0
        TN = 0
        FN = 0

        for i in range(len(y_true)): 
            if y_true[i] == 1 and y_pred[i] == 1:
                TP += 1
            if y_pred[i]==1 and y_true[i]!=y_pred[i]:
                FP += 1
            if y_true[i]== 0 and y_pred[i]==0:
                TN += 1
            if y_pred[i]==0 and y_true[i] != y_pred[i]:
                FN += 1

        if(FP == 0) : 
            FPR = 0;
        else : 
            FPR = FP / (FP + TN)

        if(TP == 0) : 
            TPR = 0
        else : 
            TPR = TP / (TP + FN)

        return(TN , FPR, FN , TPR , TP , FP)

    tn, fpr, fn, tpr, tp , fp = perf_measure(y_true, y_pred)

    return tpr , fpr , tp , fp

tpr1 , fpr1 , tp1 , fp1 = get_all_stats(y_true=[1,1,1] , y_pred=[1,0,0])
tpr2 , fpr2 , tp2 , fp2 = get_all_stats(y_true=[1,0,1] , y_pred=[0,1,0])
tpr3 , fpr3 , tp3 , fp3 = get_all_stats(y_true=[0,0,0] , y_pred=[1,0,0])

plt.figure(figsize=(12,6))
plt.tick_params(labelsize=12)

print(tpr1 , fpr1 , tp1 , fp1)
print(tpr2 , fpr2 , tp2 , fp2)
print(tpr3 , fpr3 , tp3 , fp3)

plt.plot([fpr1,fpr2,fpr3], [tpr1 , tpr2, tpr3], color='blue', label='')
plt.ylabel("TPR",fontsize=16)
plt.xlabel("FPR",fontsize=16)
plt.legend()
生成的ROC图为:

为了模拟三种不同的假阳性率和真阳性率以及不同的阈值,通过实现函数
get_all_stats
三次以不同的方式计算这些值

tpr1 , fpr1 , tp1 , fp1 = get_all_stats(y_true=[1,1,1] , y_pred=[1,0,0])
tpr2 , fpr2 , tp2 , fp2 = get_all_stats(y_true=[1,0,1] , y_pred=[0,1,0])
tpr3 , fpr3 , tp3 , fp3 = get_all_stats(y_true=[0,0,0] , y_pred=[1,0,0])
有9个实例被分类为1或0,其中真值为:
[1,1,1,1,0,1,0,0]

在阈值1处,预测值为
[1,0,0]
,其中该阈值处的真值为
[1,1,1]

在阈值2处,预测值为
[0,1,0]
,其中该阈值处的真值为
[1,0,1]

在阈值3处,预测值为
[1,0,0]
,其中该阈值处的真值为
[0,0,0]

如图所示,所生成分类器的生成图不同于“典型”ROC曲线:


当它首先下降,然后假阳性率和真阳性率下降,导致线路“向后移动”。我是否正确实施了ROC曲线?可以为这条曲线计算AUC吗?

好的,因为你有很多代表->帮助了很多其他人,所以你有动力去帮助别人。我们开始吧

这个ROC曲线没有意义。问题在于,您只在不同阈值下计算数据子集的FPR/TPR。在每个阈值处,您应该使用所有数据来计算FPR和TPR。因此,您的绘图中似乎有3个点,但对于
y_true=[1,1,1,1,0,1,0,0,0]
y_pred=[1,0,0,0,1,0,0]
,您应该只有一个点具有FPR/TPR。但是,为了确保您有一个实际的ROC曲线,您也不能仅仅在不同的阈值上组成
y_pred
值-这些值需要来自实际的预测概率,然后对其进行适当的阈值化。我修改了你的代码,因为我喜欢使用
numpy
;下面是计算ROC曲线的方法

#从真正的标签开始,就像你做的那样
y_true=np.数组([1,1,1,1,0,1,0,0])
#以及每一个都是“1”的预测概率
#我只是用了随机数,但你会得到的
#从你的分类器
预测=np.array([
0.07485627, 0.72546085, 0.60287482,
0.90537829, 0.75789236, 0.01852192,
0.85425979, 0.36881312, 0.63893516
])
#现在定义一组阈值(阈值越多越好)
#这条曲线将看起来很好)。在实践中,有一种更聪明的方法可以做到这一点
#(您可以对预测的概率进行排序,只需要一个阈值
#但这只是为了帮助理解
阈值=np.linspace(0,1,11)#0.1,0.2,…,1.0
fprs=[]
tprs=[]
#我们可以预先计算哪些输入实际上是1s/0s,以及每个输入有多少个
true\u 1\u idx=np。其中(y\u true==1)[0]
true\u 0\u idx=np。其中(y\u true==0)[0]
n\u true\u 1=len(true\u 1\u idx)
n\u true\u 0=len(true\u 0\u idx)
对于阈值中的阈值:
#现在,对于每一个阈值,我们使用它来计算潜在的概率
#以获得实际的预测类
预测类=预测>=阈值
#并根据这些数据计算FPR/TPR
tprs.append((pred_类[true_1\u idx]==1.sum()/n_true_1)
fprs.append((pred_类[true_0\u idx]==1.sum()/n_true_0)
plt.图(figsize=(12,6))
plt.勾选参数(标签大小=12)
plt.绘图(fprs、tprs、颜色=‘蓝色’)
plt.ylabel(“TPR”,fontsize=16)
plt.xlabel(“FPR”,fontsize=16)

注意,随着FPR(x轴)的增加,ROC曲线在TPR(y轴)中始终不递减;也就是说,当你向右移动时,它向上移动。从阈值设置的工作原理可以清楚地看出这一点。阈值为0时,所有预测都是“1”,因此我们得到FPR=TPR=1。增加阈值会减少对“1”的预测,因此FPR和TPR只能保持不变或降低

注意,即使我们使用了最佳阈值,曲线中仍然存在跳跃,因为我们有有限的数据量,所以我们可以使用任何阈值获得有限数量的不同TPR/FPR对。但是,如果您有足够的数据,那么这就开始看起来很顺利了。在这里,我替换了上面代码中的几行,以获得更平滑的绘图:

n_点=1000
y_true=np.random.randint(0,2,size=n_点)
预测=np.random.random(n_点)
阈值=np.linspace(0,1,1000)

如果不清楚的话,AUC为0.5是最糟糕的,你可以看到这就是我们随机“预测”得到的结果。如果您的AUC低于0.5,您可以将每个预测都翻转到高于0.5(并且您的模型/培训可能有问题)


如果你真的想在实践中绘制ROC曲线,而不仅仅是自己写来学习更多,使用sklearn。他们还必须为你获得AUC。

好的,积极帮助,因为你有很多代表->帮助了很多其他人。我们开始吧

这个ROC曲线没有意义。问题在于,您只在不同阈值下计算数据子集的FPR/TPR。在每个阈值处,您应该使用所有数据来计算FPR和TPR。因此,您的绘图中似乎有3个点,但对于
y_true=[1,1,1,1,0,1,0,0,0]
y_pred=[1,0,0,0,1,0,0]
,您应该只有一个点具有FPR/TPR。但是,为了确保您有一个实际的ROC曲线,您也不能仅仅在不同的阈值上组成
y_pred
值-这些值需要来自实际的预测概率,然后对其进行适当的阈值化。我修改了你的代码,因为我喜欢使用
numpy
;下面是计算ROC曲线的方法

#从真正的标签开始,就像你做的那样
y_true=np.数组([1,1,1,1,0,1,0,0])
#以及每一个都是“1”的预测概率
#我只是用了随机的