pkl & npz & yaml & yml

什么是 .pkl (Pickle) 格式?

Pickle 是 Python 自带的一个序列化模块。所谓“序列化”,就是把内存里的 Python 对象(比如列表、字典、甚至你自己写的类实例)转化成一串二进制字节流,保存到硬盘上

  • 能存什么:几乎所有的 Python 对象。包括:
    • 简单的:列表、字典、字符串
    • 复杂的:训练好的机器学习模型(如 Scikit-learn 模型)、自定义的类、嵌套非常深的数据结构
  • 优点:
    • 极其通用:只要是 Python 对象,通常都能保存
    • 保持结构:读回来的时候,原来的字典还是字典,类还是类
  • 缺点:
    • 安全性差:加载不明来源的 .pkl 文件可能会执行恶意代码
    • 跨语言难:它是 Python 专用的,很难在 C++ 或 Java 中直接读取
    • 性能一般:对于海量纯数值数据,读写速度不如专门的格式

代码示例:

1
2
3
4
5
6
7
8
9
10
import pickle

data = {'name': 'Alice', 'scores': [95, 88, 100]}
# 保存
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)

# 加载
with open('data.pkl', 'rb') as f:
loaded_data = pickle.load(f)

什么是 .npz (NumPy Zip) 格式?

.npz 是 NumPy 库特有的压缩格式。它其实是一个 ZIP 压缩包,里面打包了多个 .npy 文件(每个 .npy 文件代表一个独立的 NumPy 数组)

  • 能存什么:专门存储 NumPy 数组(ndarrays)
  • 优点:
    • 高效且省空间:专门为数字矩阵优化,读取速度极快,且支持压缩(savez_compressed)
    • 支持“延迟加载” (Lazy Loading):当你打开一个 10GB 的 .npz 时,它不会立刻把所有数组塞进内存,而是等到你真正访问某个数组(如 data[‘arr1’])时才读取
    • 适合大数据集:常用于存储深度学习的权重、训练集的特征向量等
  • 缺点:
    • 单一性:虽然也能强行存一些简单对象,但它主要是为数组设计的,不适合存复杂的自定义类

代码示例:

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

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

# 保存(可以给数组起名)
np.savez('arrays.npz', x=arr1, y=arr2)

# 加载
data = np.load('arrays.npz')
print(data['x']) # 访问指定的数组

对比

特性 .pkl (Pickle) .npz (NumPy)
主要用途 保存复杂对象、训练好的模型 保存大量的数字矩阵、多维数组
支持类型 几乎所有 Python 类型 主要是 NumPy 数组
读取速度 较慢(对数值数据) 极快(对数值数据)
安全性 存在安全风险(不建议加载未知文件) 相对安全
存储方式 单一二进制流 多个数组的压缩包(ZIP)
典型场景 保存 RandomForest 模型、配置字典 保存 深度学习权重、图像像素矩阵
  • 处理纯数字、矩阵、张量(比如特征、图像数据、权重),选 .npz 或 .npy
  • 需要把整个模型、复杂的配置、或者是各种乱七八糟的对象存成一个文件,选择 .pkl
  • 在深度学习中(如 PyTorch),模型文件通常也是基于 pickle 的变体(如 .pth 或 .pt),但内部针对张量存储做了特殊优化

什么是 YAML / YML?

YAML (YAML Ain’t Markup Language) 是一种专门设计用来方便人类读取的数据序列化格式

  • YAML vs. YML:两者完全相同,只是后缀名不同。.yml 是为了兼容老旧系统的三位后缀习惯,现在两者通用
  • 核心特点:
    • 极高可读性:使用缩进表示层级,没有繁琐的括号或分号
    • 强类型支持:自动识别数字、布尔值、字符串和列表
    • 用途:主要用于配置文件(如你的 Hexo _config.yml)、超参数记录和数据集描述

YAML 和 NPZ&PKL

A. 职责分工

  • YAML (元数据层):存储“轻量级”信息。比如模型结构说明、训练时的学习率、数据集的路径、类别名称等
  • NPZ (数值层):存储“重型”矩阵数据(如图像张量、机器人轨迹点)
  • PKL (对象层):存储“复杂”的 Python 对象(如训练好的模型实例、复杂的嵌套字典)

B. 协作场景示例:VLA 训练配置

假设你有一个机器人动作数据集,你的文件夹里通常会这样组织:

  1. config.yaml:记录实验编号、使用的显卡 ID、.npz 文件的路径清单
  2. trajectories.npz:存储数百万个浮点数组成的机器人抓取坐标
  3. model_info.pkl:存储一个自定义的类,记录了模型训练的中间状态或特定的归一化参数

代码:如何将它们结合

在 Python 中,我们通常使用 PyYAML 库来读取配置,然后根据配置去加载对应的数值文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import yaml
import numpy as np
import pickle

# 1. 读取 YAML 配置文件
with open('experiment_config.yaml', 'r') as f:
config = yaml.safe_load(f)

print(f"正在进行实验: {config['experiment_name']}")
learning_rate = config['training']['lr']

# 2. 根据 YAML 中的路径加载 NPZ 数据
data_path = config['data_paths']['trajectory_file']
arrays = np.load(data_path) # 加载 npz 文件
arm_coords = arrays['coords']

# 3. 加载 PKL 中的复杂模型对象
model_path = config['data_paths']['model_file']
with open(model_path, 'rb') as f:
model_state = pickle.load(f) # 加载 pkl 文件