Python 内存有效的将大型numpy阵列拆分为训练和测试的方法

Python 内存有效的将大型numpy阵列拆分为训练和测试的方法,python,arrays,scikit-learn,Python,Arrays,Scikit Learn,我有一个大的numpy数组,当我运行scikit learn的train_test_split将数组拆分为训练和测试数据时,我总是会遇到内存错误。什么是一种更有效的内存分割为训练和测试的方法,为什么训练和测试分割会导致这种情况 以下代码导致内存错误并导致崩溃 import numpy as np from sklearn.cross_validation import train_test_split X = np.random.random((10000,70000)) Y = np.ran

我有一个大的numpy数组,当我运行scikit learn的train_test_split将数组拆分为训练和测试数据时,我总是会遇到内存错误。什么是一种更有效的内存分割为训练和测试的方法,为什么训练和测试分割会导致这种情况

以下代码导致内存错误并导致崩溃

import numpy as np
from sklearn.cross_validation import train_test_split

X = np.random.random((10000,70000))
Y = np.random.random((10000,))
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.33, random_state=42)

我认为一种更有效的内存方法是迭代地选择实例进行训练和测试,不过,正如计算机科学中的典型情况一样,使用矩阵会牺牲固有的效率

您可以做的是迭代数组,对于每个实例,“掷硬币”使用随机包来确定是否将实例用作训练或测试,并根据具体情况将实例存储在适当的numpy数组中

这种迭代方法只适用于10000个实例。但奇怪的是,10000 X 70000并没有那么大;你在运行什么类型的机器?让我想知道这是Python/numpy/scikit问题还是机器问题


不管怎样,希望这有帮助

我尝试过的一种有效方法是将X存储在一个数据帧中并洗牌

X = X.reindex(np.random.permutation(X.index))
因为我在尝试时遇到了相同的内存错误

np.random.shuffle(X)
然后,我将pandas数据帧转换回numpy数组,并使用此函数,我可以获得列车测试拆分

#test_proportion of 3 means 1/3 so 33% test and 67% train
def shuffle(matrix, target, test_proportion):
    ratio = int(matrix.shape[0]/test_proportion) #should be int
    X_train = matrix[ratio:,:]
    X_test =  matrix[:ratio,:]
    Y_train = target[ratio:,:]
    Y_test =  target[:ratio,:]
    return X_train, X_test, Y_train, Y_test

X_train, X_test, Y_train, Y_test = shuffle(X, Y, 3)

目前这是可行的,当我想进行k次交叉验证时,我可以迭代循环k次并洗牌pandas数据帧。虽然这就足够了,但为什么numpy和sci kit learn的shuffle和train_test_split实现会导致大型阵列的内存错误?

我的代码也面临同样的问题。我使用的是像你一样的密集数组,内存不足。我将我的培训数据转换为稀疏数据,我正在进行文档分类,并解决了我的问题。

我遇到了类似的问题

正如@user1879926所提到的,我认为洗牌是导致内存耗尽的主要原因

如前所述, 具有禁用洗牌的选项


因此,我认为您可以通过添加shuffle=False选项来避免内存错误。

使用sklearn split方法并减少内存使用的另一种方法是生成X的索引向量并在此向量上拆分。之后,您可以选择条目,例如将培训和测试拆分写入磁盘

import h5py
import numpy as np
from sklearn.cross_validation import train_test_split

X = np.random.random((10000,70000))
Y = np.random.random((10000,))

x_ids = list(range(len(X)))
x_train_ids, x_test_ids, Y_train, Y_test = train_test_split(x_ids, Y, test_size = 0.33, random_state=42)

# Write

f = h5py.File('dataset/train.h5py', 'w')
f.create_dataset(f"inputs", data=X[x_train_ids], dtype=np.int)
f.create_dataset(f"labels", data=Y_train, dtype=np.int)
f.close()

f = h5py.File('dataset/test.h5py', 'w')
f.create_dataset(f"inputs", data=X[x_test_ids], dtype=np.int)
f.create_dataset(f"labels", data=Y_test, dtype=np.int)
f.close()

# Read

f = h5py.File('dataset/train.h5py', 'r')
X_train = np.array(f.get('inputs'), dtype=np.int)
Y_train = np.array(f.get('labels'), dtype=np.int)
f.close()

f = h5py.File('dataset/test.h5py', 'r')
X_test = np.array(f.get('inputs'), dtype=np.int)
Y_test = np.array(f.get('labels'), dtype=np.int)
f.close()

一个10000 x 70000 NumPy浮点数组有700MB的元素,每个元素占用8个字节,所以这个数组使用大约6GB的内存。这实际上是相当大的。我想大小都是相对的——用个人电脑的术语来说,绝对是相当大的。HPC术语,不太多。我问题中的代码片段对你们中的任何一个人有用吗?@user1879926是的。在具有48Gb内存的计算机上。这就是为什么我问你运行的是哪台机器。我的Macbook有16gb的RAM和大约500GB的可用磁盘空间。这可能会引起我的兴趣-在64G机器上工作,在8G笔记本电脑上出现大问题可能会导致内存错误,如果我没有杀死它的话。问题很可能是训练/测试拆分不可避免地会复制数据,因为它使用了奇特的索引,而在没有随机性的情况下,例如KFold,这是可以避免的,但您必须自己编写拆分代码,因为sklearn的KFold也会复制数据。如果你需要随机化,你可以先考虑把数据放在数据库里。如果你的模型可以从一个生成器中分批学习,这个方法对于从SkSeLee中获得分裂也是很有用的,这也与分层有关。您还可以创建指向文件的路径列表,而不是索引列表。在这种情况下,你不需要写作和阅读。这应该是公认的答案!不需要巫术