在 python 中保存 `.npz` 文件而不是 `.npy` 在速度、内存和查找方面有什么优势?

What is the advantage of saving `.npz` files instead of `.npy` in python, regarding speed, memory and look-up?

保存 .npz 文件的 numpy.savez 的 python 文档是:

The .npz file format is a zipped archive of files named after the variables they contain. The archive is not compressed and each file in the archive contains one variable in .npy format. [...]

When opening the saved .npz file with load a NpzFile object is returned. This is a dictionary-like object which can be queried for its list of arrays (with the .files attribute), and for the arrays themselves.

我的问题是:numpy.savez有什么意义?

它只是一个更优雅的版本(更短的命令)来保存多个数组,还是在 saving/reading 过程中有加速?是不是占用内存少?

主要优点是数组是延迟加载的。也就是说,如果您有一个包含 100 个数组的 npz 文件,您可以在不实际加载任何数据的情况下加载该文件。如果您请求单个数组,则只加载该数组的数据。

npz 文件的一个缺点是它们不能进行内存映射(使用 load(<file>, mmap_mode='r')),因此对于大型数组,它们可能不是最佳选择。对于数组具有共同形状的数据,我建议看一下 structured arrays。这些可以是内存映射的,允许使用类似 dict 的语法访问数据(即 arr['field']),并且在内存方面非常有效。

回答你的问题有两部分解释。

我。 NPY 与 NPZ

正如我们已经从文档中读到的,.npy 格式是:

the standard binary file format in NumPy for persisting a single arbitrary NumPy array on disk. ... The format is designed to be as simple as possible while achieving its limited goals. (sources)

.npz只是一个

simple way to combine multiple arrays into a single file, one can use ZipFile to contain multiple “.npy” files. We recommend using the file extension “.npz” for these archives. (sources)

因此,.npz 只是一个包含多个“.npy”文件的 ZipFile。这个 ZipFile 可以 压缩(使用 np.savez_compressed)或解压缩(使用 np.savez.

类似于类Unix系统中的tarball archive file,一个tarball文件可以是一个包含其他文件的未压缩归档文件,也可以是结合各种压缩程序的压缩归档文件(gzip, bzip2, 等等)

二.用于二进制序列化的不同 API

并且 Numpy 还提供 different APIs 来生成这些二进制文件输出:

  • np.save ---> 将数组保存为 NumPy .npy 格式的二进制文件
  • np.savez --> 以未压缩 .npz 格式
  • 将多个数组保存到一个文件中
  • np.savez_compressed --> 以压缩 .npz 格式
  • 将多个数组保存到一个文件中
  • np.load --> 从 .npy.npz 或 pickled 文件
  • 加载数组或 pickled 对象

如果我们浏览 Numpy 的源代码,under the hood:

def _savez(file, args, kwds, compress, allow_pickle=True, pickle_kwargs=None):
    ...
    if compress:
        compression = zipfile.ZIP_DEFLATED
    else:
        compression = zipfile.ZIP_STORED
    ...


def savez(file, *args, **kwds):
    _savez(file, args, kwds, False)


def savez_compressed(file, *args, **kwds):
    _savez(file, args, kwds, True)

然后回到问题:

  • 如果只使用np.save,在.npy格式之上没有更多的压缩,只有一个归档文件,方便管理多个相关文件。
  • 如果使用 np.savez_compressed,那么磁盘上的内存当然会减少,因为有更多 CPU 时间来完成压缩工作(即有点慢)。