画交叉验证的ROC曲线,多个样本不同的ROC重叠。

最近在画交叉验证的ROC曲线。由于我采用的是留一法来做10折交叉,这就导致我每一折的样本数量是不固定的,但我又想画一个平均的校验验证性能曲线,并且把置信区间也画出来,找了很久资料,我画了一个这样的。先看效果图,如下图:画交叉验证的ROC曲线,多个样本不同的ROC重叠。_第1张图片
中间蓝色的是平均的ROC,周围蓝色的带是所有的交叉验证触及的最大范围。因为交叉验证需要多次抽样,但我用的是深度学习,很难做到抽样,所以就用最大范围代替置信区间。具体做法如下:

from my_utils.utils import *
from sklearn.metrics import auc, plot_roc_curve, roc_curve
import my_utils.file_util as fu
import matplotlib.pyplot as plt
class_type = '1p19q'
#图表的保存路径
save_path = ''
#存放所有交叉验证的预测结果和label的文件路径
record_dir  = ''
#find_file是我自己写的寻找路径下所有best-auc.csv文件的函数,用的时候可以替换成自己的
#返回的是所有csv文件的绝对路径。文件格式是第一和第二列是预测值,第三列label。
#因为我用的是one hot做二分类,所以有两个值
flods_dir = find_file(record_dir, 2,1, suffix='best_auc.csv')
pre_record = []
#获取所有交叉验证的预测值和label
for record_file in flods_dir:
    temp = fu.csv_reader(record_file)
    temp_fold_record = []
    #因为是二分类,所有只取第一个预测值,第二个不要
    temp_fold_record.append([i[0] for i in temp])
    #取label值
    temp_fold_record.append([i[2] for i in temp])
    pre_record.append(temp_fold_record)

roc_record, value, fpr, tpr = [], [], [], []

for record in pre_record:
    label = np.array([int(i) for i in record[1]]).squeeze()
    pred = np.array([float(i) for i in record[0]]).squeeze()
    #计算roc曲线
    t_fpr, t_tpr, thre = roc_curve(label, 1-pred)
    #计算AUC
    auc_score = auc(t_fpr, t_tpr)
    fpr.append([float(i) for i in t_fpr])
    value.extend([float(i) for i in t_fpr])
    tpr.append([float(i) for i in t_tpr])

mean_fpr, min_fpr, max_fpr = [],[],[]
mean_tpr, min_tpr, max_tpr= [],[],[]
#这个是为了对曲线进行插值,因为每个曲线的样本不一样,所以获取到的fpr和tpr也不一样长度,
#所以需要进行插值
#插值的原理是,获取所有fpr的值,然后将每个交叉验证的roc都插值成和fpr的值一样多的长度。
#插值并不会改变每个roc曲线的形状,这个可以放心使用
unique = np.unique(np.array(value).flatten())
#对fpr和tpr进行插值
for l in range(len(fpr)):
    tpr[l] = np.interp(unique, fpr[l], tpr[l], 0, 1)
    fpr[l] = np.interp(unique, fpr[l], fpr[l], 0, 1)
    #将每个交叉验证的ROC都画出来
    plt.plot(fpr[l], tpr[l])

fpr = np.array(fpr)
tpr = np.array(tpr)
#求fpr和tpr的极大极小,获取每个实验所能触及的最大指标范围
min_fpr = np.min(fpr, axis=0)
max_fpr = np.max(fpr, axis=0)
min_tpr = np.min(tpr, axis=0)
max_tpr = np.max(tpr, axis=0)
#获取均值,为了得到交叉验证的平均曲线
mean_tpr = np.mean(tpr, axis=0)
mean_fpr = np.mean(fpr, axis=0)
mean_tpr[0] = 0

plt.figure(dpi=300)
plt.title(class_type)
plt.style.use('seaborn')
plt.xlabel('1-Specificity')
plt.ylabel('Sencitivity')
#画平均曲线
p1 = plt.plot(mean_fpr, mean_tpr, marker='.', 
        linestyle='--',c='b', linewidth=1,
         alpha=0.65, label='20X')#markeredgecolor='b',

plt.legend(loc='lower right')
#将极大极小值的范围填充淡蓝色
p2 = plt.fill_between(min_fpr,max_tpr, min_tpr,color='blue', alpha=0.08)
#展示图象
plt.show()

下面附上每个交叉验证的图像来验证范围画的对不对。
画交叉验证的ROC曲线,多个样本不同的ROC重叠。_第2张图片
再对比我们画的画交叉验证的ROC曲线,多个样本不同的ROC重叠。_第3张图片
可以看到啊,我们画的范围与所有ROC的曲线的范围是吻合的,平均曲线也像模像样。

你可能感兴趣的:(医疗图像处理,可视化,python,机器学习,ROC,可视化,交叉验证)