Sklearn 中分层 KFold 与分层 ShuffleSplit 的区别

从标题来看,我想知道

参数为 shuffle=True的 StratifiedKFold

StratifiedKFold(n_splits=10, shuffle=True, random_state=0)

还有

分层的 ShuffleSplit

StratifiedShuffleSplit(n_splits=10, test_size=’default’, train_size=None, random_state=0)

以及使用 StratifiedShuffleSplit 的优点是什么

46972 次浏览

stratKFolds中,即使包含了洗牌,每个测试集也不应该重叠。使用 stratKFoldsshuffle=True,数据在开始时被重新洗牌一次,然后分成所需的拆分数。测试数据总是其中的一部分,列车数据是其余部分。

ShuffleSplit中,每次都要对数据进行洗牌,然后进行拆分。这意味着测试集可能在拆分之间重叠。

有关差异的示例,请参见此块。请注意 ShuffleSplit测试集中元素的重叠。

splits = 5


tx = range(10)
ty = [0] * 5 + [1] * 5


from sklearn.model_selection import StratifiedShuffleSplit, StratifiedKFold
from sklearn import datasets


stratKfold = StratifiedKFold(n_splits=splits, shuffle=True, random_state=42)
shufflesplit = StratifiedShuffleSplit(n_splits=splits, random_state=42, test_size=2)


print("stratKFold")
for train_index, test_index in stratKfold.split(tx, ty):
print("TRAIN:", train_index, "TEST:", test_index)


print("Shuffle Split")
for train_index, test_index in shufflesplit.split(tx, ty):
print("TRAIN:", train_index, "TEST:", test_index)

产出:

stratKFold
TRAIN: [0 2 3 4 5 6 7 9] TEST: [1 8]
TRAIN: [0 1 2 3 5 7 8 9] TEST: [4 6]
TRAIN: [0 1 3 4 5 6 8 9] TEST: [2 7]
TRAIN: [1 2 3 4 6 7 8 9] TEST: [0 5]
TRAIN: [0 1 2 4 5 6 7 8] TEST: [3 9]
Shuffle Split
TRAIN: [8 4 1 0 6 5 7 2] TEST: [3 9]
TRAIN: [7 0 3 9 4 5 1 6] TEST: [8 2]
TRAIN: [1 2 5 6 4 8 9 0] TEST: [3 7]
TRAIN: [4 6 7 8 3 5 1 2] TEST: [9 0]
TRAIN: [7 2 6 5 4 3 0 9] TEST: [1 8]

至于何时使用它们,我倾向于使用 stratKFolds进行任何交叉验证,并且我使用 ShuffleSplit和2分割来进行火车/测试集分割。但我相信两者都有其他用例。

@ Ken Syme 已经有了一个很好的答案,我只是想补充一些东西。

  • StratifiedKFold KFold的变异体。首先,StratifiedKFold对数据进行洗牌,然后将数据分成 n_splits部分和完成部分。 现在,它将使用每个部分作为一个测试集。

对于 shuffle = True,数据被 random_state洗牌。否则, 数据由 np.random(默认情况下)洗牌。 例如,使用 n_splits = 4,您的数据对于 y(因变量)有3个类(label)。4个测试集覆盖所有数据,没有任何重叠。

enter image description here

  • 另一方面,StratifiedShuffleSplitShuffleSplit的一个变种。 首先,StratifiedShuffleSplit对数据进行洗牌,然后将数据分割成 n_splits部分。但是,还没有完成。在此步骤之后,StratifiedShuffleSplit选择一个部件作为测试集使用。 然后,它重复相同的过程 n_splits - 1其他时间,以获得 n_splits - 1其他测试集。看下面的图片,有相同的数据,但是这一次,4个测试集不覆盖所有的数据,即测试集之间存在重叠。

enter image description here

所以,这里的区别是 StratifiedKFold 只是洗牌和分裂一次,因此测试集不重叠,而 StratifiedShuffleSplit 每次分割前进行洗牌,分割 n_splits次,测试集可以重叠

  • 注意 : 这两个方法使用“分层折叠”(这就是为什么“分层”出现在两个名称中)。这意味着每个部分保留了与原始数据相同百分比的每个类(标签)的样本。您可以在交叉验证文档中阅读更多内容

KFold,StratifiedKFold,StratifiedShuffleSplit 的输出示例: Output examples of KFold, StratifiedKFold, StratifiedShuffleSplit

上面的图片输出是 @Ken Syme代码的扩展:

from sklearn.model_selection import KFold, StratifiedKFold, StratifiedShuffleSplit
SEED = 43
SPLIT = 3


X_train = [0,1,2,3,4,5,6,7,8]
y_train = [0,0,0,0,0,0,1,1,1]   # note 6,7,8 are labelled class '1'


print("KFold, shuffle=False (default)")
kf = KFold(n_splits=SPLIT, random_state=SEED)
for train_index, test_index in kf.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)


print("KFold, shuffle=True")
kf = KFold(n_splits=SPLIT, shuffle=True, random_state=SEED)
for train_index, test_index in kf.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)


print("\nStratifiedKFold, shuffle=False (default)")
skf = StratifiedKFold(n_splits=SPLIT, random_state=SEED)
for train_index, test_index in skf.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)
    

print("StratifiedKFold, shuffle=True")
skf = StratifiedKFold(n_splits=SPLIT, shuffle=True, random_state=SEED)
for train_index, test_index in skf.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)
    

print("\nStratifiedShuffleSplit")
sss = StratifiedShuffleSplit(n_splits=SPLIT, random_state=SEED, test_size=3)
for train_index, test_index in sss.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)


print("\nStratifiedShuffleSplit (can customise test_size)")
sss = StratifiedShuffleSplit(n_splits=SPLIT, random_state=SEED, test_size=2)
for train_index, test_index in sss.split(X_train, y_train):
print("TRAIN:", train_index, "TEST:", test_index)