使用 Python 和 NumPy 的超大矩阵
- 2025-01-14 08:50:00
- admin 原创
- 149
问题描述:
NumPy是一个非常有用的库,通过使用它,我发现它能够轻松处理相当大的矩阵(10000 x 10000),但处理任何更大的矩阵时就会变得困难(尝试创建 50000 x 50000 的矩阵会失败)。显然,这是因为需要大量内存。
有没有办法以某种方式在 NumPy 中本地创建巨大的矩阵(比如 100 万乘以 100 万)(无需几 TB 的 RAM)?
解决方案 1:
PyTables 和 NumPy 是可行的方法。
PyTables 将以 HDF 格式将数据存储在磁盘上,并可选择压缩。我的数据集通常压缩 10 倍,这在处理数千万或数亿行时非常方便。它的速度也非常快;我 5 年前的笔记本电脑可以以每秒 1,000,000 行的速度执行类似 SQL 的 GROUP BY 聚合来处理数据。对于基于 Python 的解决方案来说,这还不错!
再次以 NumPy recarray 的形式访问数据非常简单:
data = table[row_from:row_to]
HDF 库负责读取相关数据块并转换为 NumPy。
解决方案 2:
numpy.array
s 应该存在于内存中。如果你想处理大于 RAM 的矩阵,你必须解决这个问题。至少有两种方法可以遵循:
尝试一种更高效的矩阵表示,利用矩阵具有的任何特殊结构。例如,正如其他人已经指出的那样,对于稀疏矩阵(具有大量零的矩阵),存在高效的数据结构,例如
scipy.sparse.csc_matrix
。修改算法以在子矩阵上工作。您可以从磁盘中只读取当前正在计算的矩阵块。设计用于集群的算法通常以块为单位工作,因为数据分散在不同的计算机上,并且只在需要时传递。例如,用于矩阵乘法的 Fox 算法(PDF 文件)。
解决方案 3:
您应该能够使用 numpy.memmap 将文件映射到磁盘上。使用较新的 Python 和 64 位计算机,您应该拥有必要的地址空间,而无需将所有内容加载到内存中。操作系统应该只处理将文件的一部分保留在内存中。
解决方案 4:
要处理稀疏矩阵,您需要scipy
位于顶层的包numpy
——请参阅此处了解有关稀疏矩阵选项的更多详细信息scipy
。
解决方案 5:
Stefano Borini 的帖子让我开始了解这类事情已经进展到什么程度。
就是这样。 它似乎基本上可以满足您的要求。HDF5 将允许您存储非常大的数据集,然后以与 NumPy 相同的方式访问和使用它们。
解决方案 6:
确保您使用的是 64 位操作系统和 64 位版本的 Python/NumPy。请注意,在 32 位架构上,您通常可以寻址 3GB 内存(大约 1GB 会因内存映射 I/O 等而丢失)。
对于 64 位系统,如果数组大于可用 RAM,您可以使用虚拟内存,但如果必须进行交换,速度会变慢。此外,内存映射(请参阅 numpy.memmap)是一种处理磁盘上的大文件而不将其加载到内存中的方法,但同样,您需要有 64 位地址空间才能使用这种方法。PyTables 也会为您完成大部分工作。
解决方案 7:
有时,一个简单的解决方案是使用自定义类型作为矩阵项。根据您需要的数字范围,您可以dtype
为您的项目使用手动且特别小的类型。由于 Numpy 默认考虑对象的最大类型,因此这在许多情况下可能是一个有用的想法。以下是一个例子:
In [70]: a = np.arange(5)
In [71]: a[0].dtype
Out[71]: dtype('int64')
In [72]: a.nbytes
Out[72]: 40
In [73]: a = np.arange(0, 2, 0.5)
In [74]: a[0].dtype
Out[74]: dtype('float64')
In [75]: a.nbytes
Out[75]: 32
并使用自定义类型:
In [80]: a = np.arange(5, dtype=np.int8)
In [81]: a.nbytes
Out[81]: 5
In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16)
In [78]: a.nbytes
Out[78]: 8
解决方案 8:
你是在问如何在没有 TB 级 RAM 的情况下处理 2,500,000,000 个元素的矩阵吗?
在没有 80 亿字节 RAM 的情况下处理 20 亿个项目的方法是不将矩阵保存在内存中。
这意味着需要使用更加复杂的算法来从文件系统中分块获取数据。
解决方案 9:
据我了解,关于 numpy 的情况,不是,但我可能是错的。
我可以向您推荐这个替代解决方案:将矩阵写入磁盘并分块访问。我建议您使用 HDF5 文件格式。如果您需要透明格式,您可以重新实现 ndarray 接口以将磁盘存储的矩阵分页到内存中。如果您修改数据以将它们同步回磁盘,请小心。
解决方案 10:
十五年后,但也许这对某些人有用。有 zarr 库,但它仍处于早期开发阶段,我没有使用它的经验:
https://zarr.readthedocs.io/en/stable/index.html
根据文档,它正是为保存较大的 numpy 块而创建的。