Python数据存储必备:Numpy Save功能解读 – wiki基地

Python 数据存储必备:Numpy Save 功能解读

在 Python 数据科学领域,NumPy 库扮演着举足轻重的角色。它不仅提供了强大的 N 维数组对象(ndarray),还具备高效的数值计算功能。然而,在数据处理流程中,将数据持久化存储到磁盘,并在需要时重新加载同样至关重要。NumPy 提供的 savesavezsavez_compressed 函数正是解决这一问题的利器。本文将深入探讨这些函数的功能、用法、应用场景,以及它们之间的区别与联系,帮助你全面掌握 NumPy 数据存储的精髓。

1. 数据持久化的重要性

在数据分析和机器学习项目中,我们经常需要处理大量的数据。这些数据可能来源于各种渠道,如传感器采集、网络爬虫、数据库查询等。在数据处理的各个阶段,我们通常会进行数据清洗、转换、特征提取、模型训练等操作。如果每次运行程序都重新执行这些步骤,不仅耗时耗力,而且可能因为数据源的变化导致结果不一致。

因此,将中间结果或最终结果保存到磁盘,形成一种持久化的存储机制,具有以下显著优势:

  • 节省计算资源: 避免重复执行耗时的计算过程,直接加载已保存的数据,大幅提高效率。
  • 保证结果一致性: 确保每次运行程序时使用相同的数据,避免因数据源变化导致的结果差异。
  • 便于数据共享: 将处理好的数据保存为文件,方便团队成员之间共享和协作。
  • 支持离线分析: 无需连接数据源,即可加载已保存的数据进行离线分析和建模。
  • 实现模型持久化: 将训练好的机器学习模型保存到磁盘,方便后续部署和应用。

2. NumPy save 函数:保存单个数组

numpy.save 函数用于将单个 NumPy 数组保存为 .npy 格式的二进制文件。这是一种 NumPy 特有的文件格式,能够完整地保存数组的数据、形状(shape)和数据类型(dtype)等信息。

2.1 基本语法

python
numpy.save(file, arr, allow_pickle=True, fix_imports=True)

  • file 文件名或文件对象。如果传入的是文件名,则会自动添加 .npy 扩展名(如果文件名中没有该扩展名)。
  • arr 要保存的 NumPy 数组。
  • allow_pickle 是否允许使用 Python pickle 模块。默认为 True。当数组包含对象数据类型(object dtype)时,必须使用 pickle 来序列化对象。但 pickle 存在安全风险,如果数据来源不可信,建议设置为 False
  • fix_imports 仅在 Python 2 中有用,用于尝试兼容 Python 2 和 Python 3 的 pickle 格式。一般情况下保持默认值 True 即可。

2.2 使用示例

“`python
import numpy as np

创建一个示例数组

data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

将数组保存到文件

np.save(‘my_array.npy’, data)

从文件加载数组

loaded_data = np.load(‘my_array.npy’)

验证加载的数据是否与原始数据一致

print(np.array_equal(data, loaded_data)) # 输出:True
“`

2.3 注意事项

  • .npy 文件是二进制文件,无法直接用文本编辑器打开查看。
  • .npy 文件格式是 NumPy 特有的,其他软件可能无法直接读取。
  • 如果数组包含对象数据类型,且 allow_pickle=False,则 save 函数会抛出异常。

3. NumPy savez 函数:保存多个数组

numpy.savez 函数用于将多个 NumPy 数组保存到一个 .npz 格式的压缩文件中。.npz 文件实际上是一个 zip 压缩包,其中包含了多个 .npy 文件,每个 .npy 文件对应一个数组。

3.1 基本语法

python
numpy.savez(file, *args, **kwds)

  • file 文件名或文件对象。如果传入的是文件名,则会自动添加 .npz 扩展名(如果文件名中没有该扩展名)。
  • *args 要保存的 NumPy 数组,可以传入任意多个数组。
  • **kwds 以关键字参数的形式指定数组名称和对应的数组。如果不指定数组名称,则默认使用 arr_0arr_1arr_2 等作为名称。

3.2 使用示例

“`python
import numpy as np

创建多个示例数组

array1 = np.array([1, 2, 3])
array2 = np.array([[4, 5], [6, 7]])
array3 = np.array([‘a’, ‘b’, ‘c’])

将多个数组保存到文件,使用位置参数

np.savez(‘multiple_arrays.npz’, array1, array2, array3)

将多个数组保存到文件,使用关键字参数

np.savez(‘named_arrays.npz’, a=array1, b=array2, c=array3)

从文件加载数组

data1 = np.load(‘multiple_arrays.npz’)
data2 = np.load(‘named_arrays.npz’)

通过数组名称访问数据

print(data1[‘arr_0’]) # 输出:[1 2 3]
print(data2[‘b’]) # 输出:[[4 5] [6 7]]

获取所有数组名称

print(data1.files) # 输出:[‘arr_0’, ‘arr_1’, ‘arr_2’]
print(data2.files) # 输出: [‘a’, ‘b’, ‘c’]
“`

3.3 注意事项

  • .npz 文件是 zip 压缩文件,可以用解压缩软件打开查看。
  • .npz 文件中的每个 .npy 文件仍然是 NumPy 特有的二进制文件。
  • savez 函数默认使用 ZIP_STORED 存储方法,即不进行压缩。如果需要压缩,可以使用 savez_compressed 函数。

4. NumPy savez_compressed 函数:保存多个数组(压缩)

numpy.savez_compressed 函数与 savez 函数类似,都可以将多个 NumPy 数组保存到一个文件中。区别在于 savez_compressed 函数使用 ZIP_DEFLATED 存储方法,对数据进行压缩,可以减小文件大小。

4.1 基本语法

python
numpy.savez_compressed(file, *args, **kwds)

  • file 文件名或文件对象。如果传入的是文件名,则会自动添加 .npz 扩展名(如果文件名中没有该扩展名)。
  • *args 要保存的 NumPy 数组,可以传入任意多个数组。
  • **kwds 以关键字参数的形式指定数组名称和对应的数组。如果不指定数组名称,则默认使用 arr_0arr_1arr_2 等作为名称。

4.2 使用示例

“`python
import numpy as np

创建多个示例数组

array1 = np.random.rand(1000, 1000)
array2 = np.random.rand(500, 500)

使用 savez 保存

np.savez(‘uncompressed.npz’, array1, array2)

使用 savez_compressed 保存

np.savez_compressed(‘compressed.npz’, array1, array2)

比较文件大小(compressed.npz 通常比 uncompressed.npz 小)

import os
print(f”Uncompressed size: {os.path.getsize(‘uncompressed.npz’)} bytes”)
print(f”Compressed size: {os.path.getsize(‘compressed.npz’)} bytes”)

从文件加载数组(与 savez 相同)

data = np.load(‘compressed.npz’)
print(data[‘arr_0’].shape) # 输出:(1000, 1000)
“`

4.3 注意事项

  • savez_compressed 函数生成的 .npz 文件仍然是 zip 压缩文件,可以用解压缩软件打开查看。
  • 压缩可以减小文件大小,但会增加保存和加载的时间。
  • 对于某些类型的数据(如已经压缩过的图像数据),压缩效果可能不明显。

5. savesavezsavez_compressed 的比较

特性 save savez savez_compressed
保存数组数量 单个 多个 多个
文件格式 .npy .npz .npz
压缩 无(默认)
文件大小 较大 较大(默认) 较小
保存/加载速度 较快 较快(默认) 较慢
适用场景 保存单个数组 保存多个数组 保存多个大型数组

6. 应用场景

  • 中间结果缓存: 在数据处理流程中,将耗时操作的中间结果保存到磁盘,避免重复计算。例如,在图像处理中,可以将特征提取的结果保存下来,后续直接加载使用。
  • 模型参数保存: 将训练好的机器学习模型的参数保存到磁盘,方便后续部署和应用。例如,可以将深度学习模型的权重和偏置保存下来,然后在其他程序中加载使用。
  • 数据集存储: 将大型数据集分割成多个小文件,分别保存到磁盘,方便管理和加载。例如,可以将图像数据集的每个类别保存为一个单独的文件。
  • 数据共享与协作: 将处理好的数据保存为文件,方便团队成员之间共享和协作。例如,可以将清洗后的数据保存为 .npz 文件,供其他成员进行后续分析。
  • 实验结果记录: 将不同实验条件下的结果保存到不同的文件中,方便比较和分析。例如,可以将不同参数设置下的模型性能指标保存到不同的文件中。

7. 进阶技巧

7.1 使用内存映射(memmap

对于超大型数组,如果一次性加载到内存可能会导致内存溢出。NumPy 提供了 memmap 功能,可以将数组存储在磁盘上,并像访问内存中的数组一样访问它,而无需一次性加载整个数组。

“`python
import numpy as np

创建一个大型数组并保存到文件

data = np.random.rand(10000, 10000)
fp = np.memmap(‘my_large_array.dat’, dtype=’float64′, mode=’w+’, shape=(10000, 10000))
fp[:] = data[:]
del fp # 关闭文件并确保数据写入磁盘

使用 memmap 加载数组

newfp = np.memmap(‘my_large_array.dat’, dtype=’float64′, mode=’r’, shape=(10000, 10000))

访问部分数据(不会一次性加载整个数组)

print(newfp[0, :10])

修改部分数据(会直接写入磁盘)

newfp[0, :10] = 0
“`

7.2 使用 pathlib 库管理文件路径

pathlib 是 Python 标准库中用于处理文件路径的模块,它提供了更加面向对象和易用的 API。

“`python
from pathlib import Path
import numpy as np

创建一个 Path 对象

file_path = Path(‘my_data’) / ‘my_array.npy’

创建目录(如果不存在)

file_path.parent.mkdir(parents=True, exist_ok=True)

保存数组

data = np.array([1, 2, 3])
np.save(file_path, data)

加载数组

loaded_data = np.load(file_path)

检查文件是否存在

print(file_path.exists())

获取文件名

print(file_path.name)
“`

7.3 使用 HDF5 或 Zarr 存储更复杂的数据结构

对于更复杂的数据结构,如多维数组、表格数据、元数据等,可以考虑使用 HDF5 或 Zarr 等更高级的数据存储格式。这些格式提供了更强大的功能,如数据压缩、分块存储、并行读写等。

  • HDF5: 一种广泛使用的科学数据存储格式,支持多种数据类型和压缩算法。可以使用 h5py 库在 Python 中操作 HDF5 文件。
  • Zarr: 一种新兴的数据存储格式,专为并行计算和云存储设计。可以使用 zarr 库在 Python 中操作 Zarr 文件。

8. 总结

NumPy 的 savesavezsavez_compressed 函数为 Python 数据持久化提供了便捷高效的解决方案。通过这些函数,我们可以轻松地将 NumPy 数组保存到磁盘,并在需要时快速加载,从而节省计算资源、保证结果一致性、方便数据共享和协作。结合 memmappathlib 以及 HDF5、Zarr 等进阶技巧,我们可以更加灵活地处理各种数据存储需求,为数据科学项目保驾护航。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部