引言

一般我们会在研究中验证某个特征的有效性,会使用该特征对病例个样本进行二分类,通常回选择支持向量机(SVM),这里的目的并非一定要得到很高的正确率,更多地只是想说明该特征可以区分case组和control组。

留一法 or 留一对法?

因为样本量的原因,一般是使用留一法进行多重比较校正,但是有时候也会被要求使用留一对的方法,简单的就是每一次从case中拿出一例,然后从control中拿出一例,使用剩余的(m+n)- 2的样本进行训练,对取出的样本(一个来自case一个来自control)进行测试。

但是你可能会想case组有m个样本,control组有n个样本,两组人的数量不一样(m≠n)要怎么处理呢?

  1. 首先k=m<n?m:n(选取二者中较小的一个数)
  2. 一共进行k次随机取样本,训练模型,分类,得到分类正确率
  3. 然后重复步骤(1,2)N次,就会得到多个准确率和多条ROC曲线。
  4. 你可能会问为什么要重复这多(N)次?因为这m和n不相等,进行k次抽样,肯定会导致有一些样本(样本量大的那一组有样本无法被抽中成为测试集),因此通过重复N次来较少这个因素。

具体如何实现留一对?leave one pair out?

在我以前的博客中已经介绍了如何使用留一法的SVM,具体见留一法SVM,可以借助sklearn.model_selection中的LeaveOneGroupOut实现,该函数可以根据组别(可以理解为每一个样本有一个所属组的编号)将数据分成与组别相同的组数,比如我有20个样本,这20个样本根据性别可以分为2组。在后续的多重比较校正中每一次取出其中的一组作为测试集,剩余组作为训练集即可。leave one pair out 是上述过程的一个特例(因为在对两组人进行分类时,可能会有需求每次将类别1和类别2同时拿出来一个作为测试集),因此接祖leaveOneGroupOut,我们只需要对两组人进行分别编号,然后编号对应时作为一组,具体实现过程如下:

# 该方法是每次排除一个组,怎样才能每次排除一对?那就是正常组和病人组对应配对?
pair_data1 = [i for i in range(np.size(data1_label,0))]
pair_data2 = [i for i in range(np.size(data2_label,0))]
# 随机打乱分组
random.shuffle(pair_data1)
random.shuffle(pair_data2)
pair = pair_data1+pair_data2
loo = LeaveOneGroupOut()
loo.get_n_splits(dataset,groups=pair)
...
for train_index, test_index in loo.split(dataset,groups=pair):X_train, X_test = dataset[train_index], dataset[test_index]Y_train, Y_test = np.array(datalabels)[train_index], np.array(datalabels)[test_index]...

上述代码说明

  1. 首先将data1进行编号0:M-1,然后对N进行编号0:N-1,数字为组别
  2. 之后对组别进行打乱,打乱的组别(后续说明为什么打乱)
  3. 然后将分组编号合并(前面为data1的组别,后面为data2的组别)
  4. 然后将样本特征及其对应的分组编号作为参数输入到LeaveOneGroupOut的get_n_splits中,其实上述过程会将数据分成max(M,N)份,如果M与N的大小不一样的话,整个过程会出现leave one out 的情况(后续会对此进行处理)

特殊处理说明

  1. 因为编号是由小到大,因此当编号小于min(M,N)时程序都能正常的leave one pair out,当编号大于等于min(M,N)时只能得到一个一个样本,此时在代码中加入判断条件跳出循环,就可以了。代码如下:
print(test_index)if np.size(X_test,0)==1:print('条件不满足,跳出循环!')break
  1. 为什么需要随机打乱?因为两组人的数量可能不同,分组的方式也不唯一,因此需要随机打乱来排除这种认为分组方式对结果的影响,因此每次代码的运行分组的方式都是不一样的,可以通过多运行几次来减小分组带来的误差,同时可以借此判断结果是否稳定。

完整实现代码


"""
Created on Wed Sep  9 10:06:14 2020@author: Administer
"""import numpy as np
from sklearn.model_selection import LeaveOneOut
from sklearn.model_selection import LeaveOneGroupOut
import scipy.io as scio
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
import random###################功能性函数###################################################
# 将一个任意嵌套的列表整理为一个列表
def flatten(nested):try:for sublist in nested:for element in flatten(sublist):yield elementexcept TypeError:yield nested# 读取一个txt文件中的数字并将其转换为一个列表
def read_txt2number(path):significant_index = []with open(path) as f:for line in f.readlines():line = line.strip('\n')      #去掉列表中每一个元素的换行符significant_index.append(line)number_list = [int(i) for i in significant_index]   # 将字符类型转换为数字return number_list  # 获取一个预测结果的TP TN FP FN
def get_TpTN_FpFn(list1,list2):# list1 为真实的label list2 为预测的labelreallabel_list=list(flatten(list1))predictlabel_list=list(flatten(list2))TP_count = 0TN_count = 0FP_count = 0FN_count = 0for i in range(len(reallabel_list)):if reallabel_list[i] == 1 and predictlabel_list[i] ==1:TP_count += 1if reallabel_list[i] == -1 and predictlabel_list[i] ==-1:TN_count += 1if reallabel_list[i] == -1 and predictlabel_list[i] == 1:FP_count +=1if reallabel_list[i] == 1 and predictlabel_list[i] == -1:FN_count += 1return TP_count, TN_count, FP_count, FN_count
##################数据的读取与整理了#############################################path2 = r'C:\Users\Administer\Desktop\GTCS_HC\20201013data_and_result\6_gene expression class_SVM\SVM class\dataset'MSN_HC = scio.loadmat(path2 + '\\average_MSr_dataset1_HC.mat')
train_MSN_HC = MSN_HC['result']
MSN_GTCS = scio.loadmat(path2 + '\\average_MSr_dataset1_GTCS.mat')
train_MSN_GTCS = MSN_GTCS['result']train_data1 = train_MSN_HC;
train_data2 = train_MSN_GTCS;
dataset =(np.hstack((train_data1,train_data2))).Tdata1_label = list(-1 for i in range(np.size(train_data1,1)));
data2_label = list(1 for i in range(np.size(train_data2,1)))
datalabels = data1_label + data2_label#####################################LOOVC#####################################
# loo = LeaveOneOut()
# loo.get_n_splits(dataset)# 该方法是每次排除一个组,怎样才能每次排除一对?那就是正常组和病人组对应配对?
pair_data1 = [i for i in range(np.size(data1_label,0))]
pair_data2 = [i for i in range(np.size(data2_label,0))]
# 随机打乱分组
random.shuffle(pair_data1)
random.shuffle(pair_data2)
pair = pair_data1+pair_data2
loo = LeaveOneGroupOut()
loo.get_n_splits(dataset,groups=pair)predictlabel_list = []
reallabel_list = []
coef_weight_list = []
Y_score_list = []
sum_of_coef = np.zeros((1,np.size(dataset,1)))
#clf = make_pipeline(StandardScaler(), SVC(C=0.9, kernel='linear', gamma='auto'))
#clf = SVC(C=0.9, kernel='linear', gamma='auto')
#clf = svm.LinearSVC()
scaler = StandardScaler()
dataset = scaler.fit_transform(dataset)
clf = SVC(C=1, kernel='linear', gamma='auto')
count_right_label = 0
count = 0                     # 循环次数
# 用留一法进行验证for train_index, test_index in loo.split(dataset,groups=pair):X_train, X_test = dataset[train_index], dataset[test_index]Y_train, Y_test = np.array(datalabels)[train_index], np.array(datalabels)[test_index]print(test_index)if np.size(X_test,0)==1:print('条件不满足,跳出循环!')breakclf.fit(X_train,Y_train)Y_score_temp = clf.decision_function([X_test[0,:]])            # 得到的结果为该类到超平面的距离temp1 = clf.coef_Y_score_temp1 = clf.decision_function([X_test[1,:]])            # 得到的结果为该类到超平面的距离temp2 = clf.coef_sum_of_coef += np.abs(temp1)sum_of_coef += np.abs(temp2)coef_weight_list.append(temp1)coef_weight_list.append(temp2)predictlabel_list.append(clf.predict([X_test[0,:]]))predictlabel_list.append(clf.predict([X_test[1,:]]))reallabel_list.append(Y_test[0])reallabel_list.append(Y_test[1])Y_score_list.append(Y_score_temp)Y_score_list.append(Y_score_temp1)if Y_test[0] == clf.predict([X_test[0,:]]):count_right_label +=1 if Y_test[1] == clf.predict([X_test[1,:]]):count_right_label +=1 count += 1print('第{}次循环'.format(count))
accurancy = count_right_label/len(reallabel_list)
print('******循环结束!************')
print('准确率为:%.2f%%' %(accurancy*100))
print('******运行结束!************')average_weight = list(flatten(sum_of_coef/2*count)) TP_count, TN_count, FP_count, FN_count = get_TpTN_FpFn(reallabel_list,predictlabel_list)
F1_score = (2 * TP_count)/(2*TP_count + FP_count +FN_count)
F2_score = (2 * TN_count)/(2*TN_count + FP_count +FN_count)
ACC = (TP_count + TN_count)/(TP_count + FN_count + TN_count + FP_count)
SEN = TP_count/(TP_count + FN_count)
SPE = TN_count / (TN_count + FP_count)print('F1_SCORE为:%.2f%%' %(F1_score*100))
print('F2_SCORE为:%.2f%%' %(F2_score*100))
print('ACC(准确率)为:%.2f%%' %(ACC*100))
print('SEN(敏感度)为:%.2f%%' %(SEN*100))
print('SPE(特异性)为:%.2f%%' %(SPE*100))  #print('ROI权重为:{}'.format(average_weight))import matplotlib.pyplot as plt# ROC AUCfrom sklearn.metrics import roc_curve, auc
# 为每个类别计算ROC曲线和AUC
real = np.array(list(flatten(reallabel_list)))
predict = np.array(list(flatten(predictlabel_list)))
roc_auc = dict()
fpr, tpr, threshold = roc_curve(real,Y_score_list)
roc_auc = auc(fpr, tpr)plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange',lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
order=10
# plt.savefig('./loocv_ROC_roc'+str(order)+'.png',dpi=400) # 以400大批保存图片
plt.show()
# scio.savemat('fpr_fdr'+str(order)+'.mat',{'fpr':fpr,'tpr':tpr} )


如何使用python sklearn 中的LeaveOneGroupOu?特例:leave one pair out的实现多重比较校正?相关推荐

  1. python中fit_Python sklearn中的.fit与.predict的用法说明

    我就废话不多说了,大家还是直接看代码吧~ clf=KMeans(n_clusters=5) #创建分类器对象 fit_clf=clf.fit(X) #用训练器数据拟合分类器模型 clf.predict ...

  2. python使用sklearn中的make_blobs函数生成聚类(clustering)分析需要的仿真数据、matplotlib可视化生成的仿真数据

    python使用sklearn中的make_blobs函数生成聚类(clustering)分析需要的仿真数据.matplotlib可视化生成的仿真数据 目录

  3. python使用sklearn中的make_classification函数生成分类模型(classification)需要的仿真数据、使用pandas查看生成数据的特征数据、目标数据

    python使用sklearn中的make_classification函数生成分类模型(classification)需要的仿真数据.使用pandas查看生成数据的特征数据(features).目标 ...

  4. Python中sklearn中HistGradientBoostingRegressor回归器配置单调约束参数monotonic_cst提高回归模型的抗噪声以及局部扰动的能力

    Python中sklearn中HistGradientBoostingRegressor回归器配置单调约束参数monotonic_cst提高回归模型的抗噪声以及局部扰动的能力 目录

  5. Python之 sklearn:sklearn中的train_test_split函数的简介及使用方法之详细攻略

    Python之 sklearn:sklearn中的train_test_split函数的简介及使用方法之详细攻略 目录 sklearn中的train_test_split函数的简介 train_tes ...

  6. Python之 sklearn:sklearn中的RobustScaler 函数的简介及使用方法之详细攻略

    Python之 sklearn:sklearn中的RobustScaler 函数的简介及使用方法之详细攻略 目录 sklearn中的RobustScaler 函数的简介及使用方法 sklearn中的R ...

  7. python pca降维_机器学习之sklearn中的降维算法

    1. PCA与SVD sklearn中降维算法都被包括在模块decomposition中,这个模块本质是一个矩阵分解模块.在过去的十年中,如果要讨论算法进步的先锋,矩阵分解可以说是独树一帜.矩阵分解可 ...

  8. 在Sklearn中使用SVC运行RFE的python代码

    部分代码 from sklearn.feature_selection import RFE, RFECV from sklearn.svm import SVC, SVR import pandas ...

  9. 在Sklearn中使用LinearRegression运行RFE的python代码

    部分代码 import numpy as np import pandas as pd from sklearn.feature_selection import RFE from sklearn.l ...

  10. python sklearn svm多分类_sklearn中SVM一对一多分类参数的研究

    1.引言 最近在学习sklearn库中SVM算法中C-SVC多分类的相关应用,但是在sklearn中关于如何提取训练后的参数,并脱离原有的sklearn库,甚至脱离原有的python开发环境,在新的平 ...

最新文章

  1. nginx 开发一个简单的 HTTP 模块
  2. CSDN2008最有价值博客获奖感言--放飞梦想,让我们扬帆远航
  3. Luogu P1108 低价购买 DP
  4. 计算机一级b类论理,计算机一级B论理参考题.doc
  5. C++中函数模板template和函数参数为指针,且有返回值的结合使用
  6. (10.1)Python学习笔记二
  7. PHP数据结构之三 线性表中的单链表的PHP实现
  8. MySQL启动关闭服务巨慢,这样解决!
  9. 使用xcopy对文件夹进行复制,del、rd 删除文件、文件夹
  10. java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
  11. python3 自动识图
  12. rollup打包js的注意点-haorooms博客分享
  13. SAP License:FICO知识浓缩版
  14. TensorFlow中tf.train.Saver类说明
  15. .reg文件添加、修改、删除注册表的方法
  16. 计算机组成原理笔记(王道考研) 第七章:输入输出系统
  17. 小学生期末评语经典大全
  18. JavaScript高级程序设计(红宝石书)学习笔记
  19. 第二课:创建三层神经网络解决非线性问题
  20. [电设训练]幅频特性测试仪

热门文章

  1. 域名转发修改dns服务器,域名注册修改DNS服务器
  2. 设计模式实例学习-策略模式
  3. 一个 pcie 插槽损坏的 h77n-wifi(BIOS添加nvme模块实现pcie启动操作系统)
  4. 超级账本 —— 面向企业的分布式账本
  5. 【BUG】Python3|爬虫请求得到的json中的值全是问号
  6. JAVA基础_数组(一维数组)
  7. android中关于keytool 错误:java.lang.Exception:密钥库文件不存在: 解决步骤
  8. 读书笔记10 《蔡康永的说话之道1》 蔡康永
  9. 【215期推荐】另类思考:HIS能给医院带来什么“坏处”?
  10. 小程序emijo表情的正则问题