【问题标题】:Create test/train split based on two groups with Pandas Scikit-learn使用 Pandas Scikit-learn 基于两组创建测试/训练拆分
【发布时间】:2015-11-19 21:59:36
【问题描述】:

我有一个 Pandas 数据框:comb ENROLLED_Response 条目的数量非常少,因此仅对整个 DataFrame 进行随机抽样可能会丢失太多已注册的数据。

解决方案是从ENROLLED_Response == True 的所有条目中抽取 75% 的样本 然后对 ENROLLED_Response == False 的所有条目进行 70% 的抽样

所以我应该在 DataFrame 上以 is_traintrue/false 列结束

所以我通常使用类似的东西:

from sklearn.cross_validation import cross_val_score

#split the dataset for train and test
comb['is_train'] = np.random.uniform(0, 1, len(comb)) <= .75
train, test = comb[comb['is_train']==True],  comb[comb['is_train']==False]

这对大多数情况来说都很好,但由于注册人数很少,这种方法往往会遗漏太多“注册”,因为人数太少了。所以我需要的更像是:

comb['is_train'] = train_test_split(comb['ENROLLED_Response']==True, Train_size = 0.75)
comb['is_train']= train_test_split(comb['ENROLLED_Response']==False, Train_size = 0.75)

这当然行不通。概念是:第一次对已注册的样本进行抽样并将其中的 0.75 个随机标记为火车,然后在同一新列 (is_train) 中对未注册的样本(其他所有内容)进行抽样并将其中的 0.75 个标记为火车,这样它就可以很容易在 Scikit_learn 中使用,例如:

train, test = comb[comb['is_train']==True],comb[comb['is_train']==False]

由于 random 生成的 np 数组是相对于整个 DataFrame 的长度的(以及其他问题......),所以无法弄清楚如何做到这一点。

【问题讨论】:

    标签: python pandas scikit-learn


    【解决方案1】:

    评论后更新:

    import pandas as pd
    import numpy as np
    
    np.random.seed(42)
    
    truePct = 0.75
    falsePct = 0.70
    
    comb = pd.DataFrame({ 
        "feat1": np.random.randint(low=1, high=4, size=20),
        "feat2": np.random.randint(low=1, high=4, size=20),
        "ENROLLED_Response": np.random.randint(low=0, high=4, size=20)==3
    })
    
    # Set train to False by default
    comb['train'] = False
    
    # Create two permutations for both classes
    nTrue = comb[comb.ENROLLED_Response==True].shape[0]
    nFalse = comb[comb.ENROLLED_Response==False].shape[0]
    truePerm = np.random.permutation(nTrue)[:int(np.floor(truePct*nTrue)-1)]
    falsePerm = np.random.permutation(nFalse)[:int(np.floor(falsePct*nFalse)-1)]
    
    # Select the indices
    trainTrueIndex = comb[comb.ENROLLED_Response==True].index[truePerm].values.tolist()
    trainFalseIndex = comb[comb.ENROLLED_Response==False].index[falsePerm].values.tolist()
    
    comb.loc[trainTrueIndex,'train'] = True
    comb.loc[trainFalseIndex,'train'] = True
    
    print comb
    

    结果

       ENROLLED_Response  feat1  feat2  train
    0              False      3      1  False
    1              False      1      1  False
    2              False      3      2  False
    3              False      3      2  False
    4              False      1      1   True
    5              False      1      1   True
    6              False      3      1   True
    7               True      2      3   True
    8              False      3      3  False
    9               True      3      3   True
    10             False      3      2   True
    11             False      3      3   True
    12             False      1      2   True
    13             False      3      2   True
    14             False      2      3  False
    15             False      1      2   True
    16             False      2      3   True
    17              True      2      3  False
    18              True      2      1  False
    19             False      2      3   True
    

    我不完全相信我正确地解释了您的问题,但您似乎正在处理 ENROLLED_Response 变量中的类不平衡问题。为了保持训练集和测试集的类不平衡,您可能需要使用不同的 Scikit-Learn 交叉验证函数:StratifiedShuffleSplit

    这个函数是 StratifiedKFold 和 ShuffleSplit 的合并,它返回分层的随机折叠。通过保留每个类的样本百分比来进行折叠。

    【讨论】:

    • 我认为您的解释正确,但是我认为我的内存限制阻止了我使用这种方法,我有大约 350,000 行......所以我在调用“shuffleSplit”之类的东西时遇到了内存问题,因此我试图弄清楚如何更直接地处理..
    • 看起来不错,需要等待一段时间才能标记完成,需要测试并离开一周(是的!)谢谢
    猜你喜欢
    • 2015-06-08
    • 2019-04-10
    • 2020-06-22
    • 2017-04-11
    • 2018-04-22
    • 2021-06-20
    • 2021-07-26
    • 2018-12-07
    • 2020-09-01
    相关资源
    最近更新 更多