news 2026/7/20 19:04:01

现代主流/安全优化格式(新生态)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
现代主流/安全优化格式(新生态)

safetensors(Hugging Face主导)
背景:目前AI绘画(Stable Diffusion、ComfyUI)和主流大模型最推荐的格式。

详细说明:

核心特点:100%安全,它只包含纯粹的张量数据(模型权重)和一小段描述结构的JSON文本,没有任何可执行代码,完全免疫了传统格式的木马病毒风险。

性能:支持零拷贝(Zero-copy)和内存映射(mmap),加载速度极快,远超旧格式。

使用场景:SD/SDXL/Flux模型的Checkpoint、LoRA、ControlNet,以及大语言模型权重。

2 gguf
背景:替代了早期的ggml格式,是目前端侧/本地大模型(LLM)量化的绝对霸主。

详细说明:

核心特点:将模型的所有组件(权重、分词器、超参数、元数据)封装在单个文件内。它的扩展性极强,支持未来添加新的元数据而不破坏向后兼容性。

量化优势:专门为CPU/GPU混合推理优化,支持各种强度的量化(如Q4_K_M、Q8_0),能让几百亿参数的大模型在消费级显卡甚至手机、MacBook上流畅运行。

适用场景:Llama3、Gemma、Qwen等大语言模型的本地部署,最近ComfyUI也开始流行用GGUF格式来运行轻量化的Flux或SDXL模型。

1.2 传统开发/原生框架格式(多见于训练与研究)
这类格式通常伴随官方框架诞生,虽然灵活,但在跨平台部署或安全性上存在一定局限。

1 pth/pt(PyTorch)
详细说明:

核心特点:PyTorch框架的原生存储格式,它基于PyTorch的pickle模块进行序列化。

优缺点:它极其灵活,不仅能保存模型权重,还能把训练了一半的优化器状态(Optimizer)、Epoch轮数甚至网络结构代码一起存进去,是模型训练和微调的标配。但缺点是不安全,加载恶意的pth文件,可能会在电脑上自动执行破坏性代码。

适用场景:AI绘画中的早期特定模型(如部分ControlNet、ESRGAN放大算法模型)、PyTorch算法开发与训练。

2 ckpt(Checkpoint)
背景:这是Stable Diffusion早期(1.5时代)最常用的格式,本质上和pth一样也是基于pickle序列化。

详细说明:

核心特点:由于存在和pth一模一样的安全漏洞(可注入恶意脚本),目前在生图领域已经全面被safetensors淘汰。如果你在网上下载到老的ckpt权重,建议用工具转换成safetensors再使用。

3 h5/keras/pb (TensorFlow/Keras)
背景:Google生态(TensorFlow)下的主流格式。

详细说明:

核心特点:h5(HDF5)多用于保存Keras模型的权重或完整结构;pb(Protocol Buffers)则是TensorFlow用于生产端部署的图模型格式。

适用场景:传统计算机视觉(如某些老的人脸识别、目标检测算法)和工业级TensorFlow工业管线。

1.3 夸平台推理与硬件加速格式(生产端部署)
当模型训练完成后,为了让它在手机、网页、或者不同显卡(英伟达、AMD、Intel)上跑得飞快,通常会转换成以下格式。

1 onnx(Open Neural Network Exchange)
详细说明:

核心特点:“通用翻译官”,由微软、Meta等联合发起的开放标准。它把模型结构抽象成一张通用的计算图,让你可以把PyTorch训练的模型无缝转换到TensorFlow或其他推理引擎中运行。

适用场景:跨平台部署,比如你在ComfyUI里用到的某些WD14自动打标插件、LayerDiffusion背景分离模型,很多底层都在跑ONNX格式,因为它在CPU或非英伟达显卡上的兼容性极好。

2 engine(NVIDIA TensorRT)
背景:英伟达官方对自家显卡进行极致硬件加速的专用格式。

详细说明:

核心特点:速度榨干者,你必须在自己的显卡上,把onnx或safetensors现场“编译”成 engine 格式。它会根据你当前的显卡架构(如RTX 4090)进行剪枝、层融合和量化加速。

优缺点:速度达到物理极限(通常比原模型快 50%~100%)。但完全没有通用性,在4090上编译的engine文件拿到3080上是用不了的,甚至显卡驱动升级了都可能需要重新编译。

适用场景:追求极致生图速度的WebUI/ComfyUI TensorRT加速工作流,或工业级实时AI推理。

3 tflite/onnxruntime (移动端轻量化)
背景:tflite是TensorFlow Lite格式,专门给安卓、iOS手机或嵌入式设备(如树莓派)使用,做了极端的体积压缩和定点量化。

1.4 总结
在实际生产应用时,模型包含训练和部署两大关键环节,在训练环节模型可通过不同框架来实现,典型如PyTorch、TensorFlow等,由于框架的不同会产生不同格式的训练模型,而在部署环节由于硬件平台的不同又需要需要将不同格式的模型进行差异化修改,这种多到多的操作实施起来很繁琐。经过工业界和学术界数年的探索,模型部署有了一条流行的流水线:

image

如上图,为了让模型最终能够部署到某一环境上,开发者们可以使用任意一种深度学习框架来定义网络结构,并通过训练确定网络中的参数。之后,模型的结构和参数会被转换成一种只描述网络结构的中间表示,一些针对网络结构的优化会在中间表示上进行。最后,用面向硬件的高性能编程框架(如 CUDA,OpenCL)编写,能高效执行深度学习网络中算子的推理引擎会把中间表示转换成特定的文件格式,并在对应硬件平台上高效运行模型,比如中间表示ONNX转换支持华为芯片推理的OM文件。

2 模型导出及格式转换
2.1 导出pth格式模型
在上一篇文章中源码trainNN.py已经导出mnist_cnn.pth模型文件,PyTorch使用Python原生pickle序列化任意Python对象(模型、张量、字典、优化器、数字、自定义类等),这是pth文件的核心。pickle可执行任意代码,所以处于安全考虑不要加载来源不明的pt文件,Torch 2.0+提供weights_only=True安全加载模式,仅读取张量、禁止反序列化Python对象。新版PyTorch默认开启_use_new_zipfile_serialization=True,pth本质是一个zip压缩包;旧版本是纯二进制pickle文件,无压缩。对于新版pt文件可以直接用unzip model.pt解压查看内部文件。如解压后内容如下:

1 目录及文件解释
version:pickle序列化协议版本(pickle4/pickle5),用于版本兼容校验;

.format_version:Torch自定义ZIP存储格式版本,区分新旧存储结构,版本不匹配会直接加载失败;

.storage_alignment:张量二进制存储内存对齐字节数,GPU/CPU加载时用来对齐内存,提升张量读取速度,一般是1或64;

byteorder:存储硬件字节序,x86机器固定是little(小端序),用来解析.storage里的浮点/整数二进制;

data.pkl:整个模型的逻辑骨架,用pickle序列化了checkpoint /state_dict字典,但只存张量的「描述信息」,不存权重数字;

data:目录下存储张量权重二进制数据;

.data:该目录可能是特定场景(如torch.package/export)的残留或误生成;

2 data.pkl详解
直接用UE打开该二进制文件,内容如下:

image

在VS Code中安装PKL Viewer扩展,也一并打开该文件进行分析,内容如下:

复制代码
1 0: \x80 PROTO 2
2 2: c GLOBAL ‘collections OrderedDict’
3 27: q BINPUT 0
4 29: ) EMPTY_TUPLE
5 30: R REDUCE
6 31: q BINPUT 1
7 33: ( MARK
8 34: X BINUNICODE ‘features.0.weight’
9 56: q BINPUT 2
10 58: c GLOBAL ‘torch._utils _rebuild_tensor_v2’
11 91: q BINPUT 3
12 93: ( MARK
13 94: ( MARK
14 95: X BINUNICODE ‘storage’
15 107: q BINPUT 4
16 109: c GLOBAL ‘torch FloatStorage’
17 129: q BINPUT 5
18 131: X BINUNICODE ‘0’
19 137: q BINPUT 6
20 139: X BINUNICODE ‘cuda:0’
21 150: q BINPUT 7
22 152: M BININT2 288
23 155: t TUPLE (MARK at 94)
24 156: q BINPUT 8
25 158: Q BINPERSID
26 159: K BININT1 0
27 161: ( MARK
28 162: K BININT1 32
29 164: K BININT1 1
30 166: K BININT1 3
31 168: K BININT1 3
32 170: t TUPLE (MARK at 161)
33 171: q BINPUT 9
34 173: ( MARK
35 174: K BININT1 9
36 176: K BININT1 9
37 178: K BININT1 3
38 180: K BININT1 1
39 182: t TUPLE (MARK at 173)
40 183: q BINPUT 10
41 185: \x89 NEWFALSE
42 186: h BINGET 0
43 188: ) EMPTY_TUPLE
44 189: R REDUCE
45 190: q BINPUT 11
46 192: t TUPLE (MARK at 93)
47 193: q BINPUT 12
48 195: R REDUCE
49 196: q BINPUT 13
50 198: X BINUNICODE ‘features.0.bias’
51 218: q BINPUT 14
52 220: h BINGET 3
复制代码
最一开始是由Pickle规范(PEP307/PEP574)规定的0x80=PROTO头,声明了本次序列化使用的Pickle协议版本,0x80后紧跟1字节参数不是协议号本身,而是有对应的映射表:

image

随后的二进制流,可以通过Python标准库的pickletools模块,来查看包含所有协议版本的完整指令对照表,源码内带详细注释说明每个指令的作用,该文件路径可以通过以下代码获取:

python -c “import pickletools; print(pickletools.file)”
也可以通过如下文件直接打印出相应对照表:

printpkl.py
该文件运行输出内容如下:

image

接下来继续结合PKL Viewer解析结果进行分析,第2行内容等价于python代码collections.OrderedDict,把该类压入到Pickle栈,此时栈为[OrderedDict],第3行内容表示将OrderedDict类缓存到memo表,即memo[0] = class ‘collections.OrderedDict’,第4行将空元组压入栈,此时栈为[OrderedDict, ()],第5行REDUCE的含义是callable(args),对应的代码是弹出参数空元组及类并调用类实现OrderedDict(()),之后将结果及用OrderedDict类构造一个空实例对象压入到栈,此时栈为[ordereddict实例],第6行保存对象到memo表,即memo[1] = OrderedDict(),此时实际上已经得到:state_dict = OrderedDict(),此时在memo表中分别存储了类及其实例对象,后续可根据需要进行复用。接下来代码开始向OrderedDict插入元素,第7行向栈插入MARK分隔符(用于标记一个可变长度对象的开始位置),第8行向栈压入一个Unicode字符串对象,后续它将作为key,第9行将字符串存入到memo表,第10行向栈中压入_rebuild_tensor_v2重建函数,此时栈内容为[OrderedDict(), MARK33, ‘features.0.weight’, ‘_rebuild_tensor_v2’],第11行将其存入到memo表,第12,13行两次将MARK压入到栈,第14~22行依次将“storage”,FloatStorage,“0”,“cuda:0”,288入栈,最终由第23行的TUPLE和最近MARK94产生元组对象,并入栈,此时栈内容为[OrderedDict(), MARK33, ‘features.0.weight’, ‘_rebuild_tensor_v2’, MARK93, (“storage”, FloatStorage, “0”, “cuda:0”, 288)],第25行BINPERSID会调用unpickler.persistent_load(pid)来真正从data/0中的数据实现Storage对象,这里正是结构和数据分别存放的精华所在,例如,这里weight数据288个float数据,总大小为1152字节,和data/0文件大小正好对应上:

image

此时栈内容为:[OrderedDict(), MARK33, ‘features.0.weight’, ‘_rebuild_tensor_v2’, MARK93, FloatStorage(288)],而_rebuild_tensor_v2函数的参数定义如下:

复制代码
_rebuild_tensor_v2(
storage,
storage_offset,
size,
stride,
requires_grad,
backward_hooks
)
复制代码
可见第2个参数是storage_offset,就是说生成Tensor时不一定从Storage的开头开始,而是可以从指定storage_offset下标开始,这正好对应源码中第26行内容,这里向栈中压入下标0;接下来第2732行给出_rebuild_tensor_v2函数的第3个参数size=(32,1,3,3),即weight形状是32x1x3x3,正好是288个元素;再接下来第3439行给出函数第4个参数stride=(9, 9, 3, 1),即stride[0]=133=9,stride[1]=3*3=9,stride[2]=3,stride[3]=1;随后第41行向栈中压入False值,对应参数requires_grad,之后第42~44先通过BINGET 0将之前memo中预存的OrderedDict类压栈,然后再将空元组压栈,之后通过REDUCE实例化OrderedDict对象作为参数backward_hooks的值;最终通过第46行的和MARK93闭合产生参数元组,并在48行完成_rebuild_tensor_v2函数调用产生tensor实例。接下来过程类似,最终栈内容大致如下:

复制代码
OrderedDict()
MARK33
“features.0.weight”
Tensor(…)

“features.0.bias”
Tensor(…)

“features.1.weight”
Tensor(…)
复制代码
各个元素初始化完毕后最终会通过SETITEMS完成OrderedDict对象赋值,该指令会把最近MARK后的所

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 19:02:29

婚姻冷静期边界重构:物理、数字与情感隔离实践

1. 现代婚姻关系中的边界重构实践当一段婚姻走到冷静期这个特殊阶段,双方的行为模式往往最能反映关系的真实状态。最近在社交平台上引发热议的"冰箱清空、WiFi密码修改、宠物带走"事件,实际上展现了一套完整的个人边界重建方法论。作为经历过类…

作者头像 李华
网站建设 2026/7/20 18:55:41

ORM项目搭建

第一部分:Tortoise-ORM集成 ORM 的概念 ORM 全称是 Object-Relational Mapping(对象关系映射) 。它的核心思想是:用 Python 类来代表数据库中的表,用类的实例来代表表中的一行记录 同步 ORM vs 异步 ORM 对比如代码所示…

作者头像 李华
网站建设 2026/7/20 18:54:42

关于钢结构的几个简单而复杂的问题

关于钢结构的几个简单而复杂的问题 要详细解释这个问题牵涉的内容很多,简单的说可以这样理解: 荷载和材料强度的标准值是通过试验取得统计数据后,根据其概率分布,并结合工程经验,取其中的某一分位值(不一定是最大值)确定的。 设计值是在标准值的基础上乘以一个分项系…

作者头像 李华
网站建设 2026/7/20 18:54:42

Windows平台OpenClaw智能代理框架安装与配置指南

1. Windows平台OpenClaw安装概述OpenClaw作为一款跨平台的智能代理框架,在Windows系统上提供了三种主要部署方式:原生Windows Hub应用、PowerShell CLI安装以及WSL2环境部署。根据实际使用场景的不同,开发者可以选择最适合的安装方案&#xf…

作者头像 李华
网站建设 2026/7/20 18:54:33

2026年短视频学习笔记怎么做工具成本大横评,哪款好用谁才是王者

先按场景给答案 做短视频学习笔记,核心需求是把短视频语音转文字、提炼核心知识点、方便整理复用,本次针对职场人自我提升的短视频学习场景,横评了5款主流工具,没有绝对王者,只有场景适配:只需要基础转文字…

作者头像 李华