数据集划分train_test_split\交叉验证Cross-validation

文章目录

  • 一、交叉验证介绍
    • 1.1 简单交叉验证 train_test_split
    • 1.2 K折交叉验证 K-Folder Cross Validation
      • 1.2.1 k-折交叉验证步骤
    • 1.3 留一交叉验证 Leave-one-out Cross Validation
    • 1.4 自助法 Bootstrapping
    • 1.5 分层交叉验证 StratifiedKFold
    • 1.6 留P交叉验证 LeavePOut
    • 1.7 分组交叉验 GroupKFold
      • 1.7.1 LeavePOut 和 ShuffleSplit 区别
    • 1.8 时间序列分割 TimeSeriesSplit
  • 二、train_test_split()
    • 2.1 使用形式为
    • 2.2 参数解释
    • 2.3 计算交叉验证的指标
  • 三、代码整合
  • 有趣的事,Python永远不会缺席
  • 培训说明

一、交叉验证介绍

  交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。在此基础上可以得到多组不同的训练集和测试集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。

  那么什么时候才需要交叉验证呢?交叉验证用在数据不是很充足的时候。比如在我日常项目里面,对于普通适中问题,如果数据样本量小于一万条,我们就会采用交叉验证来训练优化选择模型。如果样本大于一万条的话,我们一般随机的把数据分成三份,一份为训练集(Training Set),一份为验证集(Validation Set),最后一份为测试集(Test Set)。用训练集来训练模型,用验证集来评估模型预测的好坏和选择模型及其对应的参数。把最终得到的模型再用于测试集,最终决定使用哪个模型以及对应参数。

1.1 简单交叉验证 train_test_split

  第一种是简单交叉验证,所谓的简单,是和其他交叉验证方法相对而言的。首先,我们随机的将样本数据分为两部分(比如: 70%的训练集,30%的测试集),然后用训练集来训练模型,在测试集上验证模型及参数。接着,我们再把样本打乱,重新选择训练集和测试集,继续训练数据和检验模型。最后我们选择损失函数评估最优的模型和参数。

  • 原始数据分成训练集、验证集和测试集,并且保持数据分布的一致性,可以使用shuffle
  • 好处:处理简单,只需随机把原始数据分为两组即可
  • 缺点:只进行了一次划分,数据结果具有偶然性,没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,得到的结果并不具有说服性。
from sklearn.model_selection import train_test_split
'''
(1)random_state不填或者为0时,每次都不同;其余值表示不同随机数
(2)shuffle表示是否在分割之前对数据进行洗牌(默认True)
'''
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.30,random_state=42,shuffle=True)

1.2 K折交叉验证 K-Folder Cross Validation

  第二种是K折交叉验证(K-Folder Cross Validation)。和第一种方法不同,K折交叉验证会把样本数据随机的分成K份(一般是均分),每次随机的选择K-1份作为训练集,剩下的1份做测试集。当这一轮完成后,重新随机选择K-1份来训练数据。若干轮(小于K)之后,选择损失函数评估最优的模型和参数。
  将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标。K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2。

  应用最多,K-CV可以有效的避免过拟合与欠拟合的发生,最后得到的结果也比较具有说服性。

1.2.1 k-折交叉验证步骤

  • 第一步,不重复抽样将原始数据随机分为 k 份。
  • 第二步,每一次挑选其中 1 份作为测试集,剩余 k-1 份作为训练集用于模型训练。
  • 第三步,重复第二步 k 次,这样每个子集都有一次机会作为测试集,其余机会作为训练集。
  • 在每个训练集上训练后得到一个模型,
  • 用这个模型在相应的测试集上测试,计算并保存模型的评估指标,
  • 第四步,计算 k 组测试结果的平均值作为模型精度的估计,并作为当前 k 折交叉验证下模型的性能指标。

例如:

十折交叉验证

  • 将数据集分成十份,轮流将其中9份作为训练数据,1份作为测试数据,进行试验。每次试验都会得出相应的正确率。

  • 10次的结果的正确率的平均值作为对算法精度的估计,一般还需要进行多次10折交叉验证(例如10次10折交叉验证),再求其均值,作为对算法准确性的估计

  • 模型训练过程的所有步骤,包括模型选择,特征选择等都是在单个折叠 fold 中独立执行的。
    此外:

  • 多次 k 折交叉验证再求均值,例如:10 次10 折交叉验证,以求更精确一点。

  • 数据量大时,k设置小一些 / 数据量小时,k设置大一些。

优点:降低由一次随机划分带来的偶然性,提高其泛化能力,提高对数据的使用效率。
缺点:可能存在一种情况:数据集有5类,抽取出来的也正好是按照类别划分的5类,也就是说第一折全是0类,第二折全是1类,等等;这样的结果就会导致,模型训练时。没有学习到测试集中数据的特点,从而导致模型得分很低,甚至为0,

from sklearn.model_selection import KFold
kf = KFold(n_splits=2)
for train_index, test_index in kf.split(X):
    print('X_train:%s ' % X[train_index])
    print('X_test: %s ' % X[test_index])

1.3 留一交叉验证 Leave-one-out Cross Validation

  第三种是留一交叉验证(Leave-one-out Cross Validation)LOO-CV,在数据缺乏的情况下使用,如果设原始数据有N个样本,那么LOO-CV就是N-CV,即每个样本单独作为验证集,其余的N-1个样本作为训练集,故LOO-CV会得到N个模型,用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标。

  通过反复的交叉验证,用损失函数来度量得到的模型的好坏,最终我们可以得到一个较好的模型。那这三种情况,到底我们应该选择哪一种方法呢?一句话总结,如果我们只是对数据做一个初步的模型建立,不是要做深入分析的话,简单交叉验证就可以了。否则就用S折交叉验证。在样本量少的时候,使用S折交叉验证的特例留一交叉验证。

  • 即K = 样本数
  • 优点:不存在数据分布不一致,每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的。
  • 缺点:耗时,计算成本高,需要建立的模型数量与原始数据样本数量相同。当数据集较大时几乎不能使用。
from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
for train_index, test_index in loo.split(X):
    print('X_train:%s ' % X[train_index])
    print('X_test: %s ' % X[test_index])

1.4 自助法 Bootstrapping

  此外还有一种比较特殊的交叉验证方式,也是用于样本量少的时候。叫做自助法(bootstrapping)。比如我们有m个样本(m较小),每次在这m个样本中随机采集一个样本,放入训练集,采样完后把样本放回。这样重复采集m次,我们得到m个样本组成的训练集。当然,这m个样本中很有可能有重复的样本数据。同时,用没有被采样到的样本做测试集。这样接着进行交叉验证。由于我们的训练集有重复数据,这会改变数据的分布,因而训练结果会有估计偏差,因此,此种方法不是很常用,除非数据量真的很少,比如小于20个。

  • 优点:

  在数据集较小、难以划分时很有用
  能从D中产生不同的S,对集成学习等方法有好处

  • 缺点

  产生的S改变了D的分布,会引入估计偏差

import numpy as np
import pandas as pd
import random
data = pd.DataFrame(np.random.rand(10,4),columns=list('ABCD'))
data['y'] = [random.choice([0,1]) for i in range(10)]
train = data.sample(frac=1.0,replace=True) # 有放回随机采样
test = data.loc[data.index.difference(train.index)].copy() # 将未采样的样本作为测试集

1.5 分层交叉验证 StratifiedKFold

  通过指定分组,对测试集进行无放回抽样
  对非平衡数据可以用分层采样,就是在每一份子集中都保持和原始数据集相同的类别比例。StratifiedKFold() 各个类别的比例大致和完整数据集中相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例约是2:3:3:2,StratifiedShuffleSplit() 划分中每个类的比例和完整数据集中的相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例也是2:3:3:2。
  ShuffleSplit允许更精细地控制迭代数和训练集/检验集的样本比例。

# ==================分层K折交叉验证、分层随机交叉验证===================
# 如何解决样本不平衡问题
skf = StratifiedKFold(n_splits=3)
#各个类别的比例大致和完整数据集中相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例约是2:3:3:2
for train, test in skf.split(iris.data, iris.target):
    print("分层K折划分:%s %s" % (train.shape, test.shape))
    # break
'''
分层K折划分:(99,) (51,)
分层K折划分:(99,) (51,)
分层K折划分:(102,) (48,)
'''
skf = StratifiedShuffleSplit(n_splits=3)
# 划分中每个类的比例和完整数据集中的相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例也是2:3:3:2
for train, test in skf.split(iris.data, iris.target):
    print("分层随机划分:%s %s" % (train.shape, test.shape))
    # break
'''
分层随机划分:(135,) (15,)
分层随机划分:(135,) (15,)
分层随机划分:(135,) (15,)
'''

1.6 留P交叉验证 LeavePOut

LeavePOut与LeaveOneOut类似,它从完整的数据集里删除 p 个样本,产生所有可能的训练集和检验集。对于 n个样本,能产生m个训练-检验对: m = C p n m = C^n_p m=Cpn

# ===========K折交叉验证、留一交叉验证、留p交叉验证、随机排列交叉验证===========
# k折划分子集
kf = KFold(n_splits=2)
for train, test in kf.split(iris.data):
    print("k折划分:%s %s" % (train.shape, test.shape))#k折划分:(75,) (75,)
    break

# 留一划分子集
loo = LeaveOneOut()
for train, test in loo.split(iris.data):
    print("留一划分:%s %s" % (train.shape, test.shape))#留一划分:(149,) (1,)
    break

# 留p划分子集,LeaveOneOut(n) 相当于 KFold(n, n_folds=n) 相当于LeavePOut(n, p=1)。
# 它从完整的数据集里挑选 p个样本,产生所有可能的训练集和检验集。对于 n 个样本,能产生(Cpn) 个训练-检验对。
# https://blog.csdn.net/wong2016/article/details/81407927

lpo = LeavePOut(p=2)
for train, test in lpo.split(iris.data):
    print("留p划分:%s %s" % (train.shape, test.shape))
    #留p划分:(148,) (2,),排列组合算法Cp n = 150*149/2个模型11175
    break


# 随机排列划分子集
ss = ShuffleSplit(n_splits=3, test_size=0.25,random_state=0)
for train_index, test_index in ss.split(iris.data):
    print("随机排列划分:%s %s" % (train_index.shape, test_index.shape))
    # 随机排列划分:(112,) (38,),n_splits是模型个数
    break

1.7 分组交叉验 GroupKFold

  如何进一步测试模型的泛化能力? 留出一组特定的不属于测试集和训练集的数据。有时我们想知道在一组特定的 groups 上训练的模型是否能很好地适用于看不见的 group 。为了衡量这一点,我们需要确保验证对象中的所有样本来自配对训练折叠中完全没有表示的组。

  GroupKFold 是 k-fold 的变体,它确保同一个 group 在测试和训练集中都不被表示。 例如,如果数据是从不同的 subjects 获得的,每个 subject 有多个样本,并且如果模型足够灵活以高度人物指定的特征中学习,则可能无法推广到新的 subject 。 GroupKFold 可以检测到这种过拟合的情况。
  GroupKFold和StratifiedKFold 比较像,不过测试集是按照一定分组进行打乱的,即先分堆,然后把这些堆打乱,每个堆里的顺序还是固定不变的。

  LeaveOneGroupOut 是一个交叉验证方案,它根据第三方提供的 array of integer groups (整数组的数组)来提供样本。这个组信息可以用来编码任意域特定的预定义交叉验证折叠。每个训练集都是由除特定组别以外的所有样本构成的。
  这个是在GroupKFold 上的基础上混乱度又减小了,按照给定的分组方式将测试集分割下来。

  LeavePGroupsOut 类似于 LeaveOneGroupOut ,但为每个训练/测试集删除与 P 组有关的样本。跟上面那个一样,只是一个是单组,一个是多组。

  GroupShuffleSplit 迭代器是 ShuffleSplit 和 LeavePGroupsOut 的组合,它生成一个随机划分分区的序列,其中为每个分组提供了一个组子集。这个是有放回抽样

# ==================================组 k-fold交叉验证、留一组交叉验证、留 P 组交叉验证、Group Shuffle Split==========================================
X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]
# 泛化能力,训练集和测试的样本不重合,但是各自内部可以重合
# k折分组
gkf = GroupKFold(n_splits=3)
# 训练集和测试集属于不同的组,同一组的样本不可能同时出现在同一折的测试集和训练集中。
for train, test in gkf.split(X, y, groups=groups):
    print("组 k-fold分割:%s %s" % (train, test))
'''
组 k-fold分割:[0 1 2 3 4 5] [6 7 8 9]
组 k-fold分割:[0 1 2 6 7 8 9] [3 4 5]
组 k-fold分割:[3 4 5 6 7 8 9] [0 1 2]
'''
# 留一分组
logo = LeaveOneGroupOut()
for train, test in logo.split(X, y, groups=groups):
    print("留一组分割:%s %s" % (train, test))
'''
留一组分割:[3 4 5 6 7 8 9] [0 1 2]
留一组分割:[0 1 2 6 7 8 9] [3 4 5]
留一组分割:[0 1 2 3 4 5] [6 7 8 9]
'''
# 留p分组
lpgo = LeavePGroupsOut(n_groups=2)
for train, test in lpgo.split(X, y, groups=groups):
    print("留 P 组分割:%s %s" % (train, test))
'''三个模型,三个类别C23=3
留 P 组分割:[6 7 8 9] [0 1 2 3 4 5]
留 P 组分割:[3 4 5] [0 1 2 6 7 8 9]
留 P 组分割:[0 1 2] [3 4 5 6 7 8 9]
'''
# 随机分组
gss = GroupShuffleSplit(n_splits=4, test_size=0.5, random_state=0)
for train, test in gss.split(X, y, groups=groups):
    print("随机分割:%s %s" % (train, test))

1.7.1 LeavePOut 和 ShuffleSplit 区别

  LeavePOut 是使得数据集经过数次分割后,所有的测试集出现的元素的集合即是完整的数据集,即无放回的抽样,
  ShuffleSplit 则是有放回的抽样,只能说经过一个足够大的抽样次数后,保证测试集出现了完成的数据集的倍数。

1.8 时间序列分割 TimeSeriesSplit

  TimeSeriesSplit 是 k-fold 的一个变体,它首先返回 k 折作为训练数据集,并且 (k+1) 折作为测试数据集。 请注意,与标准的交叉验证方法不同,连续的训练集是超越前者的超集。 另外,它将所有的剩余数据添加到第一个训练分区,它总是用来训练模型。

  这个类可以用来交叉验证以固定时间间隔观察到的时间序列数据样本。

  针对时间序列的处理,防止未来数据的使用,分割时是将数据进行从前到后切割(这个说法其实不太恰当,因为切割是延续性的。。)

# ==================================时间序列分割==========================================
#是 k-fold 的一个变体,K折就是讲数据集切分成K小块,验证集和测试集相互形成补集它首先返,每次分割中不会有重叠。相当于无放回抽样。
# 而TimeSeriesSplit中,是又放回的
# 即K组数据,前一组的训练集+测试集,是后一组的训练集,,第K+1作为测试集,组成K个模型
# 请注意,与标准的交叉验证方法不同,连续的训练集是超越前者的超集。 另外,它将所有的剩余数据添加到第一个训练分区,它总是用来训练模型。
# 这个类可以用来交叉验证以固定时间间隔观察到的时间序列数据样本。

tscv = TimeSeriesSplit(n_splits=3)
TimeSeriesSplit(max_train_size=None, n_splits=3)
for train, test in tscv.split(iris.data):
    print("时间序列分割:%s %s" % (train.shape, test.shape))
    print(test)
'''三个模型
时间序列分割(39,) (37,):
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38] 
 [39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
 63 64 65 66 67 68 69 70 71 72 73 74 75]
时间序列分割(76,) (37,):
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 72 73 74 75] 
 [ 76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93
  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111
 112]
时间序列分割(113,) (37,):
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71
  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89
  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107
 108 109 110 111 112] 
 [113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
 149]

'''

二、train_test_split()

2.1 使用形式为

  train_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和test

from sklearn.model_selection import train_test_split 
X_train, X_test, y_train, y_test = train_test_split(train_data,train_target,test_size=0.2, random_state=0)

2.2 参数解释

  train_data:样本特征集
  train_target:样本的标签集
  test_size:样本占比,测试集占数据集的比重,如果是整数的话就是样本的数量
  random_state:是随机数的种子。在同一份数据集上,相同的种子产生相同的结果,不同的种子产生不同的划分结果


  X_train,y_train:构成了训练集

  X_test,y_test:构成了测试集

2.3 计算交叉验证的指标

  使用交叉验证最简单的方法是在估计器和数据集上调用 cross_val_score 辅助函数。

三、代码整合

# coding = utf-8
# 2019/8/1  Luckyxxt:有趣的事,Python永远不会缺席!
''
from sklearn.model_selection import train_test_split,cross_val_score,cross_validate # 交叉验证所需的函数
from sklearn.model_selection import KFold,LeaveOneOut,LeavePOut,ShuffleSplit # 交叉验证所需的子集划分方法
from sklearn.model_selection import StratifiedKFold,StratifiedShuffleSplit # 分层分割
from sklearn.model_selection import GroupKFold,LeaveOneGroupOut,LeavePGroupsOut,GroupShuffleSplit # 分组分割
from sklearn.model_selection import TimeSeriesSplit # 时间序列分割
from sklearn import datasets  # 自带数据集
from sklearn import svm  # SVM算法
from sklearn import preprocessing  # 预处理模块
from sklearn.metrics import recall_score  # 模型度量

iris = datasets.load_iris()  # 加载数据集
print('样本集大小:',iris.data.shape,iris.target.shape)

# =====================数据集划分,训练模型======================
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)
# 交叉验证划分训练集和测试集.test_size为测试集所占的比例
print('训练集大小:',X_train.shape,y_train.shape)  # 训练集样本大小
print('测试集大小:',X_test.shape,y_test.shape)  # 测试集样本大小
clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train) # 使用训练集训练模型
print('准确率:%.3f'%(clf.score(X_test, y_test)))  # 计算测试集的度量值(准确率)准确率:0.967
print('未归一化',X_train[1:3])
'''
未归一化 [[4.8 3.1 1.6 0.2]
 [5.8 2.7 5.1 1.9]]
'''
#  如果涉及到归一化,则在测试集上也要使用训练集模型提取的归一化函数。
scaler = preprocessing.StandardScaler().fit(X_train)
print('scaler',scaler)
# scaler StandardScaler(copy=True, with_mean=True, with_std=True)
# 通过训练集获得归一化函数模型。(也就是先减几,再除以几的函数)。在训练集和测试集上都使用这个归一化函数
X_train_transformed = scaler.transform(X_train)
print('归一化',X_train_transformed[1:3])
'''
归一化 [[-1.17402201  0.00522823 -1.10334891 -1.19530695]
 [-0.04394735 -0.93585257  0.77939706  0.9337031 ]]
'''
clf = svm.SVC(kernel='linear', C=1).fit(X_train_transformed, y_train) # 使用训练集训练模型
X_test_transformed = scaler.transform(X_test)
print('归一化后score%.3f'%(clf.score(X_test_transformed, y_test)))  # 计算测试集的度量值(准确度),归一化后score0.933


# ========================直接调用交叉验证评估模型=================
clf = svm.SVC(kernel='linear', C=1)
scores = cross_val_score(clf, iris.data, iris.target, cv=5)  #交叉验证cv为迭代次数。
print('迭代5次的scores',scores)  # 打印输出每次迭代的度量值(准确度)
# [0.96666667 1.         0.96666667 0.96666667 1.        ]
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
# 获取置信区间。(也就是均值和方差),std()计算标准偏差Accuracy: 0.98 (+/- 0.03)

# =======================多种度量结果===================
scoring = ['precision_macro', 'recall_macro'] #不懂
# precision_macro为精度,recall_macro为召回率
# sklearn.metrics.SCORERS.keys()
scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,cv=5, return_train_score=True)
sorted(scores.keys())
print('测试结果:',scores)  # scores类型为字典。包含训练得分,拟合次数, score-times (得分次数)


# =================K折交叉验证、留一交叉验证、留p交叉验证、随机排列交叉验证====================
# k折划分子集
kf = KFold(n_splits=2)
for train, test in kf.split(iris.data):
    print("k折划分:%s %s" % (train.shape, test.shape))#k折划分:(75,) (75,)
    break

# 留一划分子集
loo = LeaveOneOut()
for train, test in loo.split(iris.data):
    print("留一划分:%s %s" % (train.shape, test.shape))#留一划分:(149,) (1,)
    break

# 留p划分子集,LeaveOneOut(n) 相当于 KFold(n, n_folds=n) 相当于LeavePOut(n, p=1)。
# 它从完整的数据集里挑选 p个样本,产生所有可能的训练集和检验集。对于 n 个样本,能产生(Cpn) 个训练-检验对。
# https://blog.csdn.net/wong2016/article/details/81407927

lpo = LeavePOut(p=2)
for train, test in lpo.split(iris.data):
    print("留p划分:%s %s" % (train.shape, test.shape))
    #留p划分:(148,) (2,),排列组合算法Cp n = 150*149/2个模型11175
    break


# 随机排列划分子集
ss = ShuffleSplit(n_splits=3, test_size=0.25,random_state=0)
for train_index, test_index in ss.split(iris.data):
    print("随机排列划分:%s %s" % (train_index.shape, test_index.shape))
    # 随机排列划分:(112,) (38,),n_splits是模型个数
    break

# ======================分层K折交叉验证、分层随机交叉验证========================
# 如何解决样本不平衡问题
skf = StratifiedKFold(n_splits=3)
#各个类别的比例大致和完整数据集中相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例约是2:3:3:2
for train, test in skf.split(iris.data, iris.target):
    print("分层K折划分:%s %s" % (train.shape, test.shape))
    # break
'''
分层K折划分:(99,) (51,)
分层K折划分:(99,) (51,)
分层K折划分:(102,) (48,)
'''
skf = StratifiedShuffleSplit(n_splits=3)
# 划分中每个类的比例和完整数据集中的相同,若数据集有4个类别,比例是2:3:3:2,则划分后的样本比例也是2:3:3:2
for train, test in skf.split(iris.data, iris.target):
    print("分层随机划分:%s %s" % (train.shape, test.shape))
    # break
'''
分层随机划分:(135,) (15,)
分层随机划分:(135,) (15,)
分层随机划分:(135,) (15,)
'''

# ==================================组 k-fold交叉验证、留一组交叉验证、留 P 组交叉验证、Group Shuffle Split==========================================
X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]
# 泛化能力,训练集和测试的样本不重合,但是各自内部可以重合
# k折分组
gkf = GroupKFold(n_splits=3)
# 训练集和测试集属于不同的组,同一组的样本不可能同时出现在同一折的测试集和训练集中。
for train, test in gkf.split(X, y, groups=groups):
    print("组 k-fold分割:%s %s" % (train, test))
'''
组 k-fold分割:[0 1 2 3 4 5] [6 7 8 9]
组 k-fold分割:[0 1 2 6 7 8 9] [3 4 5]
组 k-fold分割:[3 4 5 6 7 8 9] [0 1 2]
'''
# 留一分组
logo = LeaveOneGroupOut()
for train, test in logo.split(X, y, groups=groups):
    print("留一组分割:%s %s" % (train, test))
'''
留一组分割:[3 4 5 6 7 8 9] [0 1 2]
留一组分割:[0 1 2 6 7 8 9] [3 4 5]
留一组分割:[0 1 2 3 4 5] [6 7 8 9]
'''
# 留p分组
lpgo = LeavePGroupsOut(n_groups=2)
for train, test in lpgo.split(X, y, groups=groups):
    print("留 P 组分割:%s %s" % (train, test))
'''三个模型,三个类别C23=3
留 P 组分割:[6 7 8 9] [0 1 2 3 4 5]
留 P 组分割:[3 4 5] [0 1 2 6 7 8 9]
留 P 组分割:[0 1 2] [3 4 5 6 7 8 9]
'''
# 随机分组
gss = GroupShuffleSplit(n_splits=4, test_size=0.5, random_state=0)
for train, test in gss.split(X, y, groups=groups):
    print("随机分割:%s %s" % (train, test))


# ===========================时间序列分割=====================

tscv = TimeSeriesSplit(n_splits=3)
TimeSeriesSplit(max_train_size=None, n_splits=3)
for train, test in tscv.split(iris.data):
    print("时间序列分割:%s %s" % (train.shape, test.shape))
    print(test)

'''

有趣的事,Python永远不会缺席

欢迎关注小婷儿的博客

    文章内容来源于小婷儿的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

    如需转发,请注明出处:小婷儿的博客python    https://www.cnblogs.com/xxtalhr/

博客园 https://www.cnblogs.com/xxtalhr/

CSDN https://blog.csdn.net/u010986753

有问题请在博客下留言或加作者:
     微信:tinghai87605025 联系我加微信群
     QQ :87605025
     python QQ交流群:py_data 483766429

培训说明

OCP培训说明连接 https://mp.weixin.qq.com/s/2cymJ4xiBPtTaHu16HkiuA

OCM培训说明连接 https://mp.weixin.qq.com/s/7-R6Cz8RcJKduVv6YlAxJA

     小婷儿的python正在成长中,其中还有很多不足之处,随着学习和工作的深入,会对以往的博客内容逐步改进和完善哒。重要的事多说几遍。。。。。。

你可能感兴趣的:(model_selection)