拆分 k 折,其中每折验证数据不包含重复项

Split k-fold where each fold of validation data doesn't include duplicates

假设我有一个 pandas 数据框 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个数据,其中190个数据为class 0,10个数据为class 1(即保留每个class的样本百分比)。

我试过 StratifiedShuffleSplit 来自 sklearn.model_selection,如下所示。

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.

中给我重复项

有人可以帮助我吗?

您需要的是用于交叉验证的 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