1. GroupKFold(_BaseKFold)

主要参数:

n_splits : int, default=3

在GroupKFold.split(X[, y, groups])中会调用下面的方法

def _iter_test_indices(self, X, y, groups):
if groups is None:
raise ValueError("The 'groups' parameter should not be None.")
groups = check_array(groups, ensure_2d=False, dtype=None) unique_groups, groups = np.unique(groups, return_inverse=True) # unique_groups[groups] 可以重建原来的groups
n_groups = len(unique_groups) if self.n_splits > n_groups:
raise ValueError("Cannot have number of splits n_splits=%d greater"
" than the number of groups: %d."
% (self.n_splits, n_groups)) # Weight groups by their number of occurrences
n_samples_per_group = np.bincount(groups) # 每组中的样本数 # Distribute the most frequent groups first
indices = np.argsort(n_samples_per_group)[::-1] # 按从每组样本数由多到少的顺序排列每组的索引
n_samples_per_group = n_samples_per_group[indices] # 每组的样本数从大到小的排列,n_samples_per_group 的索引不再有意义而被 indices 代替 # Total weight of each fold
n_samples_per_fold = np.zeros(self.n_splits) # Mapping from group index to fold index
group_to_fold = np.zeros(len(unique_groups)) # Distribute samples by adding the largest weight to the lightest fold
# largest weight 就是当前最大的一组样本数,lightest fold 就是所有fold中所含样本最少的那一折
for group_index, weight in enumerate(n_samples_per_group):
lightest_fold = np.argmin(n_samples_per_fold)
n_samples_per_fold[lightest_fold] += weight
group_to_fold[indices[group_index]] = lightest_fold # 这里就是组数要比折数多的原因,因为一组必须全部放到一折里面,一折可包含多组 indices = group_to_fold[groups] for f in range(self.n_splits):
yield np.where(indices == f)[0] # 返回每一折的 test index

总结

GroupKFold是没有随机性参数的,也就是样本的groups确定后,每一折包含那些样本也是确定的。算法的文字描述如下:

  1. 每组按照组内样本数的多少进行排序
  2. 以组为单位对所有组做一次遍历
  3. 将当前组内所有样本放入当前分配的所有折中所含样本数最少的折中

使用时注意组数要大于折数,同一组的样本一定被分到同一折中。

2. GroupShuffleSplit(ShuffleSplit)

主要参数:

n_splits : int (default 5) 划分样本训练集和测试集的次数,不同于折数

train_size/test_size : 训练集或测试集的样本比例或数目

random_state

在GroupShuffleSplit.split(X[, y, groups])方法中:

def _iter_indices(self, X, y, groups):
if groups is None:
raise ValueError("The 'groups' parameter should not be None.")
groups = check_array(groups, ensure_2d=False, dtype=None)
classes, group_indices = np.unique(groups, return_inverse=True)
for group_train, group_test in super(
GroupShuffleSplit, self)._iter_indices(X=classes): # 对组进行ShuffleSplit,group_train包含了作为训练集的组号,group_test类同
# these are the indices of classes in the partition
# invert them into data indices # np.in1d 返回group_indices中的元素是否在group_train中,True False的数组
# np.flatnonzero() 返回数组中不为0的元素的索引,实际就是选为train或者test的样本的index
train = np.flatnonzero(np.in1d(group_indices, group_train))
test = np.flatnonzero(np.in1d(group_indices, group_test)) yield train, test

然后其中调用ShuffleSplit的同名方法:

# ShuffleSplit的方法
def _iter_indices(self, X, y=None, groups=None):
n_samples = _num_samples(X) # 返回 X 中样本数目
n_train, n_test = _validate_shuffle_split(n_samples, # 对传入参数做数据检查,返回训练集和测试集的样本数
self.test_size,
self.train_size)
rng = check_random_state(self.random_state) # 对random_state做数据检查,返回随机种子 np.random.RandomState()
for i in range(self.n_splits):
# random partition
permutation = rng.permutation(n_samples) # 随机打乱数据
ind_test = permutation[:n_test]
ind_train = permutation[n_test:(n_test + n_train)]
yield ind_train, ind_test # 返回每一折的训练集的index和测试集的index

总结

GroupShuffleSplit是有随机性参数random_state的,其随机性来自于其父类ShuffleSplit。该算法的核心就是对组编号做ShuffleSplit,这也是其继承该类的原因,然后所有落在train中的组的所有样本组成训练集,其他组成测试集。和GroupKFold类似,一组的数组要么只出现在train中,要么只出现test中,不可同时出现在二者之中。

3. KFold(_BaseKFold)

注意

参数shuffle的默认值是False,而我们一般要设置为True。当shuffle设置为True时,random_state才会被用到,这时,如果random_state如果不设置,每次结果会不一样,只有给每次设置random_state同一个值,shuffle的结果才是相同的。所以shuffle决定是否引入随机性,random_state只不过是让随机性可以重现。

4. LeaveOneGroupOut(BaseCrossValidator)

    def _iter_test_masks(self, X, y, groups):
if groups is None:
raise ValueError("The 'groups' parameter should not be None.")
# We make a copy of groups to avoid side-effects during iteration
groups = check_array(groups, copy=True, ensure_2d=False, dtype=None)
unique_groups = np.unique(groups)
if len(unique_groups) <= 1:
raise ValueError(
"The groups parameter contains fewer than 2 unique groups "
"(%s). LeaveOneGroupOut expects at least 2." % unique_groups)
for i in unique_groups:
yield groups == i # 返回作为测试集的index

总结

一开始对留一法不是很清楚,其实留一法就是交叉验证方法的极端情形,当交叉验证的折数和数据集的个数相等时就是留一法。理解了留一法后上面的源码就是非常清晰简洁的。一句话概括该算法就是以组为单位做留一法。

5. LeavePGroupsOut(BaseCrossValidator)

理解前面的就很简单,就是留出P个Group做测试集。

6. LeaveOneOut(BaseCrossValidator)

7. LeavePOneOut(BaseCrossValidator)

8. PredefinedSplit(BaseCrossValidator)

def __init__(self, test_fold):
self.test_fold = np.array(test_fold, dtype=np.int)
self.test_fold = column_or_1d(self.test_fold) # 将shape是(n_samples,1)的数组拉成(n_samples,)的数组
self.unique_folds = np.unique(self.test_fold)
self.unique_folds = self.unique_folds[self.unique_folds != -1] # test_fold 中所有-1的样本要放到train中,也就是test_fold中不为-1的值的种类数就是split的数目。 def split(self, X=None, y=None, groups=None):
ind = np.arange(len(self.test_fold))
for test_index in self._iter_test_masks():
train_index = ind[np.logical_not(test_index)]
test_index = ind[test_index]
yield train_index, test_index def _iter_test_masks(self):
"""Generates boolean masks corresponding to test sets."""
for f in self.unique_folds:
test_index = np.where(self.test_fold == f)[0]
test_mask = np.zeros(len(self.test_fold), dtype=np.bool)
test_mask[test_index] = True
yield test_mask

上面的源码是清晰明了的,下面举例子说明:

PredefinedSplit需要的参数只有一个那就是test_fold, test_fold的size要和数据集的size相同,test_fold中元素的值为-1,表示这个样本要放到训练集中,test_fold中具有相同值的元素对应的样本要放到同一个test_set中。比如 test_fold = [1, 1, 1, -1, -1, -1, 2, 2, 2, 2]表示或做两个split,第一次split中第4(首个index是1)到第10个样本做train,第1个到第3个做test;第二次split中第1到第7个样本做train,第8个到第10个样本做test 。

9. RepeatedKFold(_RepeatedSplits)

用不同的随机化重复KFold若干次,内部代码在每次KFold时会把shuffle设置为True。

10. RepeatedStratifiedKFold(_RepeatedSplits)

11. ShuffleSplit(BaseShuffleSplit)

12. StratifiedKFold(_BaseKFold)

注意

split(X, y, [groups])中y是必须的参数而不是可选的。

13. StratifiedShuffleSplit(BaseShuffleSplit)

14. TimeSeriesSplit(_BaseKFold)

def __init__(self, n_splits=3, max_train_size=None):
super(TimeSeriesSplit, self).__init__(n_splits,
shuffle=False,
random_state=None)
self.max_train_size = max_train_size # 训练集的最大样本数 def split(self, X, y=None, groups=None):
X, y, groups = indexable(X, y, groups)
n_samples = _num_samples(X)
n_splits = self.n_splits
n_folds = n_splits + 1
if n_folds > n_samples: # 折数不能大于样本数,也即是参数n_splits不能大于样本数减1
raise ValueError(
("Cannot have number of folds ={0} greater"
" than the number of samples: {1}.").format(n_folds,
n_samples))
indices = np.arange(n_samples)
test_size = (n_samples // n_folds)
test_starts = range(test_size + n_samples % n_folds,
n_samples, test_size)
for test_start in test_starts:
if self.max_train_size and self.max_train_size < test_start:
yield (indices[test_start - self.max_train_size:test_start],
indices[test_start:test_start + test_size])
else:
yield (indices[:test_start],
indices[test_start:test_start + test_size])

使用方法总结

  • KFold类:n_splits既是折数(确定train和test的size),也是重复次数。
  • ShuffleSplit类:n_splits是重复次数,需要额外参数train_size/test_size来确定train和test被划分的大小。
  • LeaveOneOut类:不需要参数,LeaveOnePOut需要参数p。
# template
spliter = Spliter(...)
for i, trn_idx,test_idx in enumerate(spliter.split(X,y)):
....

sklearn.model_selection Part 1: Splitter Classes的更多相关文章

  1. sklearn.model_selection Part 2: Model validation

    1. check_cv() def check_cv(cv=3, y=None, classifier=False): if cv is None: cv = 3 if isinstance(cv, ...

  2. sklearn.model_selection 的 train_test_split作用

    train_test_split函数用于将数据划分为训练数据和测试数据. train_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train_data和test_data ...

  3. sklearn.model_selection.StratifiedShuffleSplit

    sklearn.model_selection.StratifiedShuffleSplit

  4. sklearn.model_selection模块

    后续补代码 sklearn.model_selection模块的几个方法参数

  5. 【sklearn】网格搜索 from sklearn.model_selection import GridSearchCV

    GridSearchCV用于系统地遍历模型的多种参数组合,通过交叉验证确定最佳参数. 1.GridSearchCV参数    # 不常用的参数 pre_dispatch 没看懂 refit 默认为Tr ...

  6. sklearn.model_selection 的train_test_split方法和参数

    train_test_split是sklearn中用于划分数据集,即将原始数据集划分成测试集和训练集两部分的函数. from sklearn.model_selection import train_ ...

  7. No module named ‘sklearn.model_selection解决办法

    在python中运行导入以下模块 from sklearn.model_selection import train_test_split 出现错误:  No module named ‘sklear ...

  8. [Python]-sklearn.model_selection模块-处理数据集

    拆分数据集train&test from sklearn.model_selection import train_test_split 可以按比例拆分数据集,分为train和test x_t ...

  9. SK-Learn 全家福

    SK-Learn API 全家福 最近SK-Learn用的比较多, 以后也会经常用,将Sk-Learn 所有内容整理了一下,整理思路,并可以备查. (高清图片可以用鼠标右键在单独窗口打开,或者保存到本 ...

随机推荐

  1. 一些通用的js工具类,添加自定义插件

    common_t.js /** * 通用工具组件 对原有的工具进行封装,自定义某方法统一处理<br> * ^_^ * * Author: em.D * Date: 2016-05-17 * ...

  2. java中的全局变量、局部变量与静态常量的区别

    java中的变量类型分类: 类变量:独立于方法之外的变量,用 static 修饰.实例变量:独立于方法之外的变量,不过没有 static 修饰.局部变量:类的方法中的变量.比如: public cla ...

  3. python 高级函数

    高级函数 map 格式:map(func, lt) 说明:接受两个参数,一个函数和一个可迭代对象,返回一个生成器,将func依次作用于lt 示例: l = [1,2,3,4,5]​def double ...

  4. Python(os和sys)理解

    Python(os和sys)理解 os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口; sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时 ...

  5. Tcp之心跳包

    Tcp之心跳包 心跳包 跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着. 事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很 ...

  6. 在java中使用solr7.2.0 新旧版本创建SolrClient对比

    在Java中使用solr 版本7.2.0 solrj已经更新到了7.2.0,新版本solr获取SolrClient的方式也和之前旧版本有所不同 solr6.5开始不推荐直接使用HttpSolrClie ...

  7. 1、linux基础优化

    1.添加一个用户 [root@oldboy ~]# useradd oldboy [root@oldboy ~]# id oldboy uid=500(oldboy) gid=500 (oldboy) ...

  8. RT-Thread中的串口DMA分析

    这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...

  9. 神经网络优化算法:梯度下降法、Momentum、RMSprop和Adam

    最近回顾神经网络的知识,简单做一些整理,归档一下神经网络优化算法的知识.关于神经网络的优化,吴恩达的深度学习课程讲解得非常通俗易懂,有需要的可以去学习一下,本人只是对课程知识点做一个总结.吴恩达的深度 ...

  10. DNS信息探测

    前面学习一下DNS域名解析原理及过程,今天我们学习下DNS域名信息的探测 本章主要目标是从各个角度搜集测试目标的基本信息,包括搜集信息的途径.各种工具的使用方法,以及简单的示例. 0x00 DNS信息 ...