人工智能之数据分析 numpy

第十二章 数据持久化


前言

NumPy 提供了多种数据持久化(Persistence) 方式,用于高效地保存和加载数组数据。根据数据规模、结构复杂度、跨平台需求等不同场景,可选择不同的方法。

本文系统讲解:

  • 基础二进制/文本保存(.npy, .npz, .txt
  • 结构化数组(Structured Arrays)记录数组(Record Arrays)
  • 内存映射(Memory Mapping) —— 处理超大文件
  • 其他读写方式(如 HDF5、Pickle 等)

一、基础数据持久化

1. np.save() / np.load() —— 单个数组(推荐)

保存为 .npy 格式(NumPy 专用二进制格式),​保留 dtype、形状、字节序​。

import numpy as np

# 保存
arr = np.array([1, 2, 3, 4])
np.save('data.npy', arr)

# 加载
loaded = np.load('data.npy')
print(loaded)  # [1 2 3 4]

✅ 优点:

  • 高效(C 语言级 I/O)
  • 支持任意维度和 dtype
  • 元数据完整保留

2. np.savez() / np.savez_compressed() —— 多个数组

保存多个数组到一个 .npz 文件(ZIP 格式)。

a = np.array([1, 2, 3])
b = np.array([[4, 5], [6, 7]])

# 无压缩
np.savez('arrays.npz', a=a, b=b)

# 有压缩(节省空间)
np.savez_compressed('arrays_compressed.npz', a=a, b=b)

# 加载
data = np.load('arrays.npz')
print(data['a'])  # [1 2 3]
print(data['b'])  # [[4 5] [6 7]]
data.close()  # 显式关闭(或用 with)

💡 .npz 文件本质是 ZIP,可用解压软件打开查看内容。


3. 文本格式:np.savetxt() / np.loadtxt()

适用于小规模、人类可读的数据(如 CSV 风格)。

arr = np.array([[1.1, 2.2], [3.3, 4.4]])

# 保存为文本
np.savetxt('data.txt', arr, delimiter=',', fmt='%.2f')

# 加载
loaded = np.loadtxt('data.txt', delimiter=',')

⚠️ 缺点:

  • 只支持 1D/2D 数组
  • 浮点精度可能丢失
  • 速度慢、文件大

二、结构化数组(Structured Arrays)

当数据包含​异构字段​(如姓名、年龄、成绩),可使用结构化数组。

1. 定义 dtype

# 定义结构化 dtype
dt = np.dtype([
    ('name', 'U10'),      # Unicode 字符串,最长10字符
    ('age', 'i4'),        # 32位整数
    ('score', 'f4')       # 32位浮点
])

# 创建数组
students = np.array([
    ('Alice', 20, 85.5),
    ('Bob', 22, 90.0)
], dtype=dt)

print(students['name'])   # ['Alice' 'Bob']
print(students[0])        # ('Alice', 20, 85.5)

2. 持久化结构化数组

# 保存
np.save('students.npy', students)

# 加载
loaded_students = np.load('students.npy')
print(loaded_students.dtype)  # 与原 dtype 一致

✅ 结构化数组可直接用 .npy 保存,​完全保留字段信息​。


三、记录数组(Record Arrays)—— 结构化数组的子类

提供​属性访问语法​(arr.name 而非 arr['name'])。

# 从结构化数组创建
rec_arr = np.rec.array(students)

# 或直接创建
rec_arr2 = np.rec.array([
    ('Charlie', 21, 88.0),
    ('Diana', 19, 92.5)
], dtype=dt)

print(rec_arr.name)   # ['Alice' 'Bob'] ← 属性访问!
print(rec_arr.age)    # [20 22]

⚠️ 注意:np.rec.arraynp.ndarray 的子类,​不推荐在新代码中使用​(官方文档建议优先用结构化数组 + 字典式访问)。

但记录数组同样支持 np.save() / np.load()


四、内存映射(Memory Mapping)—— 处理超大数组

当数组​大于内存​(如几十 GB 的科学数据),可使用 np.memmap 实现​按需加载​。

原理:

  • 文件存储在磁盘
  • NumPy 通过虚拟内存机制“映射”到数组
  • 访问时自动从磁盘读取对应块,无需一次性加载

示例:

# 创建一个 10GB 的 float32 数组(仅占磁盘,不占内存)
filename = 'big_array.dat'
shape = (1000000, 2500)  # ~10^10 元素 × 4 bytes ≈ 37.25 GB

# 创建 memmap(mode='w+' 表示可读写)
big_arr = np.memmap(filename, dtype='float32', mode='w+', shape=shape)

# 初始化(可选)
big_arr[:] = 0.0  # 实际只写入磁盘,内存占用极小

# 使用(像普通数组一样)
big_arr[0, :10] = np.arange(10)

# 刷新到磁盘(重要!)
big_arr.flush()

# 之后可重新加载
loaded = np.memmap(filename, dtype='float32', mode='r', shape=shape)
print(loaded[0, :10])  # [0. 1. 2. ... 9.]

模式说明:

mode 说明
'r' 只读
'r+' 读写(文件必须存在)
'w+' 读写(覆盖或新建)
'c' 复制写(修改不影响原文件)

✅ 适用场景:

  • 卫星遥感图像
  • 基因组数据
  • 物理模拟快照
  • 大型嵌入向量矩阵

五、其他常用读写方式

1. Pickle(Python 通用序列化)

import pickle

with open('data.pkl', 'wb') as f:
    pickle.dump(arr, f)

with open('data.pkl', 'rb') as f:
    loaded = pickle.load(f)

⚠️ 缺点:

  • 不跨语言
  • 安全风险(反序列化攻击)
  • .npy 慢且文件更大

✅ 仅建议用于保存包含 NumPy 数组的​复杂 Python 对象​(如 dict、class 实例)。


2. HDF5(推荐用于大型科学数据)

通过 h5py 库支持:

import h5py

# 写入
with h5py.File('data.h5', 'w') as f:
    f.create_dataset('my_array', data=arr)
    f.create_dataset('students', data=students)  # 也支持结构化数组

# 读取
with h5py.File('data.h5', 'r') as f:
    arr_h5 = f['my_array'][:]      # 加载全部
    partial = f['my_array'][0:10]  # 只加载前10行(支持切片!)

✅ HDF5 优势:

  • 支持超大文件(TB 级)
  • 分层数据组织(类似文件夹)
  • 压缩(gzip, lzf)
  • 跨平台、跨语言(C/Fortran/Python/Matlab)
  • 支持部分读取(类似 memmap)

🔧 安装:pip install h5py


3. Parquet / Feather(表格数据,配合 Pandas)

若数据是表格形式(类似 DataFrame),可先转为 Pandas 再保存:

import pandas as pd

df = pd.DataFrame(students)  # 结构化数组 → DataFrame
df.to_parquet('data.parquet')  # 列式存储,高效压缩
df_loaded = pd.read_parquet('data.parquet')

六、选择建议:按场景选格式

场景 推荐格式 理由
单个数组,快速保存/加载 .npy 最快、最简单
多个数组 .npz 一个文件打包
人类可读、小数据 .txt/.csv 兼容 Excel
异构字段(姓名/年龄等) 结构化数组 +.npy 保留字段语义
超大数组(> 内存) np.memmapHDF5 按需加载
科学数据共享 HDF5 跨平台、压缩、元数据
与 Pandas 交互 Parquet / HDF5 生态兼容

七、注意事项

  1. 路径与编码​:
    • 在 Windows 上注意路径分隔符(推荐用 pathlib
    • 文本文件注意 encoding='utf-8'
  2. 版本兼容性​:
    • .npy 格式随 NumPy 版本演进,但向后兼容良好
  3. 内存映射生命周期​:
    • memmap 对象应保持引用,避免过早释放
    • 修改后务必调用 .flush()
  4. 结构化数组字符串长度​:
    • 'U10' 表示最多 10 个 Unicode 字符,​不足会截断​!

掌握这些持久化技术,我们可以灵活应对从 KB 到 TB 级别的数据存储需求。NumPy 的设计哲学是:​小数据用 .npy,大数据用 memmapHDF5,结构化数据用自定义 dtype​。

后续

本文主要讲述了numpy数据持久化。python过渡项目部分代码已经上传至gitee,后续会逐步更新,主要受时间原因限制,当然自己也可以克隆到本地学习拓展。

资料关注

公众号:咚咚王
gitee:https://gitee.com/wy18585051844/ai_learning

《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》

 posted on 2025-11-23 19:41  咚咚王者  阅读(0)  评论(0)    收藏  举报