使用memmap文件进行批处理



我有一个庞大的数据集,我希望对其进行PCA。我受限于RAM和PCA的计算效率。因此,我转而使用迭代PCA。

数据集大小(140000、3504)

文档说明This algorithm has constant memory complexity, on the order of batch_size, enabling use of np.memmap files without loading the entire file into memory.

这真的很好,但不确定如何利用它。

我试着加载一个memmap,希望它能在块中访问它,但我的RAM吹了。我下面的代码最终使用了大量的内存:

ut = np.memmap('my_array.mmap', dtype=np.float16, mode='w+', shape=(140000,3504))
clf=IncrementalPCA(copy=False)
X_train=clf.fit_transform(ut)

当我说"my RAM blow"时,我看到的Traceback是:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:Python27libsite-packagessklearnbase.py", line 433, in fit_transfo
rm
    return self.fit(X, **fit_params).transform(X)
  File "C:Python27libsite-packagessklearndecompositionincremental_pca.py",
 line 171, in fit
    X = check_array(X, dtype=np.float)
  File "C:Python27libsite-packagessklearnutilsvalidation.py", line 347, in
 check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
MemoryError

我如何通过减少批大小来改善这一点而不影响准确性?


My ideas to diagnosis:

我看了sklearn源代码,在fit()函数源代码中,我可以看到以下内容。这对我来说是有意义的,但我仍然不确定我的情况是什么问题。

for batch in gen_batches(n_samples, self.batch_size_):
        self.partial_fit(X[batch])
return self
编辑:

最坏的情况是,我将不得不为iterativePCA编写自己的代码,该代码通过读取和关闭.npy文件进行批处理。但这将破坏利用已经存在的黑客的目的。

Edit2: 如果我能删除一批处理过的memmap file。这很有意义。

Edit3: 理想情况下,如果IncrementalPCA.fit()只是使用批处理,它应该不会使我的RAM崩溃。张贴整个代码,只是为了确保我没有在之前将memmap完全刷新到磁盘时犯错误。

temp_train_data=X_train[1000:]
temp_labels=y[1000:] 
out = np.empty((200001, 3504), np.int64)
for index,row in enumerate(temp_train_data):
    actual_index=index+1000
    data=X_train[actual_index-1000:actual_index+1].ravel()
    __,cd_i=pywt.dwt(data,'haar')
    out[index] = cd_i
out.flush()
pca_obj=IncrementalPCA()
clf = pca_obj.fit(out)

令人惊讶的是,我注意到out.flush并没有释放我的内存。是否有一种方法可以使用del out来完全释放我的内存,然后有人将文件的指针传递给IncrementalPCA.fit() .

您在32位环境中遇到sklearn问题。我假设你正在使用np.float16,因为你在一个32位的环境中,你需要允许你创建memmap对象而没有numpy thowing错误。

在64位环境中(在Windows上使用Python3.3 64位进行测试),您的代码可以开箱即用。所以,如果你有一台64位的计算机,安装64位的python和64位的numpy, scipy, scikit-learn,你就可以开始了。

不幸的是,如果您不能做到这一点,就没有简单的修复方法。我在github上提出了一个问题,但它不容易修补。最根本的问题是,在库中,如果类型是float16,就会触发数组到内存的一个副本。详情如下:

所以,我希望您可以访问具有大量RAM的64位环境。如果没有,您将不得不自己拆分数组并批处理它,这是一个相当大的任务…

N。B 看到您去源代码诊断您的问题真是太好了:)但是,如果您查看代码失败的行(来自Traceback),您将看到您发现的for batch in gen_batches代码从未到达。


详细诊断:

OP代码产生的实际错误:

import numpy as np
from sklearn.decomposition import IncrementalPCA
ut = np.memmap('my_array.mmap', dtype=np.float16, mode='w+', shape=(140000,3504))
clf=IncrementalPCA(copy=False)
X_train=clf.fit_transform(ut)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:Python27libsite-packagessklearnbase.py", line 433, in fit_transfo
rm
    return self.fit(X, **fit_params).transform(X)
  File "C:Python27libsite-packagessklearndecompositionincremental_pca.py",
 line 171, in fit
    X = check_array(X, dtype=np.float)
  File "C:Python27libsite-packagessklearnutilsvalidation.py", line 347, in
 check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
MemoryError

调用check_array(代码链接)使用dtype=np.float,但原始数组使用dtype=np.float16。即使check_array()函数默认为copy=False并将其传递给np.array(),它也会被忽略(根据文档),以满足dtype不同的要求;因此,np.array制作了一个副本。

这可以在IncrementalPCA代码中解决,通过确保dtype in (np.float16, np.float32, np.float64)的数组保留dtype。然而,当我尝试这个补丁时,它只是将MemoryError推到了执行链的更远的地方。

同样的复制问题发生在代码从主scipy代码调用linalg.svd()时,这次错误发生在调用gesdd()(来自lapack的包装本机函数)期间。因此,我不认为有一种方法来修补这个(至少不是一个简单的方法-它是在核心代码的最小修改)。

是否单独触发崩溃?

X_train_mmap = np.memmap('my_array.mmap', dtype=np.float16,
                         mode='w+', shape=(n_samples, n_features))
clf = IncrementalPCA(n_components=50).fit(X_train_mmap)

如果没有,那么您可以使用该模型将(迭代地投影您的数据)转换为使用批处理的较小数据:

X_projected_mmap = np.memmap('my_result_array.mmap', dtype=np.float16,
                             mode='w+', shape=(n_samples, clf.n_components))
for batch in gen_batches(n_samples, self.batch_size_):
    X_batch_projected = clf.transform(X_train_mmap[batch])
    X_projected_mmap[batch] = X_batch_projected

我还没有测试过这段代码,但我希望你能明白。

相关内容

  • 没有找到相关文章