根据类别分布在训练和测试之间划分数据集[重复]

Posted

技术标签:

【中文标题】根据类别分布在训练和测试之间划分数据集[重复]【英文标题】:Divide dataset between train and test respecting class distribution [duplicate] 【发布时间】:2020-08-11 23:25:46 【问题描述】:

我想在具有以下分布的给定数据集中运行 10 次机器学习算法

np.unique(x[:,24], return_counts=True)
(array([1., 2.]), array([700, 300]))

这意味着我 70% 的数据来自第 1 类,30% 来自第 2 类。

下面是我的数据的快照。最后一列通知类标签(1 或 2):

1,6,4,12,5,5,3,4,1,67,3,2,1,2,1,0,0,1,0,0,1,0,0,1,1
2,48,2,60,1,3,2,2,1,22,3,1,1,1,1,0,0,1,0,0,1,0,0,1,2
4,12,4,21,1,4,3,3,1,49,3,1,2,1,1,0,0,1,0,0,1,0,1,0,1
1,42,2,79,1,4,3,4,2,45,3,1,2,1,1,0,0,0,0,0,0,0,0,1,1
1,24,3,49,1,3,3,4,4,53,3,2,2,1,1,1,0,1,0,0,0,0,0,1,2
4,36,2,91,5,3,3,4,4,35,3,1,2,2,1,0,0,1,0,0,0,0,1,0,1
4,24,2,28,3,5,3,4,2,53,3,1,1,1,1,0,0,1,0,0,1,0,0,1,1
2,36,2,69,1,3,3,2,3,35,3,1,1,2,1,0,1,1,0,1,0,0,0,0,1
4,12,2,31,4,4,1,4,1,61,3,1,1,1,1,0,0,1,0,0,1,0,1,0,1
2,30,4,52,1,1,4,2,3,28,3,2,1,1,1,1,0,1,0,0,1,0,0,0,2
2,12,2,13,1,2,2,1,3,25,3,1,1,1,1,1,0,1,0,1,0,0,0,1,2
1,48,2,43,1,2,2,4,2,24,3,1,1,1,1,0,0,1,0,1,0,0,0,1,2
2,12,2,16,1,3,2,1,3,22,3,1,1,2,1,0,0,1,0,0,1,0,0,1,1
1,24,4,12,1,5,3,4,3,60,3,2,1,1,1,1,0,1,0,0,1,0,1,0,2
1,15,2,14,1,3,2,4,3,28,3,1,1,1,1,1,0,1,0,1,0,0,0,1,1
1,24,2,13,2,3,2,2,3,32,3,1,1,1,1,0,0,1,0,0,1,0,1,0,2
4,24,4,24,5,5,3,4,2,53,3,2,1,1,1,0,0,1,0,0,1,0,0,1,1
1,30,0,81,5,2,3,3,3,25,1,3,1,1,1,0,0,1,0,0,1,0,0,1,1
2,24,2,126,1,5,2,2,4,44,3,1,1,2,1,0,1,1,0,0,0,0,0,0,2
4,24,2,34,3,5,3,2,3,31,3,1,2,2,1,0,0,1,0,0,1,0,0,1,1
4,9,4,21,1,3,3,4,3,48,3,3,1,2,1,1,0,1,0,0,1,0,0,1,1
1,6,2,26,3,3,3,3,1,44,3,1,2,1,1,0,0,1,0,1,0,0,0,1,1
1,10,4,22,1,2,3,3,1,48,3,2,2,1,2,1,0,1,0,1,0,0,1,0,1
2,12,4,18,2,2,3,4,2,44,3,1,1,1,1,0,1,1,0,0,1,0,0,1,1
4,10,4,21,5,3,4,1,3,26,3,2,1,1,2,0,0,1,0,0,1,0,0,1,1
1,6,2,14,1,3,3,2,1,36,1,1,1,2,1,0,0,1,0,0,1,0,1,0,1
4,6,0,4,1,5,4,4,3,39,3,1,1,1,1,0,0,1,0,0,1,0,1,0,1
3,12,1,4,4,3,2,3,1,42,3,2,1,1,1,0,0,1,0,1,0,0,0,1,1
2,7,2,24,1,3,3,2,1,34,3,1,1,1,1,0,0,0,0,0,1,0,0,1,1
1,60,3,68,1,5,3,4,4,63,3,2,1,2,1,0,0,1,0,0,1,0,0,1,2
2,18,2,19,4,2,4,3,1,36,1,1,1,2,1,0,0,1,0,0,1,0,0,1,1
1,24,2,40,1,3,3,2,3,27,2,1,1,1,1,0,0,1,0,0,1,0,0,1,1
2,18,2,59,2,3,3,2,3,30,3,2,1,2,1,1,0,1,0,0,1,0,0,1,1
4,12,4,13,5,5,3,4,4,57,3,1,1,1,1,0,0,1,0,1,0,0,1,0,1
3,12,2,15,1,2,2,1,2,33,1,1,1,2,1,0,0,1,0,0,1,0,0,0,1
2,45,4,47,1,2,3,2,2,25,3,2,1,1,1,0,0,1,0,0,1,0,1,0,2
4,48,4,61,1,3,3,3,4,31,1,1,1,2,1,0,0,1,0,0,0,0,0,1,1

完整的数据集可以在here找到

我想将数据分成 90% 用于训练和 10% 用于测试。但是,对于每个拆分,我必须保持数据的比例(例如,在训练和验证拆分中,70% 的数据必须属于 1 类,30% 属于 2 类)

我知道如何简单地将数据划分为训练和测试,但我不知道如何使这种划分服从我上面引用的类分布。如何在 Python 中做到这一点?

【问题讨论】:

我认为在您上次的编辑中,您是否想重复训练/测试拆分 10 次并不清楚。之前好像更清楚了 只需使用 scikit-learn 的 train_test_split 和参数 stratify=y(其中 y 是您的类变量)scikit-learn.org/stable/modules/generated/… 看起来 op 想要重复这个 n 次。来自未经编辑的问题this should be repeated 10 times。所以我的猜测是 OP 想在这里执行某种 k_fold 交叉验证。所以RepeatedStratifiedKFold 似乎是适应这些要求的好方法。 train_test_split 本身无法做到这一点@desertnaut 我理解正确吗@mad?你想重复训练/测试拆分 10 次吗? 在这种情况下,您可以按照 Desertnaut 的建议使用 train_test_split 。使用RepeatedStratifiedKFold 的全部意义在于回答最初提出的问题,因此重复拆分 n 次 【参考方案1】:

一种众所周知的将数据拆分为训练和测试的方法是 scikit-learn train_test_split

model_selection.train_test_split 的 API 文档。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.10, random_state=42)

您可以使用random_state 变量(种子),直到您的类之间的比例正确为止。虽然train_test_split 不会强制执行比例,但它通常遵循人口比例。

【讨论】:

train_test_split 使用stratify参数scikit-learn.org/stable/modules/generated/…强制比例【参考方案2】:

您可以使用RepeatedStratifiedKFold,顾名思义,它会重复K-Fold 交叉验证器n 次。要重复这个过程10 次,设置n_repeats,并在train/test 大小中大约有9:1 的比例,我们可以设置n_splits=10

from sklearn.model_selection import RepeatedStratifiedKFold

X = a[:,:-1]
y = a[:,-1]

rskf = RepeatedStratifiedKFold(n_splits=10, n_repeats=10, random_state=2)

for train_index, test_index in rskf.split(X, y):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    print(f'\nClass 1: ((y_train==1).sum()/len(y_train))*100:.0f%') 
    print(f'\nShape of train: X_train.shape[0]')
    print(f'Shape of test: X_test.shape[0]')

Class 1: 73%

Shape of train: 33
Shape of test: 4

Class 1: 73%

Shape of train: 33
Shape of test: 4

Class 1: 73%

Shape of train: 33
Shape of test: 4

Class 1: 73%

Shape of train: 33
Shape of test: 4
...

【讨论】:

感谢您的回答。命令会尊重类之间的比例吗?我的意思是,在每个训练/测试分组中,我会有 70% 的课程和 30% 的课程吗? 是的,请查看打印声明。这基本上就是StratifiedKFold 所做的@mad。来自文档:The folds are made by preserving the percentage of samples for each class.

以上是关于根据类别分布在训练和测试之间划分数据集[重复]的主要内容,如果未能解决你的问题,请参考以下文章

数据集的划分

机器学习100天:005 数据预处理之划分训练集

机器学习100天:005 数据预处理之划分训练集

22在不同的划分上进行训练和测试

划分训练、测试集和数据观察

技巧 - 训练集与测试集划分方法