目录

  1. 概述
  2. 权重文件基础概念
  3. 常见权重文件格式
  4. 格式对比
  5. 选择建议
  6. 转换工具
  7. 最佳实践
  8. 常见问题

概述

大模型权重文件是训练完成后保存的模型参数文件,包含了神经网络的所有可学习参数(权重、偏置等)。不同的深度学习框架和部署场景衍生出了多种权重文件格式,每种格式都有其特定的优势和适用场景。

随着大模型技术的快速发展,权重格式也在不断演进,从最初的框架原生格式到如今的通用格式,安全性和加载效率成为重要的考量因素。


权重文件基础概念

什么是模型权重

模型权重是神经网络中可学习的参数,主要包括:

参数类型 说明 示例
权重矩阵 (Weight) 层与层之间的连接参数 全连接层的权重矩阵
偏置 (Bias) 每个神经元的偏移量 卷积层的偏置项
归一化参数 批归一化层的参数 BN层的 γ 和 β
嵌入矩阵 词嵌入层的参数 Word Embedding
位置编码 位置编码参数 Transformer的位置编码

权重的数据结构

# 典型的权重字典结构示例
state_dict = {
    'model.encoder.layer.0.attention.self.query.weight': tensor([...]),
    'model.encoder.layer.0.attention.self.query.bias': tensor([...]),
    'model.encoder.layer.0.attention.self.key.weight': tensor([...]),
    # ... 更多层
    'model.pooler.dense.weight': tensor([...]),
    'model.pooler.dense.bias': tensor([...]),
}

精度与存储大小

不同精度对模型大小和性能的影响:

精度 字节/参数 7B模型大小 13B模型大小 70B模型大小 质量影响
FP32 4字节 28GB 52GB 280GB 无损
FP16 2字节 14GB 26GB 140GB 极小
BF16 2字节 14GB 26GB 140GB 极小
INT8 1字节 7GB 13GB 70GB 轻微
INT4 0.5字节 3.5GB 6.5GB 35GB 可察觉
INT2 0.25字节 1.75GB 3.25GB 17.5GB 明显

常见权重文件格式

PyTorch 格式 (.pt/.pth/.bin)

描述:PyTorch 框架的原生权重格式,使用 Python 的 pickle 模块进行序列化。

文件结构

  • 使用 Python pickle 序列化字典
  • 包含键值对,键为参数名称,值为张量数据
  • 可保存模型权重、优化器状态、学习率调度器等

特点

  • ✅ 与 PyTorch 生态完全兼容
  • ✅ 支持保存完整的模型结构和优化器状态
  • ✅ 使用简单,保存和加载方便
  • ✅ 支持动态计算图
  • ❌ 存在安全风险(pickle 可能执行恶意代码)
  • ❌ 文件体积较大
  • ❌ 加载速度相对较慢
  • ❌ 跨框架兼容性差

适用场景

  • PyTorch 模型的训练和推理
  • 需要保存训练中间状态(如优化器状态、学习率调度器)
  • 研究和开发环境
  • 模型微调和断点续训

文件内部结构

PyTorch 文件 (.pt/.pth)
├── 版本信息 (version)
├── 数据源 (source)
├── 数据 (data)
│   ├── 键值对 1 (key1: tensor)
│   ├── 键值对 2 (key2: tensor)
│   └── ...
└── 其他元数据

示例代码

import torch

# 保存模型权重(仅保存参数)
torch.save(model.state_dict(), 'model.pth')

# 保存完整模型(包含结构)
torch.save(model, 'model_full.pt')

# 保存训练状态(包含优化器、学习率调度器等)
checkpoint = {
    'epoch': epoch,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'loss': loss,
    'lr_scheduler_state_dict': scheduler.state_dict(),
}
torch.save(checkpoint, 'checkpoint.pth')

# 加载模型权重
model.load_state_dict(torch.load('model.pth', map_location='cpu'))

# 加载完整模型
model = torch.load('model_full.pt')

# 加载训练状态
checkpoint = torch.load('checkpoint.pth')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])

安全警告

# 不安全的加载方式(可能执行恶意代码)
state_dict = torch.load('untrusted_model.pth')

# 推荐的安全加载方式(仅加载数据,不执行代码)
state_dict = torch.load('model.pth', weights_only=True)

SafeTensors 格式 (.safetensors)

描述:由 Hugging Face 推出的安全、快速的模型权重格式,旨在替代 pickle 格式。

设计目标

  1. 安全性:不涉及代码执行,防止恶意代码注入
  2. 速度:零拷贝反序列化,加载速度更快
  3. 简单性:文件格式简单,易于解析
  4. 兼容性:跨框架、跨平台支持

文件结构

SafeTensors 文件 (.safetensors)
├── 头部 (Header) - 8字节长度 + JSON 元数据
│   ├── 张量信息(名称、形状、数据类型、偏移量)
│   └── 元数据(可选)
├── 数据区 (Data) - 原始张量数据
│   ├── tensor1_data
│   ├── tensor2_data
│   └── ...
└── 填充区 (Padding) - 对齐用

头部 JSON 示例

{
  "__metadata__": { "format": "pt" },
  "model.layers.0.self_attn.q_proj.weight": {
    "dtype": "bfloat16",
    "shape": [4096, 4096],
    "data_offsets": [0, 33554432]
  },
  "model.layers.0.self_attn.k_proj.weight": {
    "dtype": "bfloat16",
    "shape": [1024, 4096],
    "data_offsets": [33554432, 41943040]
  }
}

特点

  • ✅ 安全性高(不涉及代码执行)
  • ✅ 加载速度快(零拷贝反序列化,比 PyTorch 快 3-10 倍)
  • ✅ 文件体积相对较小(无 pickle 开销)
  • ✅ 支持懒加载(lazy loading),可部分读取
  • ✅ 跨框架兼容性好
  • ✅ 内存映射(mmap)支持
  • ❌ 相对较新,部分旧工具可能不支持
  • ❌ 不支持保存优化器状态
  • ❌ 不支持动态计算图

性能对比

操作 PyTorch (.pth) SafeTensors (.safetensors) 提升
加载 7B 模型 ~60秒 ~15秒 4x
加载 70B 模型 ~600秒 ~120秒 5x
内存占用 较高 较低 -20%

适用场景

  • 模型分发和共享
  • 生产环境部署
  • 需要快速加载模型的场景
  • 安全敏感的应用
  • Hugging Face Hub 上的模型发布

示例代码

from safetensors.torch import save_file, load_file
import torch

# 保存模型权重
tensors = {key: value.contiguous() for key, value in model.state_dict().items()}
save_file(tensors, 'model.safetensors')

# 加载模型权重(完整加载)
state_dict = load_file('model.safetensors', device='cpu')
model.load_state_dict(state_dict)

# 懒加载(部分加载)
from safetensors import safe_open

with safe_open('model.safetensors', framework='pt', device='cpu') as f:
    # 只读取特定张量
    tensor_names = f.keys()
    specific_tensor = f.get_tensor('model.layers.0.self_attn.q_proj.weight')

多文件分片

model.safetensors.index.json    # 索引文件,记录每个张量在哪个分片
model-00001-of-00004.safetensors # 分片 1
model-00002-of-00004.safetensors # 分片 2
model-00003-of-00004.safetensors # 分片 3
model-00004-of-00004.safetensors # 分片 4

ONNX 格式 (.onnx)

描述:Open Neural Network Exchange 格式,是一种开放的模型表示格式,支持跨框架模型转换。

设计目标

  1. 跨框架兼容:PyTorch、TensorFlow、Caffe2 等框架互转
  2. 优化部署:支持模型优化和量化
  3. 硬件加速:支持各种硬件加速器

文件结构

ONNX 文件 (.onnx)
├── 模型结构 (Model)
│   ├── 图信息 (Graph)
│   │   ├── 输入节点 (Inputs)
│   │   ├── 输出节点 (Outputs)
│   │   ├── 节点列表 (Nodes) - 算子
│   │   ├── 初始化器 (Initializers) - 权重
│   │   └── 值信息 (Value Info)
│   ├── 算子集 (Opset)
│   └── 元数据 (Metadata)
└── 序列化的 Protocol Buffer 数据

支持的数据类型

ONNX 类型 NumPy 类型 说明
FLOAT float32 32位浮点
UINT8 uint8 8位无符号整数
INT8 int8 8位有符号整数
UINT16 uint16 16位无符号整数
INT16 int16 16位有符号整数
INT32 int32 32位有符号整数
INT64 int64 64位有符号整数
STRING str 字符串
BOOL bool 布尔值
FLOAT16 float16 16位浮点
DOUBLE float64 64位浮点
UINT32 uint32 32位无符号整数
UINT64 uint64 64位无符号整数
COMPLEX64 complex64 64位复数
COMPLEX128 complex128 128位复数

特点

  • ✅ 跨框架兼容(PyTorch、TensorFlow、Caffe2 等)
  • ✅ 支持模型优化和量化
  • ✅ 推理性能优秀
  • ✅ 支持硬件加速(如 TensorRT、OpenVINO)
  • ✅ 静态计算图,推理效率高
  • ❌ 可能丢失部分训练时的元数据
  • ❌ 转换过程可能遇到算子不兼容问题
  • ❌ 不支持保存优化器状态
  • ❌ 动态控制流支持有限

算子集 (Opset)

  • ONNX 定义了多个算子集版本
  • 新版本支持更多算子,但兼容性可能降低
  • 常用版本:opset 11, 13, 17, 18

适用场景

  • 跨平台模型部署
  • 边缘设备和移动端部署
  • 需要高性能推理的场景
  • 模型优化和量化
  • 与各种推理引擎集成

示例代码

import torch
import torch.onnx

# 准备模型和数据
model.eval()
dummy_input = torch.randn(1, 3, 224, 224)

# 导出为 ONNX 格式
torch.onnx.export(
    model,                          # PyTorch 模型
    dummy_input,                    # 示例输入
    'model.onnx',                   # 输出文件名
    export_params=True,             # 导出训练参数
    opset_version=17,               # ONNX 算子集版本
    do_constant_folding=True,       # 常量折叠优化
    input_names=['input'],          # 输入节点名称
    output_names=['output'],        # 输出节点名称
    dynamic_axes={                  # 动态维度
        'input': {0: 'batch_size', 2: 'height', 3: 'width'},
        'output': {0: 'batch_size'}
    }
)

# 验证导出的模型
import onnx
onnx_model = onnx.load('model.onnx')
onnx.checker.check_model(onnx_model)

# 使用 ONNX Runtime 推理
import onnxruntime as ort
session = ort.InferenceSession('model.onnx')
outputs = session.run(None, {'input': input_data.numpy()})

量化支持

from onnxruntime.quantization import quantize_dynamic, quantize_static

# 动态量化(INT8)
quantize_dynamic('model.onnx', 'model_int8.onnx', weight_type=QuantType.QInt8)

# 静态量化(需要校准数据)
quantize_static('model.onnx', 'model_int8_static.onnx', calibration_data_reader)

TensorFlow 格式 (.h5/.pb/.ckpt)

描述:TensorFlow 框架的权重格式,包括 HDF5 格式(.h5)、SavedModel 格式(.pb)和检查点格式(.ckpt)。

HDF5 格式 (.h5)

文件结构

HDF5 文件 (.h5)
├── 模型结构 (model_weights)
│   ├── 层1 (layer1)
│   │   ├── 权重 (weights)
│   │   └── 偏置 (bias)
│   ├── 层2 (layer2)
│   └── ...
├── 训练配置 (training_config)
└── 优化器状态 (optimizer_weights) [可选]

特点

  • ✅ 单文件存储,便于分发
  • ✅ 支持保存完整模型结构
  • ✅ 支持保存优化器状态
  • ❌ 不支持自定义模型结构
  • ❌ 跨框架兼容性差
SavedModel 格式 (.pb)

文件结构

SavedModel 目录
├── saved_model.pb          # 模型图定义
├── variables/              # 变量(权重)
│   ├── variables.data-00000-of-00001
│   └── variables.index
└── assets/                 # 资源文件(如词汇表)
    └── assets.txt

特点

  • ✅ TensorFlow Serving 标准格式
  • ✅ 支持模型签名 (Signature)
  • ✅ 支持多种计算图
  • ✅ 支持 Asset 文件
  • ❌ 格式较为复杂
  • ❌ 跨框架兼容性差
Checkpoint 格式 (.ckpt)

文件结构

Checkpoint 目录
├── checkpoint              # 索引文件,记录检查点状态
├── ckpt-00001.data-00000-of-00001  # 权重数据
├── ckpt-00001.index       # 索引数据
└── ckpt-00001.meta        # 元数据(图结构)

特点

  • ✅ 支持增量保存
  • ✅ 可恢复训练
  • ✅ 支持分布式训练
  • ✅ 包含优化器状态
  • ❌ 格式因框架版本而异
  • ❌ 文件体积较大

示例代码

import tensorflow as tf

# ===== HDF5 格式 =====
# 保存模型
model.save('model.h5')

# 加载模型
model = tf.keras.models.load_model('model.h5')

# ===== SavedModel 格式 =====
# 保存模型
tf.saved_model.save(model, 'saved_model/')

# 加载模型
loaded_model = tf.saved_model.load('saved_model/')

# 使用签名推理
infer = loaded_model.signatures['serving_default']
output = infer(input_tensor)

# ===== Checkpoint 格式 =====
# 创建检查点回调
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath='checkpoints/ckpt-{epoch:04d}',
    save_weights_only=True,
    save_freq='epoch'
)

# 保存检查点
model.save_weights('checkpoints/ckpt')

# 加载检查点
model.load_weights('checkpoints/ckpt')

GGUF 格式 (.gguf)

描述:GPT-Generated Unified Format,专为 llama.cpp 和本地 LLM 部署设计的格式。

设计目标

  1. 统一格式:整合模型配置、 tokenizer、权重数据
  2. 量化支持:内置多种量化方案
  3. 本地优化:专为 CPU 推理优化
  4. 元数据嵌入:支持丰富的模型元数据

文件结构

GGUF 文件 (.gguf)
├── 文件头 (Header)
│   ├── 魔数 (Magic): 0x46554747 ("GGUF")
│   ├── 版本号 (Version): 3
│   ├── 张量数量 (Tensor Count)
│   └── 元数据数量 (KV Count)
├── 元数据区 (Metadata) - 键值对
│   ├── 模型架构信息
│   ├── 量化信息
│   ├── Tokenizer 配置
│   └── 其他自定义元数据
├── 张量信息区 (Tensor Info)
│   ├── 张量名称
│   ├── 张量形状
│   ├── 张量类型
│   └── 偏移量
└── 张量数据区 (Tensor Data)
    ├── tensor1_data (可能已量化)
    ├── tensor2_data
    └── ...

元数据示例

{
  "general.architecture": "llama",
  "general.name": "Llama 2 7B",
  "llama.context_length": 4096,
  "llama.embedding_length": 4096,
  "llama.block_count": 32,
  "llama.attention.head_count": 32,
  "llama.attention.layer_norm_rms_epsilon": 1e-05,
  "general.file_type": 15,
  "general.quantize_version": 2
}

量化类型详解

类型 比特数 块大小 7B模型大小 质量 推理速度 说明
F32 32 - 28GB ★★★★★ ★☆☆☆☆ 无损
F16 16 - 14GB ★★★★★ ★★☆☆☆ 几乎无损
Q8_0 8 32 7.5GB ★★★★☆ ★★★☆☆ 高质量
Q6_K 6 256 5.5GB ★★★★☆ ★★★☆☆ 高质量
Q5_K_M 5 256 4.8GB ★★★☆☆ ★★★★☆ 平衡
Q5_K_S 5 256 4.6GB ★★★☆☆ ★★★★☆ 轻量
Q4_K_M 4 256 4.1GB ★★★☆☆ ★★★★☆ 推荐
Q4_K_S 4 256 3.9GB ★★★☆☆ ★★★★☆ 轻量
Q4_0 4 32 3.8GB ★★☆☆☆ ★★★★★ 快速
Q3_K_M 3 256 3.3GB ★★☆☆☆ ★★★★☆ 紧凑
Q3_K_S 3 256 3.1GB ★★☆☆☆ ★★★★☆ 轻量
Q3_K_L 3 256 3.6GB ★★☆☆☆ ★★★★☆ 大型
Q2_K 2 256 2.7GB ★☆☆☆☆ ★★★★☆ 最紧凑
Q2_K_S 2 256 2.5GB ★☆☆☆☆ ★★★★☆ 超轻量
IQ1_S 1 256 1.8GB ☆☆☆☆☆ ★★★☆☆ 实验性
IQ1_M 1 256 2.0GB ☆☆☆☆☆ ★★★☆☆ 实验性

量化命名规则

  • Q:Quantized(量化)
  • 数字:每个元素占用的比特数
  • _K:使用块量化(K-quant),块大小为 256
  • _M:Medium(中等质量),使用重要性矩阵
  • _S:Small(轻量),质量略低但体积更小
  • _L:Large(大型),质量更高但体积更大
  • IQ:Integer Quantization(整数量化),实验性

量化原理详解

1. 基础量化(如 Q4_0)

原始 FP16 权重: [-0.1234, 0.5678, -0.9012, 0.3456, ...]

量化为 Q4_0:
1. 将权重分成 32 个元素的块
2. 计算每个块的 scale 和 min 值
3. 将每个值映射到 [-8, 7] 范围
4. 存储 scale、min 和量化后的值

量化后: scale=0.0025, min=-0.95, values=[-8, 7, -8, 7, ...]

2. K-Quant 量化(如 Q4_K_M)

K-Quant 量化过程:
1. 将权重分成 256 个元素的块
2. 识别"重要"和"非重要"权重
3. 对重要权重使用更高的精度
4. 对非重要权重使用更低的精度
5. 存储 scale、min 和量化后的值

优势:在相同比特数下,保留更多关键信息

3. 重要性矩阵(Importance Matrix)

重要性矩阵的作用:
- 识别模型中对输出影响较大的权重
- 对重要权重分配更多比特
- 对非重要权重分配更少比特
- 在保持质量的同时减少体积

M(Medium)vs S(Small):
- Q4_K_M: 使用重要性矩阵,质量更高
- Q4_K_S: 不使用重要性矩阵,体积更小

4. 量化类型选择指南

需求场景 推荐类型 备选类型 说明
高质量生成 Q8_0 Q6_K 适合需要高质量输出的场景
平衡选择 Q4_K_M Q5_K_M 推荐大多数用户使用
资源受限 Q3_K_M Q4_K_S 适合内存有限的环境
极致压缩 Q2_K Q2_K_S 适合存储受限的环境
实验性 IQ1_M IQ1_S 正在研究中,质量较低

量化注意事项

  1. 精度损失

    • 量化会导致模型质量下降
    • 下降程度取决于量化级别和模型类型
    • 建议在实际任务上测试量化后的模型
  2. 硬件兼容性

    • 不同量化类型对硬件要求不同
    • Q4_0 和 Q8_0 兼容性最好
    • Q2_K 和 IQ1 可能需要特定硬件支持
  3. 内存占用

    • 量化后的模型仍需加载到内存
    • 运行时内存占用约为模型大小的 1.5-2 倍
    • 需预留足够的内存空间
  4. 推理速度

    • 量化级别越低,推理速度越快
    • 但质量也会相应下降
    • 需根据实际需求权衡
  5. GGUF 文件类型

    • general.file_type 元数据类型表示量化类型
    • 常见值:1 (F32), 2 (F16), 7 (Q8_0), 8 (Q4_K_M), 15 (Q2_K)
  6. 量化版本

    • general.quantize_version 表示量化版本
    • 版本 2 是当前推荐的版本
    • 新版本可能包含量化算法改进
  7. 混合量化(Mixed Quantization)

    基本概念

    • 混合量化是指对模型中不同的层或张量使用不同的量化类型
    • 核心思想:对模型输出影响大的层使用高精度,影响小的层使用低精度
    • 优势:在保持模型质量的同时,进一步减小模型体积

    为什么需要混合量化

    • 不同层对模型质量的贡献不同
    • 例如:embedding 层直接影响词汇理解,需要更高精度
    • 中间层可能对质量影响相对较小,可以使用更低精度
    • 全局统一量化无法平衡质量和体积

    常见的混合量化策略

    策略名称 高精度层 低精度层 适用场景
    嵌入层优先 Embedding (Q8_0) 其他层 (Q4_K_M) 通用场景
    输出层优先 Output/Embedding (Q8_0) 中间层 (Q4_K_M) 需要高质量输出
    关键层优先 Attention (Q6_K) FFN (Q4_K_M) 需要保持推理能力
    分层量化 前几层 (Q6_K) 后几层 (Q4_K_M) 长文本生成

    混合量化命令示例

    # 指定 embedding 层使用 Q8_0,其他层使用 Q4_K_M
    ./quantize --embedding-qtype q8_0 input.gguf output.gguf q4_K_M
    
    # 指定 output 张量使用 Q8_0,其他层使用 Q4_K_M
    ./quantize --output-tensor q8_0 input.gguf output.gguf q4_K_M
    
    # 同时指定 embedding 和 output 使用高精度
    ./quantize --embedding-qtype q8_0 --output-tensor q8_0 input.gguf output.gguf q4_K_M
    
    # 指定特定层范围使用不同精度
    ./quantize --layer-range 0-10 q6_k --layer-range 11-31 q4_k input.gguf output.gguf q4_K_M
    

    混合量化的工作原理

    原始模型 (FP16):
    ├── Embedding Layer (重要) → 量化为 Q8_0
    ├── Attention Layer 0-15 (关键) → 量化为 Q6_K
    ├── FFN Layer 0-15 (一般) → 量化为 Q4_K_M
    ├── Attention Layer 16-31 (关键) → 量化为 Q6_K
    ├── FFN Layer 16-31 (一般) → 量化为 Q4_K_M
    └── Output Layer (重要) → 量化为 Q8_0
    
    混合量化后:
    - 关键层保持高质量 (Q8_0, Q6_K)
    - 非关键层大幅压缩 (Q4_K_M)
    - 整体体积比全局 Q4_K_M 略大,但质量更好
    

    混合量化的效果对比

    量化方式 7B模型大小 困惑度 (PPL) 质量评价
    全局 Q4_K_M 4.1GB 6.5 ★★★☆☆
    全局 Q6_K 5.5GB 5.8 ★★★★☆
    混合量化 (Embedding+Output Q8_0) 4.5GB 6.0 ★★★★☆
    混合量化 (关键层 Q6_K) 5.0GB 5.9 ★★★★☆

    选择建议

    • 内存充足:使用全局 Q6_K 或关键层 Q6_K 的混合量化
    • 内存受限:使用全局 Q4_K_M 或 Embedding Q8_0 + 其他 Q4_K_M
    • 存储受限:使用全局 Q3_K 或更低精度
    • 最佳平衡:Embedding/Output Q8_0 + 其他 Q4_K_M
  8. 量化效果评估

    • 使用 perplexity(困惑度)评估量化效果
    • 困惑度越低,量化效果越好
    • 建议在标准数据集上进行评估

量化命令示例

# 基本量化
./quantize input.gguf output.gguf q4_K_M

# 指定量化类型
./quantize input.gguf output-Q8_0.gguf q8_0
./quantize input.gguf output-Q4_K_M.gguf q4_K_M
./quantize input.gguf output-Q2_K.gguf q2_k

# 带混合量化的量化
./quantize --embedding-qtype q8_0 --output-tensor q4_K_M input.gguf output.gguf q4_K_M

特点

  • ✅ 专为大语言模型优化
  • ✅ 支持多种量化级别(Q2_K 到 F32)
  • ✅ 适合 CPU 推理
  • ✅ 文件体积可大幅压缩
  • ✅ 支持元数据嵌入
  • ✅ 单文件包含所有信息
  • ❌ 主要用于推理,不支持训练
  • ❌ 生态系统相对较小

适用场景

  • 本地大语言模型部署
  • 资源受限环境(如个人电脑)
  • 使用 llama.cpp、Ollama 等工具
  • 需要量化模型的场景
  • 边缘设备部署

示例代码

# 使用 llama.cpp 加载 GGUF 模型
from llama_cpp import Llama

# 加载模型
llm = Llama(
    model_path="model-q4_K_M.gguf",
    n_ctx=4096,          # 上下文长度
    n_threads=8,         # 线程数
    n_gpu_layers=0,      # GPU 层数(0表示纯CPU)
)

# 生成文本
output = llm(
    "Hello, how are you?",
    max_tokens=128,
    temperature=0.7,
    top_p=0.9,
)
print(output)

支持的推理框架

  • llama.cpp(原生支持)
  • Ollama(封装 llama.cpp)
  • LM Studio(GUI 工具)
  • text-generation-webui(Web UI)
  • ctransformers(Python 绑定)
  • llama-cpp-python(Python 绑定)

GGML 格式 (.ggml)

描述:llama.cpp 早期使用的模型格式,现已被 GGUF 格式取代。

历史背景

  • 2023年初:GGML 格式首次发布
  • 2023年中:GGUF 格式发布,逐步取代 GGML
  • 2024年:GGML 格式停止维护

特点

  • ✅ 专为 CPU 推理优化
  • ✅ 支持量化
  • ❌ 已被 GGUF 格式取代
  • ❌ 功能相对有限
  • ❌ 不再推荐使用

适用场景

  • 旧版 llama.cpp 项目
  • 历史项目维护

迁移建议

# 使用 llama.cpp 将 GGML 转换为 GGUF
./main --model.ggml-model.bin --convert ggml-to-gguf

Checkpoint 格式 (.ckpt)

描述:通用的模型检查点格式,用于保存训练过程中的模型状态。

文件结构(以 PyTorch Lightning 为例):

Checkpoint 文件 (.ckpt)
├── epoch                    # 当前 epoch
├── global_step              # 全局步数
├── pytorch-lightning_version # PyTorch Lightning 版本
├── callbacks                 # 回调函数状态
├── lr_schedulers            # 学习率调度器状态
├── optimizer_states         # 优化器状态
│   ├── optimizer_0
│   │   ├── state
│   │   └── param_groups
│   └── ...
├── model_state_dict         # 模型权重
├── hyperparameters          # 超参数
└── 其他训练状态

特点

  • ✅ 支持增量保存
  • ✅ 可恢复训练
  • ✅ 支持分布式训练
  • ✅ 包含优化器状态
  • ✅ 保存完整的训练状态
  • ❌ 格式因框架而异
  • ❌ 文件体积较大
  • ❌ 主要用于训练,不推荐用于部署

适用场景

  • 模型训练过程中的状态保存
  • 断点续训
  • 模型微调
  • 模型评估

示例代码

import torch
import pytorch_lightning as pl

# ===== 保存检查点 =====
# 手动保存
checkpoint = {
    'epoch': epoch,
    'global_step': global_step,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'lr_scheduler_state_dict': scheduler.state_dict(),
    'loss': loss,
}
torch.save(checkpoint, 'manual_checkpoint.ckpt')

# 使用 PyTorch Lightning 自动保存
trainer = pl.Trainer(
    callbacks=[
        pl.callbacks.ModelCheckpoint(
            dirpath='checkpoints/',
            filename='{epoch}-{val_loss:.2f}',
            save_top_k=3,
            monitor='val_loss',
            save_last=True,
        )
    ]
)

# ===== 加载检查点 =====
# 手动加载
checkpoint = torch.load('manual_checkpoint.ckpt')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
start_epoch = checkpoint['epoch'] + 1

# 使用 PyTorch Lightning 加载
model = MyLightningModule.load_from_checkpoint('checkpoint.ckpt')

Hugging Face 格式

描述:Hugging Face Hub 使用的模型存储格式,通常包含多个文件。

典型文件结构

model-name/
├── .gitattributes           # Git LFS 配置
├── config.json              # 模型配置
├── model.safetensors        # SafeTensors 权重(新版)
├── pytorch_model.bin        # PyTorch 权重(旧版)
├── generation_config.json   # 生成配置
├── tokenizer.json           # 分词器配置
├── tokenizer_config.json    # 分词器设置
├── special_tokens_map.json  # 特殊 token 映射
├── tokenizer.model          # SentencePiece 模型
├── vocab.json               # 词汇表
├── merges.txt               # BPE 合并规则
├── preprocessor_config.json # 预处理器配置
├── feature_extractor_config.json
├── README.md                # 模型卡片
└── LICENSE                  # 许可证

config.json 示例

{
  "architectures": ["LlamaForCausalLM"],
  "hidden_size": 4096,
  "intermediate_size": 11008,
  "max_position_embeddings": 4096,
  "model_type": "llama",
  "num_attention_heads": 32,
  "num_hidden_layers": 32,
  "num_key_value_heads": 32,
  "vocab_size": 32000,
  "torch_dtype": "bfloat16",
  "transformers_version": "4.31.0",
  "hidden_act": "silu",
  "rms_norm_eps": 1e-06,
  "rope_theta": 10000.0,
  "tie_word_embeddings": false
}

特点

  • ✅ 标准化的模型仓库结构
  • ✅ 支持版本控制和共享
  • ✅ 包含模型配置和分词器
  • ✅ 支持 SafeTensors 格式
  • ✅ 社区支持广泛
  • ✅ 自动模型加载
  • ❌ 依赖 Hugging Face 生态
  • ❌ 文件大小限制(单文件 50GB)

示例代码

from transformers import AutoModel, AutoTokenizer

# 加载模型和分词器
model = AutoModel.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")

# 保存模型(使用 SafeTensors 格式)
model.save_pretrained("./local-model", safe_serialization=True)
tokenizer.save_pretrained("./local-model")

# 从本地加载
model = AutoModel.from_pretrained("./local-model")
tokenizer = AutoTokenizer.from_pretrained("./local-model")

# 推送到 Hub
model.push_to_hub("my-model-name")

PaddlePaddle 格式 (.pdparams)

描述:PaddlePaddle 深度学习框架的原生权重格式。

特点

  • ✅ 与 PaddlePaddle 生态完全兼容
  • ✅ 支持分布式训练
  • ✅ 支持模型压缩
  • ❌ 跨框架兼容性差
  • ❌ 生态系统相对较小

示例代码

import paddle

# 保存模型权重
paddle.save(model.state_dict(), 'model.pdparams')

# 加载模型权重
state_dict = paddle.load('model.pdparams')
model.set_state_dict(state_dict)

CoreML 格式 (.mlmodel/.mlpackage)

描述:Apple 的机器学习框架格式,专为 iOS/macOS 优化。

文件结构

ML Package 目录
├── Model.mlpackage
│   ├── Data/
│   │   ├── model.mlmodel    # 模型描述
│   │   ├── weights/        # 权重数据
│   │   │   ├── weight_0.bin
│   │   │   └── ...
│   │   └── metadata.json   # 元数据
│   └── Manifest.json
└── ...

特点

  • ✅ Apple 设备原生支持
  • ✅ 支持 Neural Engine 加速
  • ✅ 支持模型加密
  • ✅ 支持隐私保护
  • ❌ 仅限 Apple 生态
  • ❌ 转换过程复杂

示例代码

import coremltools as ct

# 将 PyTorch 模型转换为 CoreML
mlmodel = ct.convert(
    model,
    inputs=[ct.ImageType(name="input", shape=(1, 3, 224, 224))],
)
mlmodel.save("model.mlpackage")

TensorRT 格式 (.engine/.plan)

描述:NVIDIA TensorRT 的高性能推理格式,专为 NVIDIA GPU 优化。

特点

  • ✅ NVIDIA GPU 最优性能
  • ✅ 支持 FP16/INT8 推理
  • ✅ 自动内核调优
  • ✅ 支持动态形状
  • ❌ 仅限 NVIDIA GPU
  • ❌ 转换过程耗时
  • ❌ 与硬件绑定

示例代码

import tensorrt as trt

# 从 ONNX 构建 TensorRT 引擎
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
parser = trt.OnnxParser(network, logger)

# 解析 ONNX 文件
with open('model.onnx', 'rb') as f:
    parser.parse(f.read())

# 构建引擎
config = builder.create_builder_config()
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30)  # 1GB
engine = builder.build_serialized_network(network, config)

# 保存引擎
with open('model.engine', 'wb') as f:
    f.write(engine)

格式对比

综合对比表

格式 扩展名 安全性 加载速度 文件大小 跨框架 量化支持 主要用途
PyTorch .pt/.pth ⚠️ 低 训练/推理
SafeTensors .safetensors ✅ 高 分发/推理
ONNX .onnx ✅ 高 部署/推理
TensorFlow .h5/.pb ✅ 高 训练/推理
GGUF .gguf ✅ 高 小-大 本地推理
GGML .ggml ✅ 高 小-大 已废弃
Checkpoint .ckpt ⚠️ 低 训练
PaddlePaddle .pdparams ⚠️ 低 训练/推理
CoreML .mlpackage ✅ 高 Apple 生态
TensorRT .engine ✅ 高 最快 小-中 NVIDIA GPU

场景对比表

使用场景 推荐格式 备选格式 原因
模型训练 PyTorch / Checkpoint TensorFlow 支持优化器状态保存
模型分发 SafeTensors GGUF 安全、快速、标准化
生产部署 ONNX SafeTensors 推理性能优秀
本地 LLM GGUF SafeTensors 量化支持好
移动端 CoreML (iOS) / TFLite (Android) ONNX 平台原生支持
NVIDIA GPU TensorRT ONNX GPU 最优性能
边缘设备 ONNX + INT8 GGUF 体积小、速度快
模型微调 PyTorch Checkpoint 支持断点续训
模型共享 SafeTensors (Hugging Face) - 社区标准

选择建议

训练阶段

  • 推荐:PyTorch (.pt/.pth) 或 Checkpoint (.ckpt)
  • 原因:支持保存优化器状态,便于断点续训
  • 注意事项
    • 定期保存检查点,防止训练中断
    • 保存完整的训练状态(模型、优化器、学习率调度器)
    • 使用框架提供的自动保存机制

模型分发

  • 推荐:SafeTensors (.safetensors)
  • 原因:安全、快速、文件适中
  • 注意事项
    • 单文件模型:直接使用 model.safetensors
    • 大模型分片:使用 model-00001-of-0000X.safetensors + 索引文件
    • 包含完整的模型配置和 tokenizer

生产部署

  • 推荐:ONNX (.onnx) 或 SafeTensors (.safetensors)
  • 原因:推理性能好,支持优化和量化
  • 注意事项
    • 使用 ONNX Runtime 或 TensorRT 进行推理
    • 考虑量化以提升性能
    • 使用模型优化工具(如 onnx-simplifier)

本地 LLM 部署

  • 推荐:GGUF (.gguf)
  • 原因:专为本地推理优化,支持多种量化级别
  • 注意事项
    • 根据硬件选择合适的量化级别
    • Q4_K_M 是平衡性能和质量的推荐选择
    • 使用 llama.cpp 或 Ollama 加载模型

跨平台部署

  • 推荐:ONNX (.onnx)
  • 原因:跨框架兼容性最好
  • 注意事项
    • 注意算子集版本兼容性
    • 验证目标平台的 ONNX Runtime 支持
    • 使用 onnx-simplifier 简化模型

资源受限环境

  • 推荐:GGUF (.gguf) 配合量化
  • 原因:可大幅压缩模型体积
  • 注意事项
    • 根据设备性能选择量化级别
    • 考虑内存占用和推理速度
    • 测试量化后的模型质量

Apple 生态

  • 推荐:CoreML (.mlpackage)
  • 原因:Apple 设备原生支持,性能最优
  • 注意事项
    • 使用 coremltools 转换模型
    • 支持 Neural Engine 加速
    • 注意模型大小限制

转换工具

1. PyTorch ↔ SafeTensors

pip install safetensors
from safetensors.torch import load_file, save_file
import torch

# PyTorch → SafeTensors
def pth_to_safetensors(input_path, output_path):
    state_dict = torch.load(input_path, map_location='cpu', weights_only=True)
    save_file(state_dict, output_path)
    print(f"转换完成: {output_path}")

# SafeTensors → PyTorch
def safetensors_to_pth(input_path, output_path):
    state_dict = load_file(input_path, device='cpu')
    torch.save(state_dict, output_path)
    print(f"转换完成: {output_path}")

# 使用示例
pth_to_safetensors('model.pth', 'model.safetensors')
safetensors_to_pth('model.safetensors', 'model.pth')

2. PyTorch → ONNX

pip install onnx onnxruntime onnx-simplifier
import torch
import torch.onnx

def export_to_onnx(model, dummy_input, output_path, opset_version=17):
    model.eval()
    torch.onnx.export(
        model,
        dummy_input,
        output_path,
        export_params=True,
        opset_version=opset_version,
        do_constant_folding=True,
        input_names=['input'],
        output_names=['output'],
        dynamic_axes={
            'input': {0: 'batch_size'},
            'output': {0: 'batch_size'}
        }
    )
    
    # 验证模型
    import onnx
    onnx_model = onnx.load(output_path)
    onnx.checker.check_model(onnx_model)
    
    # 简化模型
    from onnxsim import simplify
    model_simp, check = simplify(onnx_model)
    assert check, "简化失败"
    onnx.save(model_simp, output_path)
    print(f"转换完成: {output_path}")

# 使用示例
dummy_input = torch.randn(1, 3, 224, 224)
export_to_onnx(model, dummy_input, 'model.onnx')

3. Hugging Face 模型转换

from transformers import AutoModel, AutoTokenizer

def convert_hf_model(model_name, output_dir, format='safetensors'):
    # 下载模型
    model = AutoModel.from_pretrained(model_name)
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    
    # 保存模型
    if format == 'safetensors':
        model.save_pretrained(output_dir, safe_serialization=True)
    else:
        model.save_pretrained(output_dir, safe_serialization=False)
    
    tokenizer.save_pretrained(output_dir)
    print(f"模型已保存到: {output_dir}")

# 使用示例
convert_hf_model('meta-llama/Llama-2-7b-hf', './local-model')

4. GGUF 转换(使用 llama.cpp)

# 克隆 llama.cpp
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
pip install -r requirements.txt

# 转换 HF 模型为 GGUF
python convert-hf-to-gguf.py ../model-name \
    --outfile model-f16.gguf \
    --outtype f16

# 量化模型
./quantize model-f16.gguf model-q4_K_M.gguf q4_K_M

# 验证模型
./main -m model-q4_K_M.gguf -p "Hello, how are you?" -n 128

5. 使用 Optimum(Hugging Face)

pip install optimum[onnxruntime]
# 导出为 ONNX
optimum-cli export onnx --model model-name ./onnx-model/

# 量化 ONNX 模型
optimum-cli export onnx --model model-name --quantize int8 ./onnx-model-int8/

6. ONNX ↔ TensorRT

pip install tensorrt
# 使用 trtexec 转换
trtexec --onnx=model.onnx --saveEngine=model.engine --fp16

# 使用 Python API
import tensorrt as trt

def onnx_to_tensorrt(onnx_path, engine_path, fp16=True):
    logger = trt.Logger(trt.Logger.WARNING)
    builder = trt.Builder(logger)
    network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
    parser = trt.OnnxParser(network, logger)
    
    with open(onnx_path, 'rb') as f:
        parser.parse(f.read())
    
    config = builder.create_builder_config()
    config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30)
    
    if fp16 and builder.platform_has_fast_fp16:
        config.set_flag(trt.BuilderFlag.FP16)
    
    engine = builder.build_serialized_network(network, config)
    
    with open(engine_path, 'wb') as f:
        f.write(engine)
    print(f"转换完成: {engine_path}")

最佳实践

1. 训练阶段

# 定期保存检查点
checkpoint_callback = pl.callbacks.ModelCheckpoint(
    dirpath='checkpoints/',
    filename='{epoch}-{val_loss:.2f}',
    save_top_k=3,           # 保留最好的3个检查点
    monitor='val_loss',
    save_last=True,         # 保存最后一个检查点
    save_on_train_epoch_end=True,
)

# 保存模型时包含完整状态
checkpoint = {
    'epoch': epoch,
    'global_step': global_step,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'lr_scheduler_state_dict': scheduler.state_dict(),
    'best_metric': best_metric,
}
torch.save(checkpoint, f'checkpoints/checkpoint-{epoch}.pth')

2. 模型分发

# 使用 SafeTensors 格式分发
model.save_pretrained(
    output_dir,
    safe_serialization=True,  # 使用 SafeTensors 格式
    max_shard_size='5GB',     # 分片大小限制
)

# 创建模型卡片
from huggingface_hf_api import HfApi
api = HfApi()
api.upload_folder(
    folder_path=output_dir,
    repo_id="username/model-name",
    repo_type="model",
)

3. 模型优化

# ONNX 模型优化
import onnx
from onnxsim import simplify

# 简化模型
model = onnx.load('model.onnx')
model_simp, check = simplify(model)
assert check, "简化失败"
onnx.save(model_simp, 'model_simplified.onnx')

# 量化模型
from onnxruntime.quantization import quantize_dynamic, QuantType
quantize_dynamic(
    'model_simplified.onnx',
    'model_int8.onnx',
    weight_type=QuantType.QInt8
)

4. 版本控制

# 使用 DVC (Data Version Control) 管理大模型
pip install dvc

# 初始化 DVC
dvc init

# 添加模型文件
dvc add models/model.safetensors

# 提交更改
git add models/model.safetensors.dvc .gitignore
git commit -m "Add model v1.0"

# 存储到远程
dvc remote add -d myremote s3://my-bucket/models
dvc push

常见问题

Q1: SafeTensors 和 PyTorch 格式有什么区别?

A:

  • 安全性:SafeTensors 不使用 pickle,避免了代码执行风险
  • 速度:SafeTensors 加载速度比 PyTorch 快 3-10 倍
  • 大小:SafeTensors 文件通常比 PyTorch 小
  • 兼容性:SafeTensors 支持懒加载,PyTorch 不支持

Q2: 如何选择 GGUF 的量化级别?

A:

  • 高质量需求:Q8_0 或 F16
  • 平衡选择:Q4_K_M(推荐)
  • 资源受限:Q2_K 或 Q3_K_M
  • 测试建议:从 Q4_K_M 开始,根据质量和性能调整

Q3: ONNX 模型转换失败怎么办?

A:

  • 检查 PyTorch 版本和 ONNX 版本兼容性
  • 尝试降低 opset_version
  • 使用 torch.onnx.exportverbose=True 查看详细错误
  • 检查是否有不支持的算子
  • 使用 onnx-simplifier 简化模型

Q4: 如何验证模型转换的正确性?

A:

import torch
import numpy as np

# 比较原始模型和转换模型的输出
def verify_conversion(original_model, converted_model, input_data):
    original_model.eval()
    converted_model.eval()
    
    with torch.no_grad():
        original_output = original_model(input_data)
        converted_output = converted_model(input_data)
    
    # 计算差异
    diff = torch.abs(original_output - converted_output)
    max_diff = diff.max().item()
    mean_diff = diff.mean().item()
    
    print(f"最大差异: {max_diff}")
    print(f"平均差异: {mean_diff}")
    
    # 判断是否在可接受范围内
    assert max_diff < 1e-3, "转换验证失败"
    print("转换验证通过")

Q5: 如何处理大模型的分片文件?

A:

from safetensors import safe_open
import torch

def load_sharded_model(model_dir, index_file='model.safetensors.index.json'):
    import json
    
    # 读取索引文件
    with open(f'{model_dir}/{index_file}', 'r') as f:
        index = json.load(f)
    
    # 获取所有分片文件
    shard_files = set(index['weight_map'].values())
    
    # 加载所有分片
    state_dict = {}
    for shard_file in shard_files:
        with safe_open(f'{model_dir}/{shard_file}', framework='pt', device='cpu') as f:
            for key in f.keys():
                state_dict[key] = f.get_tensor(key)
    
    return state_dict

Q6: 如何加密模型权重文件?

A:

from cryptography.fernet import Fernet
import pickle

# 生成密钥
key = Fernet.generate_key()
cipher = Fernet(key)

# 加密模型
def encrypt_model(model_path, encrypted_path, key):
    with open(model_path, 'rb') as f:
        data = f.read()
    
    encrypted_data = cipher.encrypt(data)
    
    with open(encrypted_path, 'wb') as f:
        f.write(encrypted_data)

# 解密模型
def decrypt_model(encrypted_path, key):
    cipher = Fernet(key)
    
    with open(encrypted_path, 'rb') as f:
        encrypted_data = f.read()
    
    decrypted_data = cipher.decrypt(encrypted_data)
    state_dict = pickle.loads(decrypted_data)
    
    return state_dict

文档生成时间:2026-06-11

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐