如何使用python sklearn 中的LeaveOneGroupOu?特例:leave one pair out的实现多重比较校正?
引言
一般我们会在研究中验证某个特征的有效性,会使用该特征对病例个样本进行二分类,通常回选择支持向量机(SVM),这里的目的并非一定要得到很高的正确率,更多地只是想说明该特征可以区分case组和control组。
留一法 or 留一对法?
因为样本量的原因,一般是使用留一法进行多重比较校正,但是有时候也会被要求使用留一对的方法,简单的就是每一次从case中拿出一例,然后从control中拿出一例,使用剩余的(m+n)- 2的样本进行训练,对取出的样本(一个来自case一个来自control)进行测试。
但是你可能会想case组有m个样本,control组有n个样本,两组人的数量不一样(m≠n)要怎么处理呢?
- 首先k=m<n?m:n(选取二者中较小的一个数)
- 一共进行k次随机取样本,训练模型,分类,得到分类正确率
- 然后重复步骤(1,2)N次,就会得到多个准确率和多条ROC曲线。
- 你可能会问为什么要重复这多(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]...
上述代码说明
- 首先将data1进行编号0:M-1,然后对N进行编号0:N-1,数字为组别
- 之后对组别进行打乱,打乱的组别(后续说明为什么打乱)
- 然后将分组编号合并(前面为data1的组别,后面为data2的组别)
- 然后将样本特征及其对应的分组编号作为参数输入到LeaveOneGroupOut的get_n_splits中,其实上述过程会将数据分成max(M,N)份,如果M与N的大小不一样的话,整个过程会出现leave one out 的情况(后续会对此进行处理)
特殊处理说明
- 因为编号是由小到大,因此当编号小于min(M,N)时程序都能正常的leave one pair out,当编号大于等于min(M,N)时只能得到一个一个样本,此时在代码中加入判断条件跳出循环,就可以了。代码如下:
print(test_index)if np.size(X_test,0)==1:print('条件不满足,跳出循环!')break
- 为什么需要随机打乱?因为两组人的数量可能不同,分组的方式也不唯一,因此需要随机打乱来排除这种认为分组方式对结果的影响,因此每次代码的运行分组的方式都是不一样的,可以通过多运行几次来减小分组带来的误差,同时可以借此判断结果是否稳定。
完整实现代码
"""
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的实现多重比较校正?相关推荐
- python中fit_Python sklearn中的.fit与.predict的用法说明
我就废话不多说了,大家还是直接看代码吧~ clf=KMeans(n_clusters=5) #创建分类器对象 fit_clf=clf.fit(X) #用训练器数据拟合分类器模型 clf.predict ...
- python使用sklearn中的make_blobs函数生成聚类(clustering)分析需要的仿真数据、matplotlib可视化生成的仿真数据
python使用sklearn中的make_blobs函数生成聚类(clustering)分析需要的仿真数据.matplotlib可视化生成的仿真数据 目录
- python使用sklearn中的make_classification函数生成分类模型(classification)需要的仿真数据、使用pandas查看生成数据的特征数据、目标数据
python使用sklearn中的make_classification函数生成分类模型(classification)需要的仿真数据.使用pandas查看生成数据的特征数据(features).目标 ...
- Python中sklearn中HistGradientBoostingRegressor回归器配置单调约束参数monotonic_cst提高回归模型的抗噪声以及局部扰动的能力
Python中sklearn中HistGradientBoostingRegressor回归器配置单调约束参数monotonic_cst提高回归模型的抗噪声以及局部扰动的能力 目录
- Python之 sklearn:sklearn中的train_test_split函数的简介及使用方法之详细攻略
Python之 sklearn:sklearn中的train_test_split函数的简介及使用方法之详细攻略 目录 sklearn中的train_test_split函数的简介 train_tes ...
- Python之 sklearn:sklearn中的RobustScaler 函数的简介及使用方法之详细攻略
Python之 sklearn:sklearn中的RobustScaler 函数的简介及使用方法之详细攻略 目录 sklearn中的RobustScaler 函数的简介及使用方法 sklearn中的R ...
- python pca降维_机器学习之sklearn中的降维算法
1. PCA与SVD sklearn中降维算法都被包括在模块decomposition中,这个模块本质是一个矩阵分解模块.在过去的十年中,如果要讨论算法进步的先锋,矩阵分解可以说是独树一帜.矩阵分解可 ...
- 在Sklearn中使用SVC运行RFE的python代码
部分代码 from sklearn.feature_selection import RFE, RFECV from sklearn.svm import SVC, SVR import pandas ...
- 在Sklearn中使用LinearRegression运行RFE的python代码
部分代码 import numpy as np import pandas as pd from sklearn.feature_selection import RFE from sklearn.l ...
- python sklearn svm多分类_sklearn中SVM一对一多分类参数的研究
1.引言 最近在学习sklearn库中SVM算法中C-SVC多分类的相关应用,但是在sklearn中关于如何提取训练后的参数,并脱离原有的sklearn库,甚至脱离原有的python开发环境,在新的平 ...
最新文章
- nginx 开发一个简单的 HTTP 模块
- CSDN2008最有价值博客获奖感言--放飞梦想,让我们扬帆远航
- Luogu P1108 低价购买 DP
- 计算机一级b类论理,计算机一级B论理参考题.doc
- C++中函数模板template和函数参数为指针,且有返回值的结合使用
- (10.1)Python学习笔记二
- PHP数据结构之三 线性表中的单链表的PHP实现
- MySQL启动关闭服务巨慢,这样解决!
- 使用xcopy对文件夹进行复制,del、rd 删除文件、文件夹
- java.lang.NoClassDefFoundError: javax/wsdl/extensions/ElementExtensible
- python3 自动识图
- rollup打包js的注意点-haorooms博客分享
- SAP License:FICO知识浓缩版
- TensorFlow中tf.train.Saver类说明
- .reg文件添加、修改、删除注册表的方法
- 计算机组成原理笔记(王道考研) 第七章:输入输出系统
- 小学生期末评语经典大全
- JavaScript高级程序设计(红宝石书)学习笔记
- 第二课:创建三层神经网络解决非线性问题
- [电设训练]幅频特性测试仪
热门文章
- 域名转发修改dns服务器,域名注册修改DNS服务器
- 设计模式实例学习-策略模式
- 一个 pcie 插槽损坏的 h77n-wifi(BIOS添加nvme模块实现pcie启动操作系统)
- 超级账本 —— 面向企业的分布式账本
- 【BUG】Python3|爬虫请求得到的json中的值全是问号
- JAVA基础_数组(一维数组)
- android中关于keytool 错误:java.lang.Exception:密钥库文件不存在: 解决步骤
- 读书笔记10 《蔡康永的说话之道1》 蔡康永
- 【215期推荐】另类思考:HIS能给医院带来什么“坏处”?
- 小程序emijo表情的正则问题