在磁盘上保存NumPy数组的最佳方法

10 浏览
0 Comments

在磁盘上保存NumPy数组的最佳方法

我正在寻找一种快速保存大型NumPy数组的方法。我希望将它们以二进制格式保存到磁盘上,然后能够相对快速地将它们读回内存中。不幸的是,cPickle的速度不够快。

我找到了numpy.savez和numpy.load。但奇怪的是,numpy.load将npy文件加载到"内存映射"中。这意味着对数组的常规操作速度非常慢。例如,像这样的操作将会非常慢:

import numpy as np
import time
from tempfile import TemporaryFile
n = 10000000
a = np.arange(n)
b = np.arange(n) * 10
c = np.arange(n) * -0.5
file = TemporaryFile()
np.savez(file, a=a, b=b, c=c)
file.seek(0)
t = time.time()
z = np.load(file)
print("loading time =", time.time() - t)
t = time.time()
aa = z['a']
bb = z['b']
cc = z['c']
print("assigning time =", time.time() - t)

更确切地说,第一行会非常快,但是将数组分配给`obj`的剩余行速度非常慢:

loading time = 0.000220775604248
assigning time = 2.72940087318

有没有更好的保存NumPy数组的方法?理想情况下,我希望能够将多个数组存储在一个文件中。

0
0 Comments

最佳的方法是使用hdf5来保存numpy数组。在Python中,有两个处理hdf5的选项:pytables和h5py。它们都被设计成能够高效地处理numpy数组。

对于这个问题的解决方法,可以参考以下代码示例:

import h5py
import numpy as np
# 创建一个hdf5文件并打开
file = h5py.File('data.hdf5', 'w')
# 创建一个numpy数组
array = np.array([[1, 2, 3], [4, 5, 6]])
# 将数组保存到hdf5文件中
file.create_dataset('array', data=array)
# 关闭文件
file.close()

import tables
import numpy as np
# 创建一个hdf5文件并打开
file = tables.open_file('data.hdf5', mode='w')
# 创建一个numpy数组
array = np.array([[1, 2, 3], [4, 5, 6]])
# 创建一个表来保存数组数据
table = file.create_table('/', 'array', obj=array)
# 关闭文件
file.close()

根据我的经验,启用chunk storage和compression后,hdf5的读写性能非常慢。例如,我有两个形状为(2500000, 2000)的2维数组,chunk大小为(10000, 2000)。对于一个形状为(2000, 2000)的数组,单次写入操作需要约1~2秒才能完成。你有什么建议来提高性能吗?

1到2秒对于这样一个大数组来说并不算太长。与.npy格式相比,性能如何?

hdf5在CPU内存消耗方面有问题吗?当hdf5文件很大时,我在多个工作进程的训练中遇到了一些问题。而.npy文件可以使用内存映射来避免这个问题。

0
0 Comments

最佳方法来保存numpy数组到磁盘

在比较了多种numpy数组存储方式的性能(空间和时间)后,发现npz和二进制文件在稀疏数据或结构化数据上的表现比较好,可以节省大量空间但同时会增加加载时间。如果可移植性是一个问题,那么二进制文件比npy更好。如果人类可读性很重要,那么可以使用csv,虽然性能会有所损失,但是它也非常可移植。

关于为什么二进制文件比npy更适合可移植性的问题,是因为任何语言只要知道形状、数据类型以及是行还是列,就可以读取二进制文件。如果只使用Python的话,npy也可以,可能比二进制文件更容易些。

关于HDF5的问题,它确实是一种常见的存储方式,但是在此次比较中没有包含进来。

关于使用png和npy保存相同图像时大小差异很大的问题,可能是由于数据类型不同所导致的。png对于这种类型的数据可能有更好的压缩效果,但是这也不能完全解释154倍的差异。对于实际的图像,我个人认为很难找到比png更好的存储方式(除了有损压缩)。

关于h5py的缺失问题,可能是由于代码在其他格式上出现了问题,或者是jt_dump在几个地方出现了问题。关于hdf5和npy的非官方结果可以在该github仓库的fork中找到。

pickle存在一个缺点,就是它可以执行任意代码,这使得它在保存数据时比其他协议不够安全。

FortUnf是Fortran的一种非格式化二进制格式,具有几十年的历史,但我认为现在使用的用户不多。有关更多详细信息,请参阅该仓库。

PNG支持高达16位的数据,所以我怀疑PNG在转换数据类型时对numpy进行了转换,而NPY则保持了原始格式不变。

0
0 Comments

最佳方法来保留numpy数组在磁盘上的原因是为了在需要时能够有效地保存和读取大量的数据。Numpy是一个用于进行科学计算的Python库,它提供了多维数组对象和一些用于处理这些数组的函数。然而,当处理大型数据集时,将数据保存在内存中可能会变得不可行,因此需要一种方法将numpy数组永久保存在磁盘上。

解决这个问题的一种方法是使用pickle模块,它可以将Python对象序列化为字节流,然后将其保存在磁盘上。然而,pickle的一个缺点是它可能会执行任意的代码,这使得它在安全性方面不如其他保存数据的协议。

另一种解决方案是使用HDF5格式来保存numpy数组。HDF5是一种灵活的数据模型和文件格式,它可以有效地存储和组织大型数据集。在上述代码中,使用了hickle模块来实现基于HDF5的pickle克隆。通过使用hickle.dump()函数将数据保存在HDF5文件中,然后使用hickle.load()函数从文件中加载数据,我们可以实现对numpy数组的长期保存和读取。

此外,还可以直接将数据pickle到压缩存档中。在上述代码中,使用了gzip、lzma和bz2模块来实现将数据pickle到压缩存档中。通过使用pickle.dump()函数将数据pickle到gzip.open()、lzma.open()和bz2.open()文件对象中,我们可以将数据保存为压缩文件,以节省存储空间。

总之,为了有效地保存和读取numpy数组,我们可以使用pickle、HDF5或压缩存档等方法。这些方法都有各自的优点和用途,可以根据具体需求选择最合适的方法。

0