人工智能之數據分析 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)

⚠️ 缺點:

  • 不跨語言
  • 安全風險(反序列化gongji)
  • .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》