【问题标题】:Split k-fold where each fold of validation data doesn't include duplicates拆分 k 折,其中每折验证数据不包含重复项
【发布时间】:2021-10-04 08:00:18
【问题描述】:

假设我有一个熊猫数据框dfdf 包含 1,000 行。如下所示。

print(df)

                    id    class
0      0000799a2b2c42d       0
1      00042890562ff68       0
2      0005364cdcb8e5b       0
3      0007a5a46901c56       0
4      0009283e145448e       0
...                ...     ...
995    04309a8361c5a9e       0
996    0430bde854b470e       0
997    0431c56b712b9a5       1
998    043580af9803e8c       0
999    043733a88bfde0c       0

它有950个数据class 0和50个数据class 1

现在我想再添加一列作为fold,如下所示。

                    id    class  fold
0      0000799a2b2c42d       0     0
1      00042890562ff68       0     0
2      0005364cdcb8e5b       0     0
3      0007a5a46901c56       0     0
4      0009283e145448e       0     0
...                ...     ...   ...
995    04309a8361c5a9e       0     4
996    0430bde854b470e       0     4
997    0431c56b712b9a5       1     4
998    043580af9803e8c       0     4
999    043733a88bfde0c       0     4

fold 列包含 5 个折叠 (0,1,2,3,4)。每个折叠有200个数据,其中class 0有190个数据,class 1有10个数据(这意味着保留每个class的样本百分比)。

我已经从sklearn.model_selection 尝试了StratifiedShuffleSplit,如下所示。

sss = StratifiedShuffleSplit(n_split=5, random_state=2021, test_size = 0.2)
for _, val_index in sss.split(df.id, df.class):
    ....

然后我将val_index 的每个列表视为一个特定的折叠,但它最终会在每个val_index 中给我重复。

有人可以帮我吗?

【问题讨论】:

  • 你的问题不清楚;您说您希望每个 val-set 包含非重复项,而作为不会发生这种情况的证据,您指的是 train 折叠。根据定义,在 k-fold CV 中,每个样本将在 (k-1) training 折中,并且仅在 1 validation 折中; validation 折叠中不存在重复项。
  • 也不清楚为什么要附加训练和测试索引,这不是使用 k-fold CV 的正确方法;这样,在 for 循环之后,您将简单地以 train_indexestest_indexes 中的整个数据集结束,这不是重点。
  • 已编辑,希望描述清楚。

标签: python scikit-learn cross-validation k-fold


【解决方案1】:

您需要的是用于交叉验证的 kfold,而不是训练测试拆分。你可以使用StratifiedKFold,例如你的数据集是这样的:

import pandas as pd
import numpy as np
from sklearn.model_selection import StratifiedKFold

np.random.seed(12345)
df = pd.DataFrame({'id' : np.random.randint(1,1e5,1000),
'class' :np.random.binomial(1,0.1,1000)})
df['fold'] = np.NaN

我们使用 kfold,像您一样遍历并分配折叠编号:

skf = StratifiedKFold(n_splits=5,shuffle=True)
for fold, [train,test] in enumerate(skf.split(df,df['class'])):
    df.loc[test,"fold"] = fold

最终产品:

pd.crosstab(df['fold'],df['class'])

class    0   1
fold          
0.0    182  18
1.0    182  18
2.0    182  18
3.0    182  18
4.0    181  19  

【讨论】:

    猜你喜欢
    • 2016-08-10
    • 2016-09-30
    • 2022-01-16
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 2016-01-15
    • 2017-09-22
    相关资源
    最近更新 更多