Python 2.7 使用分组约束在sklearn(python 2.7)中创建训练、测试和交叉验证数据集?

Python 2.7 使用分组约束在sklearn(python 2.7)中创建训练、测试和交叉验证数据集?,python-2.7,numpy,machine-learning,data-mining,scikit-learn,Python 2.7,Numpy,Machine Learning,Data Mining,Scikit Learn,在用Python创建train、test和cross validation示例时,我将默认方法视为-: 1。跳过标题后读取数据集 2.创建培训、测试和交叉验证样本 import csv with open('C:/Users/Train/Trainl.csv', 'r') as f1: next(f1) reader = csv.reader(f1, delimiter=',') input_set = [] for row in reader:

在用Python创建train、test和cross validation示例时,我将默认方法视为-:

1。跳过标题后读取数据集 2.创建培训、测试和交叉验证样本

 import csv
 with open('C:/Users/Train/Trainl.csv', 'r') as f1:
     next(f1)
     reader = csv.reader(f1, delimiter=',')
     input_set = []   
     for row in reader:
         input_set.append(row)

import numpy as np 
from numpy import genfromtxt
from sklearn import cross_validation
train, intermediate_set = cross_validation.train_test_split(input_set, train_size=0.6, test_size=0.4)
cv, test = cross_validation.train_test_split(intermediate_set, train_size=0.5, test_size=0.5)
但我的问题是,我在csv文件中有一个字段称为“a”,我将该字段读入numpy数组,所有采样都应该尊重该字段。也就是说,所有具有类似“A”值的条目都应该放在一个样本中

Line #|A | B | C | D 
1     |1 | 
2     |1 |
3     |1 |
4     |1 |
5     |2 |
6     |2 |
7     |2 |
必需:第1、2、3、4行应包含在“一”样本中,第5、6、7行应包含在“一”样本中。 列A的值是一个唯一的id,对应于一个实体(可以被视为单个用户上的横截面数据点,因此它必须放在火车、测试或cv的一个唯一样本中),并且有许多这样的实体,因此需要按实体id进行分组。

B、C、D列可以有任何值,但它们不需要分组保存。(奖励:我可以为多个字段分组采样吗?)

我的尝试:

A.查找A的所有唯一值-将其表示为我的样本,我现在将样本分发到st train、intermediate&cv&test->中,然后将此值“A”的其余行放入每个文件中。 也就是说,如果列车有“3”的条目,“2”的测试和“1”的cv,那么所有值为A的行都将进入列车,所有行都将进行2次进入测试,所有行都将进行1次进入cv

  • 当然,这种方法是不可伸缩的
  • 我怀疑,这可能会在数据集中引入偏差,因为A列中1的数量、2的数量等不相等,这意味着这种方法将不起作用 B.我也尝试了numpy.random.shuffle,或numpy.random.permutation,根据这里的线程-,但它不符合我的要求

    C.第三种选择当然是编写一个自定义函数来进行分组,然后根据每组中的数据点数量平衡训练、测试和cv数据集。但我只是想知道,是否已经有一种有效的方法来实现这一点

    请注意,我的数据集很大,因此理想情况下,我希望有一种确定的方法来划分数据集,而不需要进行多次眼珠扫描以确保划分正确

    编辑第2部分:

    因为我没有找到任何符合我的采样标准的,所以我实际上编写了一个模块来使用分组约束进行采样。这是它的github代码。代码不是为非常大的数据编写的,因此效率不高。如果您需要这段代码,请指出如何改进运行时。

    通过强制执行此类约束,您将对您的程序产生偏见。所以,基于对“用户”数据进行分区,然后收集他们各自的“度量”的方法似乎并不坏。它可以很好地扩展,这是
    O(n)
    方法,没有扩展的唯一原因是糟糕的实现,而不是糟糕的方法

    现有方法(如sklearn库)中没有此类功能的原因是,它看起来非常人工,并且与机器学习模型相反。如果这些实体是一个实体,则不应将它们视为单独的数据点。如果您需要这个单独的表示,那么需要这样的划分,特定的实体不能部分在测试中,部分在训练中,这肯定会使整个模型产生偏差

    总之,你应该从机器学习的角度深入分析你的方法是否合理。如果您确信这一点,我认为唯一的可能性是自己编写分段,因为即使在过去使用了许多ML库,我也从未见过这样的功能


    事实上,我不确定,如果将包含N个数字(实体大小)的集合分割为具有均匀分布的给定和比例的K(=3)子集(当视为随机过程时),该问题本身不是NP问题。如果您不能保证均匀分布,那么您的数据集就不能用作培训/测试/验证模型的统计正确方法。即使它有一个合理的多项式解,它仍然可以严重放大(比线性方法更糟糕)。如果您的约束是“严格的”,如果约束是“弱的”,您可以始终采用“生成并拒绝”的方法,这本应分摊线性复杂度。

    我也面临类似的问题,尽管我的编码不太好,但我提出了如下解决方案:

  • 创建了一个仅包含df唯一Id的新数据框,并删除了重复项
  • 根据新的_DF创建培训和测试集
  • 然后将这些训练和测试集与原始df合并 同样,我们也可以为验证部分创建示例


    干杯。

    感谢@lejlot——更具体地说,我的应用程序——对于我的用例,我有一些用户收到了项目建议列表,因此一个用户有多个条目。即,每个用户推荐的确切数量是不同的。这里我只知道一些条目属于一个用户,它们与其他用户不同。我的目标是更好地利用现有的推荐列表,比如上面的“B”列。除了引入这种人为偏差+平衡测试、训练和cv数据集的每个数据点的总数之外,还有其他想法吗?在重新编码系统中,您只是像往常一样分割数据,对实体没有任何约束,应用任何其他东西都没有意义,因为您的系统不仅应该能够预测“空白”的重新编码(新)用户,但也向现有用户建议新项目,因此实际上应该以一种方式进行拆分,即所有列车/测试/cv拆分中都有一个用户。如果关于o的知识
    new = df[["Unique_Id "]].copy()
    New_DF = new.drop_duplicates()
    
    train, test = train_test_split(New_DF, test_size=0.2)
    
    df_Test = pd.merge(df, test, how='inner', on = “Unique_Id”)
    df_Train = pd.merge(df, train, how='inner', on = “Unique_Id”)