内存错误:numpy.genfromtxt()

3
我有一个50,000x5,000的矩阵(float)文件。当使用x = np.genfromtxt(readFrom, dtype=float)将文件加载到内存中时,我会收到以下错误消息:

文件"C:\Python27\lib\site-packages\numpy\lib\npyio.py"第1583行, in genfromtxt for (i, converter) in enumerate(converters)])
MemoryError

我想将整个文件加载到内存中,因为我正在使用Scipy计算每个向量之间的欧几里得距离。dis = scipy.spatial.distance.euclidean(x[row1], x[row2]) 有没有一种有效的方法将巨大的矩阵文件加载到内存中?
谢谢。
更新: 我设法解决了这个问题。以下是我的解决方案。我不确定它是否高效或逻辑上正确,但对我来说可以正常工作:
x = open(readFrom, 'r').readlines()
y = np.asarray([np.array(s.split()).astype('float32') for s in x], dtype=np.float32)
....
dis = scipy.spatial.distance.euclidean(y[row1], y[row2])

请帮助我改进我的解决方案。


1
计算所有向量对之间的距离所需时间远远超过加载文件的时间。请重新检查是否真的需要所有向量对。此外,您将需要至少 25 * 10^7 * 4 = 10^9 字节,可能是 2*10^9 字节 -- 后者在 32 位系统上是不可行的。 - krlmlr
请查看https://dev59.com/-HI-5IYBdhLWcg3wW2-p。 - bmu
2个回答

1

实际上,你正在使用8字节浮点数,因为Python的float对应于C的double(至少在大多数系统上):

a=np.arange(10,dtype=float)
print(a.dtype)  #np.float64

你应该将数据类型指定为np.float32。根据你的操作系统,以及它是32位还是64位(以及你是否使用32位Python还是64位Python),numpy可用的地址空间可能比你的4GB要小,这也可能会成为一个问题。


即使我使用 dtype=np.float32,仍会出现内存错误。 - Maggie
@Mahin 如果你只是这样做会发生什么:>>> a=np.zeros((50000,5000),dtype=np.float32); a=1,而不是使用你的 np.genfromtxt - mgilson
1
@Mahin -- 我的numpy版本太老,不支持genfromtxt,但是查看源代码中的loadtxt(如果没有缺失值,则等效),然而,numpy将值读入列表中(至少为4*N*sizeof(pointer)*N字节长)。然后(我认为)在构建numpy数组时再次复制数据,因为ndarrays在内存中是连续的。我建议你自己迭代文件并打包值(在使用np.zeros分配内存之后)。由于你知道数组的大小,所以这应该相对容易实现。 - mgilson

1

根据您的操作系统和Python版本,很可能您永远无法分配1GB数组(mgilson的答案在这里非常准确)。问题不是您的内存不足,而是您的内存不足连续。如果您使用32位机器(特别是运行Windows),增加内存将没有帮助。转移到64位架构可能会有所帮助。

使用较小的数据类型肯定可以帮助;根据您使用的操作,16位浮点数甚至8位整数可能已经足够。

如果所有这些都不起作用,那么您不得不承认数据只是不适合内存。您将不得不逐个处理它(在这种情况下,将数据存储为HDF5数组可能非常有用)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接