【模型序列化】pkl 的问题与格式选型
为什么 pkl 不够用你把iris_model.pkl拷到另一台服务器上大概率会遇到这种情况生产服务器的 scikit-learn 版本和你本地不一样pkl 文件加载失败。 或者推理太慢想换 TensorRT 加速但 TensorRT 不认识你的 pkl 文件。 这就是序列化问题如果选错格式后面的优化全是空谈。一、背景序列化是部署的第一道门 模型序列化Model Serialization解决一个核心问题把内存里的模型对象变成一个可移植的文件。这个文件要能在另一台机器、另一个时间、另一个框架里被正确还原。可移植说起来简单实际上有三个维度的兼容性需要考量版本兼容用 sklearn 0.24 保存的模型能用 1.2 加载吗框架兼容PyTorch 训练的模型能用 TensorFlow Serving 部署吗硬件兼容CPU 上训练的模型能高效跑在 NVIDIA GPU 上吗不同序列化方案在这三个维度上有不同的权衡。二、基础知识格式演进的三代2.1 第一代框架原生格式 最简单直接用框架自带的序列化工具# sklearnjoblib.dump(model,model.pkl)modeljoblib.load(model.pkl)# PyTorch只存权重torch.save(model.state_dict(),weights.pt)# PyTorch存整个模型依赖代码结构torch.save(model,model.pt)优点简单零学习成本。缺点强依赖框架版本跨框架不通无法被高性能推理引擎直接加载。 Picklepkl尤其危险它序列化的是 Python 对象加载时会执行任意代码既有安全风险也有版本绑定问题。2.2 第二代计算图格式 PyTorch 和 TensorFlow 各自有冻结计算图的格式TorchScript.pt或.torchscript把 PyTorch 模型编译成静态图不依赖原始 Python 代码# PyTorch → TorchScriptmodel.eval()scriptedtorch.jit.script(model)# 编译为静态图scripted.save(model.torchscript)# 保存不再依赖原始类定义# 加载时不需要 model 的类定义loadedtorch.jit.load(model.torchscript)outputloaded(input_tensor)SavedModelTFTensorFlow 2.x 的标准格式包含计算图和变量# TensorFlow → SavedModeltf.saved_model.save(model,saved_model/)# 导出整个目录# 加载loadedtf.saved_model.load(saved_model/)outputloaded(input_tensor) 这一代解决了版本绑定问题加载时不再需要原始的模型类定义序列化的是计算图本身而不是 Python 对象。但还是框架内的方案TorchScript 只能被 PyTorch 生态加载SavedModel 只能被 TensorFlow 生态加载不能跨框架。2.3 第三代ONNX跨框架标准ONNXOpen Neural Network Exchange是微软、Facebook、AMD 等共同推出的开放格式定义了一套与框架无关的算子集。 训练框架和推理引擎之间ONNX 充当通用翻译层你用 PyTorch 训练导出 ONNX然后用任意支持 ONNX 的引擎部署完全解耦。三、总结Pickle/pkl是原型阶段的工具不适合生产版本依赖强、安全风险高、跨框架不通序列化格式经历了三代演进框架原生 → 计算图格式 →ONNX 跨框架标准选格式的核心判断你需要版本兼容、框架兼容还是硬件兼容pkl 三个都不满足ONNX 三个都覆盖