3. 模型导出与序列化
模型训练完成后,必须将其从内存中的对象转换为可持久化存储、可跨环境传输、可被高性能推理引擎加载的格式。本章围绕四种主流序列化方案展开:Python pickle/joblib、ONNX、TensorFlow SavedModel 与 PyTorch TorchScript,并对比其适用场景与优势。
3.1 Python pickle / joblib:快速原型与轻量部署
对于基于 scikit-learn 构建的信用评分模型(逻辑回归、XGBoost、LightGBM 等),pickle 与 joblib 是最直接的序列化方式。
| 特性 | pickle | joblib |
|---|---|---|
| 适用对象 | 任意 Python 对象 | 大型 NumPy 数组、估算器 |
| 压缩支持 | 需手动包装 | 内置 compress 参数 |
| 序列化速度 | 中等 | 对大数组更快 |
| 跨版本兼容 | 弱(Python 版本敏感) | 同 pickle 限制 |
| 推荐场景 | 小型模型、临时存储 | 生产级 scikit-learn 模型 |
⚠️ 安全警告: 切勿从不可信来源加载 pickle/joblib 文件,反序列化时会执行任意代码。生产环境建议对模型文件做签名校验。
# 使用 joblib 保存与加载 scikit-learn 模型
from sklearn.ensemble import GradientBoostingClassifier
import joblib
model = GradientBoostingClassifier(n_estimators=100)
model.fit(X_train, y_train)
# 保存(带压缩)
joblib.dump(model, 'credit_score_model.pkl', compress=3)
# 加载
loaded_model = joblib.load('credit_score_model.pkl')
predictions = loaded_model.predict(X_test)
3.2 ONNX 格式:跨框架互操作与推理优化
ONNX(Open Neural Network Exchange)定义了一套统一的算子集与计算图表示,使模型可以在不同框架(PyTorch → ONNX → TensorRT / ONNX Runtime)之间迁移。
核心优势: ONNX Runtime 提供图优化、算子融合、量化推理,在 CPU/GPU 上均可获得显著加速,尤其适合信用评分场景下的高吞吐批量评分。
# 将 PyTorch 模型导出为 ONNX
import torch
import torch.onnx
class CreditScoreNet(torch.nn.Module):
def __init__(self):
super().__init__()
self.fc = torch.nn.Linear(20, 1)
def forward(self, x):
return torch.sigmoid(self.fc(x))
model = CreditScoreNet()
model.eval()
dummy_input = torch.randn(1, 20)
torch.onnx.export(
model,
dummy_input,
"credit_score.onnx",
input_names=['features'],
output_names=['score'],
dynamic_axes={'features': {0: 'batch_size'}, 'score': {0: 'batch_size'}}
)
3.3 TensorFlow SavedModel:完整服务封装
SavedModel 是 TensorFlow 官方推荐的导出格式,包含计算图(GraphDef)、权重(Checkpoint)与签名(SignatureDef),可直接被 TensorFlow Serving 加载。
# 导出 TensorFlow SavedModel
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu', input_shape=(20,)),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy')
model.fit(X_train, y_train, epochs=10)
# 导出
model.save('credit_score_savedmodel', save_format='tf')
# 使用 tf.saved_model.save 更细粒度控制
@tf.function(input_signature=[tf.TensorSpec(shape=[None, 20], dtype=tf.float32)])
def predict_fn(x):
return model(x)
tf.saved_model.save(model, 'credit_score_savedmodel_v2', signatures=predict_fn)
版本兼容: SavedModel 的序列化格式与 TensorFlow 主版本强绑定。使用 TF2.x 导出的模型无法被 TF1.x 加载。建议在 Docker 容器中固定 TensorFlow Serving 版本。
3.4 PyTorch TorchScript:生产级图模式推理
TorchScript 将 PyTorch 动态图转换为静态计算图,支持序列化、优化与无 Python 依赖的 C++ 运行时加载。
| 导出方式 | 方法 | 适用场景 |
|---|---|---|
| Tracing | torch.jit.trace |
模型不含控制流(if/for 依赖数据) |
| Scripting | torch.jit.script |
模型包含动态控制流 |
# TorchScript 导出(Tracing 方式)
import torch
class ScoringModel(torch.nn.Module):
def __init__(self):
super().__init__()
self.linear = torch.nn.Linear(20, 1)
def forward(self, x):
return torch.sigmoid(self.linear(x))
model = ScoringModel()
model.eval()
# Tracing
dummy = torch.randn(1, 20)
traced_model = torch.jit.trace(model, dummy)
traced_model.save('credit_score_traced.pt')
# Scripting(支持条件分支)
@torch.jit.script
def scored_fn(x):
score = torch.sigmoid(torch.mm(x, torch.randn(20, 1)))
if score > 0.5:
return score, torch.tensor(1)
else:
return score, torch.tensor(0)
torch.jit.save(scored_fn, 'credit_score_scripted.pt')
3.5 序列化格式选型总结
信用评分模型部署推荐路径:
1. 开发阶段使用 joblib 快速迭代。
2. 需要跨平台或 GPU 加速时,将模型转换为 ONNX 格式,配合 ONNX Runtime 部署。
3. 若已有 TensorFlow/PyTorch 基础设施,分别使用 SavedModel 或 TorchScript 获得最佳生态集成。
1. 开发阶段使用 joblib 快速迭代。
2. 需要跨平台或 GPU 加速时,将模型转换为 ONNX 格式,配合 ONNX Runtime 部署。
3. 若已有 TensorFlow/PyTorch 基础设施,分别使用 SavedModel 或 TorchScript 获得最佳生态集成。
无论选择哪种格式,都应在导出后执行 一致性验证:加载序列化模型,对同一批样本计算输出,确保与原模型输出的差异在浮点误差范围内(通常 < 1e-5)。