随机拆分训练和测试数据
Posted
技术标签:
【中文标题】随机拆分训练和测试数据【英文标题】:Randomly splitting training and testing data 【发布时间】:2016-12-01 13:34:10 【问题描述】:我有大约 3000 个对象,其中每个对象都有一个与之关联的计数。我想将这些对象在训练和测试数据中随机划分为 70% 训练和 30% 的测试分开。但是,我想根据与每个对象关联的计数来划分它们,而不是根据对象的数量。
举个例子,假设我的数据集包含 5 个对象。
Obj 1 => 200
Obj 2 => 30
Obj 3 => 40
Obj 4 => 20
Obj 5 => 110
如果我以接近 70%-30% 的比例拆分它们,我的训练集应该是
Obj 2 => 30
Obj 3 => 40
Obj 4 => 20
Obj 5 => 110
我的测试集是
Obj 1 => 200
如果我再次拆分它们,我应该得到一个接近 70-30 拆分比率的不同训练和测试集。我知道上面的分割并没有给我纯粹的 70-30 分割,但只要它接近它,它是可以接受的。
是否有任何预定义的方法/包可以在 Python 中执行此操作?
【问题讨论】:
Numpy: How to split/partition a dataset (array) into training and test datasets for, e.g., cross validation?的可能重复 只是为了记录,这可能是一个非常糟糕的主意。您通常希望保持您的训练集相同,这样您就不会针对您的测试数据进行训练。 【参考方案1】:假设我正确理解您的问题,我的建议是:
from random import shuffle
sum = sum([obj.count for obj in obj_list]) #Get the total "count" of all the objects, O(n)
shuffle(obj_list)
running_sum = 0
i = 0
while running_sum < sum * .3
running_sum += obj_list[i].count
i += 1
training_data = obj_list[i:]
testing_data = obj_list[:i]
整个操作是 O(n),你不会得到比这更好的时间复杂度。当然有办法将循环和诸如此类的东西压缩成一个衬垫,但我不知道有任何内置函数可以用一个函数完成你所要求的,尤其是当你要求它在某种意义上是“随机的”时每次拆分时都需要不同的训练/测试集(据我了解)
【讨论】:
感谢您的回复。你已经正确理解了我的问题。该方法非常优化。我同意要得到总和,我必须将它遍历所有对象一次。因此,O(n)。但是,if running_sum > sum * .7
行将使训练集始终超过 70%,我的说法是否正确。
更多单项,你是对的。我想我假设在一组 3000 件物品上,一件物品不会有很大的不同。如果这是一个问题,那么我会添加行 i -= randint(0,1) 以便它随机地略低于 0.7 或略高于
我还进行了编辑以使循环在 0.3 之后停止,意识到您只需要找到第一个 .3 即可知道 0.7,因此转到 .3 更快 - 这将节省一些时间,不知道为什么我最初没有想到这一点
在这种情况下,第一次进入的可能性可能远大于 30%(比如 50%)。所以,你最终会出现不必要的分裂。运行到 0.7 的循环提供了更大的安全网。
@Learner 这取决于测试数据的统一程度。如果数据超出了可接受的范围,您当然可以编写该函数以重试或跳过数据,但这样做的缺点是它使其不是均匀随机的。不过你是对的,如果精确接近 0.7 比函数的速度更重要,那么循环到 0.7 可能会更好【参考方案2】:
我不知道Python中是否有特定的函数,但假设没有,这里有一个方法。
随机播放对象:
from random import shuffle
values = shuffle[200, 40, 30, 110, 20]
计算字典值的百分比:
prob = [float(i)/sum(values) for i in values]
应用循环:
sum=0
for i in range(len(result)):
if sum>0.7:
index=i-1
break
sum=sum+result[i]
现在,索引之前的对象是训练对象,索引之后是测试对象。
【讨论】:
以上是关于随机拆分训练和测试数据的主要内容,如果未能解决你的问题,请参考以下文章