举例说明 P-R图的计算 ROC曲线的计算 代价曲线的计算与绘制
以上三者都要求逐个把样本作为正例进行预测,模拟的是threshold设为不同值时同一个模型的预测效果
原理内容请参考《机器学习》周志华 2.3节。也可查看以下网址
模型评估与选择(后篇)-代价曲线
只需要在下面的模块中更改model_sequence里面的分类序列的顺序。以下为针对某一二分类问题的三个模型的P-R图、ROC曲线、代价曲线。
P-R图,如果模型A的P-R 图将模型B的P-R图完全包住,则A效果比B好。同时还要看BEP和F1值也可以用来比较模型效果。
ROC曲线,曲线下方面积为AUC,AUC越大,模型效果越好。曲线上方部分面积为loss,loss越小模型越好。模型A的ROC曲线如果完全把模型B的ROC曲线包在下方则模型A的效果比B好。如果两者并不是完全包含与被包含的关系,而是有重叠区域也有未重叠区域,则用AUC值比较。
代价曲线是在出现非平衡代价的情况下才使用的。所有曲线最下方的面积越小,则代表模型越好。
如下9幅图为3个模型对同一个样本的分类结果。第一行为model_1的P-R图、ROC曲线、代价曲线。第二行为model_2,第三行为model_3。三个model对比下来model_2效果最好。绘制过程见下文代码。
# 假设我们的样本是7个1和8个0. 1作为正例,0作为负例
model_1 = [1,1,0,1,0,1,1,0,0,0,1,0,0,1,0]
model_2 = [1,1,1,1,1,1,0,0,0,1,0,0,0,0,0]
model_3 = [1,1,0,1,1,1,1,0,0,0,1,0,0,0,0]
model_sequence = [model_1,model_2,model_3]
def PNTF(model_sequence, n):# 将第几个样本之前的全部作为正例。n是从1开始的,不是从0开始的
count = len(model_sequence)
class_1_count = sum(model_sequence)
class_0_count = count - class_1_count
if (n>count - 1) or (n<1):
return None
else:
TP = sum(model_sequence[0:n])
FN = class_1_count - TP
FP = n - TP
TN = class_0_count - FP
return TP,FN,TN,FP
def P_R(TP,FN,TN,FP):
P = TP/(TP+FP)
R = TP/(TP+FN)
F1 = 2*P*R/(P+R)
return P,R,F1
def ROC_TPR_FPR(TP,FN,TN,FP):
TPR = TP/(TP+FN)
FPR = FP/(TN+FP)
return TPR,FPR
def cost_curve_FPR_FNR(TP,FN,TN,FP):
TPR = TP/(TP+FN)
FNR = 1- TPR#假反率
FPR = FP/(TN+FP)
return FPR,FNR
#只是用于test
def PR_ROC_Cost_Curve_public_part(model_sequence,verbose = False):
length = len(model_sequence)
if verbose==True:
print('把前n个样本作为正例进行预测')
print('n\t','TP\t','FN\t','TN\t','FP\t','P\t','R\t','F1\t','TPR\t','FPR\t','FNR')
list_P_R_F1 = []
list_ROC_TPR_FPR = []
list_cost_curve_FPR_FNR = []
for i in range(length - 1):
TP,FN,TN,FP = PNTF(model_sequence,i+1)
P,R,F1 = P_R(TP,FN,TN,FP)
TPR,FPR = ROC_TPR_FPR(TP,FN,TN,FP)
FPR,FNR = cost_curve_FPR_FNR(TP,FN,TN,FP)
if verbose ==True:
print(i+1,'\t',TP,'\t',FN,'\t',TN,'\t',FP,'\t',round(P,3),'\t',round(R,3),'\t',round(F1,3),'\t',round(TPR,3),'\t',FPR,'\t',round(FNR,3))
list_P_R_F1.append([P,R,F1])
list_ROC_TPR_FPR.append([TPR,FPR])
list_cost_curve_FPR_FNR.append([FPR,FNR])
return list_P_R_F1,list_ROC_TPR_FPR,list_cost_curve_FPR_FNR
import matplotlib.pyplot as plt
import numpy as np
model_count = len(model_sequence)
fig,axis = plt.subplots(model_count,3,figsize = (8,8))
axis = axis.ravel()
count = 0
for i in range(model_count):
list_P_R_F1,list_ROC_TPR_FPR,list_cost_curve_FPR_FNR = PR_ROC_Cost_Curve_public_part(model_sequence[i])
array_P_R_F1 = np.array(list_P_R_F1)
P = array_P_R_F1[:,0]
R = array_P_R_F1[:,1]
axis[count].plot(R,P)
count +=1
array_ROC_TPR_FPR = np.array(list_ROC_TPR_FPR)
TPR = array_ROC_TPR_FPR[:,0]
FPR = array_ROC_TPR_FPR[:,1]
axis[count].plot(FPR,TPR)
count +=1
array_cost_curve_FPR_FNR = np.array(list_cost_curve_FPR_FNR)
FPR = array_cost_curve_FPR_FNR[:,0]
FNR = array_cost_curve_FPR_FNR[:,1]
for j in range(len(FPR)):
axis[count].plot((0,1),(FPR[j],FNR[j]),'b')
count +=1