将大型numpy数组分割为训练和测试的高效内存方法



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

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

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)

我尝试过的一种有效的方法是将X存储在pandas数据框中并shuffle

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_testrongplit的实现会导致大数组的内存错误呢?

使用sklearn拆分方法减少内存使用的另一种方法是生成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()

我也遇到过类似的问题。

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

And,as 'Shuffle'被声明为model_selection的无效参数。train_testrongplit引用,Train_testrongplit在sklearn 0.19中有禁用shuffle的选项。

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

我的代码遇到了同样的问题。我像你一样使用密集数组,然后内存耗尽了。我将我的训练数据转换为稀疏(我正在做文档分类)并解决了我的问题。

我认为更"内存高效"的方法是迭代地选择用于训练和测试的实例(尽管,正如计算机科学中典型的那样,您牺牲了使用矩阵固有的效率)。

你可以做的是遍历数组,对于每个实例,"抛硬币"(使用随机包)来决定你是将实例用作训练还是测试,并根据具体情况将实例存储在适当的numpy数组中。

这个迭代方法只适用于10000个实例。奇怪的是,10000 X 70000并不是那么大;你用的是什么类型的机器?这让我怀疑这是Python/numpy/scikit问题还是机器问题…

不管怎样,希望这对你有帮助!

最新更新