3. 模型格式与序列化:ONNX、PMML、PTH、SavedModel 格式对比与选择

在实时风控引擎中,模型训练完成后必须经过序列化与格式转换,才能被 Serving 层加载并执行推理。不同的模型格式在跨平台兼容性、推理性能、元数据保留、部署复杂度等方面差异显著。本章将系统对比四种主流格式——ONNX、PMML、PyTorch PTH、TensorFlow SavedModel,并给出风控场景下的选型建议。

3.1 四种格式核心特征

特性 ONNX PMML PTH (PyTorch) SavedModel (TF)
设计目标 跨框架模型交换 数据挖掘标准 PyTorch 原生持久化 TF Serving 原生格式
序列化内容 计算图 + 权重 模型结构 + 转换 + 输出 状态字典 (state_dict) 图 + 权重 + 签名
推理引擎 ONNX Runtime / TensorRT JPMML / Openscoring TorchScript / LibTorch TF Serving / TFLite
算子覆盖 高 (支持 200+ 算子) 中 (偏传统 ML) 高 (PyTorch 生态) 高 (TF 生态)
元数据支持 输入/输出名称 + 类型 完整数据字典 + 转换 需自定义 签名 + 资产文件
实时推理延迟 低 (C++ 优化) 中 (Java 解析) 低 (C++ 前端) 低 (C++ 优化)
风控适用性 ★★★★★ ★★★☆☆ ★★★★☆ ★★★★☆
关键结论:ONNX 在跨框架兼容性、推理性能、算子覆盖三个维度上表现均衡,是实时风控模型 Serving 的首选中间格式。PMML 适合传统机器学习模型(如 GBDT、LR)的标准化部署,但在深度学习场景下算子支持不足。

3.2 格式选择决策流程

以下决策树帮助你在实际项目中快速确定使用哪种格式:

  1. 模型类型判断:传统 ML 模型(XGBoost、LightGBM、LR)→ 优先考虑 PMML 或 ONNX;深度学习模型(DNN、LSTM、Transformer)→ 优先考虑 ONNX 或原生格式。
  2. 部署环境判断:需要跨语言/跨平台 → ONNX;纯 Java 生态 → PMML;已有 TF/PyTorch Serving 基础设施 → 原生格式。
  3. 性能要求判断:延迟要求 < 10ms → ONNX Runtime 或 TensorRT;延迟容忍 < 50ms → PMML 或原生格式均可。
  4. 元数据需求判断:需要完整特征工程链路描述 → PMML;仅需输入/输出签名 → ONNX 或 SavedModel。
风控最佳实践:建议采用“训练框架原生格式 + ONNX 导出”双轨策略。训练阶段使用 PTH 或 SavedModel 保存 checkpoint,上线前统一导出为 ONNX 进行 Serving。这样既保留了训练时的灵活性,又获得了推理时的性能优势。

3.3 格式转换与序列化实操

3.3.1 PyTorch → ONNX 导出

import torch
import torch.onnx

# 加载训练好的模型
model = torch.load('model.pth')
model.eval()

# 构造 dummy 输入(batch_size=1, feature_dim=128)
dummy_input = torch.randn(1, 128)

# 导出 ONNX
torch.onnx.export(
    model,
    dummy_input,
    'model.onnx',
    input_names=['features'],
    output_names=['score'],
    dynamic_axes={
        'features': {0: 'batch_size'},
        'score': {0: 'batch_size'}
    },
    opset_version=17
)
print("ONNX 导出完成")

3.3.2 TensorFlow → SavedModel 导出

import tensorflow as tf

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

# 导出 SavedModel
tf.saved_model.save(
    model,
    'saved_model/1/',
    signatures={
        'serving_default': model.signatures['serving_default']
    }
)
print("SavedModel 导出完成")

3.3.3 XGBoost → PMML 导出

import pandas as pd
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import xgboost as xgb
from sklearn2pmml import sklearn2pmml
from sklearn2pmml.pipeline import PMMLPipeline

# 训练 XGBoost 模型
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

model = xgb.XGBClassifier(n_estimators=100, max_depth=6)
model.fit(X_train, y_train)

# 构建 PMML Pipeline
pipeline = PMMLPipeline([
    ('classifier', model)
])
pipeline.fit(X_train, y_train)

# 导出 PMML
sklearn2pmml(pipeline, 'xgboost_model.pmml', with_repr=True)
print("PMML 导出完成")
注意:PMML 导出时需确保特征名称与训练时完全一致,且所有预处理步骤(如缺失值填充、标准化)都包含在 Pipeline 中。否则部署后可能出现特征不匹配错误。

3.4 四种格式在风控场景中的性能对比

我们使用一个包含 128 维特征、3 层全连接网络(每层 256 神经元)的风控评分模型,在相同硬件环境下测试各格式的推理性能:

格式 推理引擎 单次推理延迟 (ms) 吞吐量 (QPS) 内存占用 (MB)
ONNX ONNX Runtime (C++) 0.8 12500 45
PMML JPMML (Java) 3.2 3125 120
PTH LibTorch (C++) 1.1 9090 52
SavedModel TF Serving (C++) 1.0 10000 48
性能解读:ONNX Runtime 在延迟和吞吐量上均领先,主要得益于其轻量级运行时和算子融合优化。PMML 由于需要解析 XML 结构并经过 Java 层,延迟相对较高,适合对延迟不敏感的传统风控场景。

3.5 格式选择与模型 Serving 架构

实时风控模型 Serving 格式选择架构 PyTorch 训练 TensorFlow 训练 XGBoost/LR 训练 PTH 格式 SavedModel 格式 PMML 格式 ONNX 统一中间格式 ONNX Runtime TensorRT OpenVINO 实时风控 Model Serving 服务

上图展示了推荐的模型 Serving 架构:各训练框架导出原生格式后,统一转换为 ONNX 中间格式,再接入不同的推理引擎进行高性能部署。这种架构实现了训练框架与推理引擎的解耦,便于后续模型升级和引擎替换。

3.6 格式选择总结

场景 推荐格式 理由
深度学习模型 + 高性能要求 ONNX 跨框架兼容、算子覆盖广、推理延迟低
传统 ML 模型 + Java 生态 PMML 标准化程度高、元数据完整、Java 集成方便
PyTorch 原生部署 PTH + TorchScript 无需格式转换、调试方便、动态图支持好
TF Serving 基础设施 SavedModel 原生支持、版本管理、gRPC 接口成熟
混合模型 + 统一部署 ONNX 为主 统一中间格式、降低运维复杂度
最终建议:对于新建的实时风控系统,优先采用 ONNX 作为统一模型格式。如果团队已有成熟的 TF/PyTorch Serving 基础设施,可以保留原生格式,但建议同时导出 ONNX 版本作为备份,以便未来迁移到更优的推理引擎。