Python scikit学习中的随机分层k倍交叉验证?
是否有任何内置方法让scikit学习执行混合分层k折叠交叉验证?这是最常见的CV方法之一,我很惊讶我没有找到一个内置的方法来实现这一点 我看到Python scikit学习中的随机分层k倍交叉验证?,python,machine-learning,scikit-learn,cross-validation,Python,Machine Learning,Scikit Learn,Cross Validation,是否有任何内置方法让scikit学习执行混合分层k折叠交叉验证?这是最常见的CV方法之一,我很惊讶我没有找到一个内置的方法来实现这一点 我看到cross\u validation.KFold()有一个洗牌标志,但它不是分层的。不幸的是,cross\u validation.StratifiedKFold()没有这样的选项,cross\u validation.StratifiedShuffleSplit()不会产生不相交的折叠 我错过什么了吗?这是计划吗 (显然我可以自己实现)据我所知,这实际上
cross\u validation.KFold()
有一个洗牌标志,但它不是分层的。不幸的是,cross\u validation.StratifiedKFold()
没有这样的选项,cross\u validation.StratifiedShuffleSplit()
不会产生不相交的折叠
我错过什么了吗?这是计划吗
(显然我可以自己实现)据我所知,这实际上是在scikit learn中实现的 “”“ 分层ShuffleSplit交叉验证迭代器 提供列车/测试索引以分割列车测试集中的数据 此交叉验证对象是分层折叠和 ShuffleSplit,返回分层随机折叠 通过保留每个类的样本百分比来生成 注意:与ShuffleSplit策略一样,分层随机拆分 不要保证所有折叠都会不同,尽管这是 对于大型数据集,仍然非常可能。
“我想我会发布我的解决方案,以防它对其他人有用
from collections import defaultdict
import random
def strat_map(y):
"""
Returns permuted indices that maintain class
"""
smap = defaultdict(list)
for i,v in enumerate(y):
smap[v].append(i)
for values in smap.values():
random.shuffle(values)
y_map = np.zeros_like(y)
for i,v in enumerate(y):
y_map[i] = smap[v].pop()
return y_map
##########
#Example Use
##########
skf = StratifiedKFold(y, nfolds)
sm = strat_map(y)
for test, train in skf:
test,train = sm[test], sm[train]
#then cv as usual
#######
#tests#
#######
import numpy.random as rnd
for _ in range(100):
y = np.array( [0]*10 + [1]*20 + [3] * 10)
rnd.shuffle(y)
sm = strat_map(y)
shuffled = y[sm]
assert (sm != range(len(y))).any() , "did not shuffle"
assert (shuffled == y).all(), "classes not in right position"
assert (set(sm) == set(range(len(y)))), "missing indices"
for _ in range(100):
nfolds = 10
skf = StratifiedKFold(y, nfolds)
sm = strat_map(y)
for test, train in skf:
assert (sm[test] != test).any(), "did not shuffle"
assert (y[sm[test]] == y[test]).all(), "classes not in right position"
当前版本0.15中引入了
交叉验证.StratifiedKFold
的洗牌标志:
这可以在变更日志中找到:
用于交叉验证的洗牌选项。分层折叠。杰弗里
布莱克本
以下是我将分层洗牌分解为训练集和测试集的实现:
import numpy as np
def get_train_test_inds(y,train_proportion=0.7):
'''Generates indices, making random stratified split into training set and testing sets
with proportions train_proportion and (1-train_proportion) of initial sample.
y is any iterable indicating classes of each observation in the sample.
Initial proportions of classes inside training and
test sets are preserved (stratified sampling).
'''
y=np.array(y)
train_inds = np.zeros(len(y),dtype=bool)
test_inds = np.zeros(len(y),dtype=bool)
values = np.unique(y)
for value in values:
value_inds = np.nonzero(y==value)[0]
np.random.shuffle(value_inds)
n = int(train_proportion*len(value_inds))
train_inds[value_inds[:n]]=True
test_inds[value_inds[n:]]=True
return train_inds,test_inds
y = np.array([1,1,2,2,3,3])
train_inds,test_inds = get_train_test_inds(y,train_proportion=0.5)
print y[train_inds]
print y[test_inds]
此代码输出:
[1 2 3]
[1 2 3]
正如我在问题中所写的,StratifiedShuffleSplit()不执行StratifiedKFold()的洗牌版本,即在StratifiedKFold()之前进行洗牌。你的答案的最后一句甚至提到了这一点。KFold CV要求折叠之间没有交集,并且它们的并集是整个数据集。啊,是的,折叠不保证分离。对不起,没有读到你问题的结尾。。