模型部署那些事

2,944 阅读12分钟

在工程服务开发中,“部署”的含义是将开发完成的服务或者软件投入到正式环境中使用的过程,包括了相关环境的配置、软件的安装、服务的测试等步骤。类似地,在机器学习和深度学习中,模型部署就是将训练好的模型进行持久化,然后运行服务加载模型,并对外提供RESTful或RPC等形式的服务接口。

如下图所示:

image

目前主流的部署方案有以下几种:

  1. HTTP服务器:在Python服务器上部署模型文件,对外提供http服务,好处是简洁快速,但是执行效率不高;

  2. C++/JAVA直接加载模型,不需要额外的接口服务,直接将预测代码和业务代码耦合在一起,好处是效率高,可以降低网络延迟,但是代码复杂且不易维护;

  3. Docker + Serving部署模型:将模型服务部署在Docker容器中,对外提供接口,好处是支持各种语言方便部署,且有较多的模型加速推理方案;

简单模型的部署

这里的简单模型主要是指线性模型、树模型等,通常我们在工作中主要是使用Sklearn、Xgboost、lightGBM和SparkML等框架进行模型的训练。

# sklearn模型保存方式一
import pickle
pickle.dump(file, output)

# sklearn模型保存方式二
from sklearn.externals import joblib
joblib.dump(model, 'model.pkl')

#xgboost模型保存
import xgboost as xgb
model = xgb.train(...)
model.save_model('model.bin')

#lightgbm模型保存
import lightgbm as lgb
model = lgb.LGBMClassifier(...)
model.fit(...)
model.save_model('model.txt')

#spark mllib模型保存
from pyspark.ml import Pipeline
from pyspark.ml.classification import RandomForestClassifier

model = RandomForestClassifier(...)
model.write().overwrite().save('{}/mdoel'.format(filename))

可见不同框架保存模型的文件格式是不同的,这就导致了在模型部署过程需要对不同的框架的模型文件进行个性化的适配。为了解决这一问题,同时满足跨平台部署和反复调用的需求,需要将模型保存为统一的文件格式。

PMML简介

预测模型标记语言PMML(Predictive Model Markup Language)是一套与平台和环境无关的模型表示语言,是目前表示机器学习模型的实际标准。

作为一个开放的成熟标准,PMML由数据挖掘组织DMG(Data Mining Group)开发和维护,经过十几年的发展,得到了广泛的应用,有超过30家厂商和开源项目(包括SAS,IBM SPSS,KNIME,RapidMiner等主流厂商)在它们的数据挖掘分析产品中支持并应用PMML。

image

PMML是一套基于XML的标准,通过 XML Schema 定义了使用的元素和属性,主要由以下核心部分组成:

  • 数据字典(Data Dictionary):描述输入数据。

  • 数据转换(Transformation Dictionary和Local Transformations):应用在输入数据字段上生成新的派生字段。

  • 模型定义(Model):每种模型类型有自己的定义。

  • 输出(Output):指定模型输出结果。

image

PMML优点

  • 平台无关性。PMML可以让模型部署环境脱离开发环境,实现跨平台部署。比如使用Python建立的模型,导出PMML后可以部署在Java生产环境中。

  • 互操作性。实现了兼容PMML的预测程序可以读取其他应用导出的标准PMML模型。

  • 广泛支持性。已取得30余家厂商和开源项目的支持,很多开源数据挖掘模型都可以转换成PMML。

  • 可读性。PMML模型是一个基于XML的文本文件,比二进制序列化文件更安全可靠。

TreeLite简介

TreeLite 能够将树模型编译优化为单独库,方便的用于模型部署。经过优化后可以将XGBoost模型的预测速度提高2-6倍。

image

如下图,黑色曲线为XGBoost在不同batch size下的吞吐量,红色曲线为XGBoost经过TreeLite编译后的吞吐量。

image

关于TreeLite的详细原理可以参考如下资料

相关论文:mlsys.org/Conferences…

项目链接:treelite.readthedocs.io/

TensorFlow模型部署

TensorFlow模型格式

TensorFlow 提供了统一模型导出格式 SavedModel,使用这一格式为中介,可以方便地在多种不同平台上镜像模型部署。同时基于历史原因,Keras的Sequential和Functional模式也有自有的模型导出格式即.h5格式,可以通过显性用 .h5 后缀,使得保存的模型格式为HDF5 。

# checkpoint格式模型保存和加载
ckpt = tf.train.Checkpoint(model)
ckpt.restore(file)

# savedmodel格式模型保存和加载
tf.saved_model.save(model,path)
model = tf.saved_model.load(path)

# H5格式模型保存和加载
tf.saved_model.save("model.h5")
model = tf.saved_model.load("model.h5")

Checkpoint格式模型可以帮助保存和恢复模型中参数的权值。而作为模型导出格式的 SavedModel 则更进一步,其包含了一个 TensorFlow 程序的完整信息:不仅包含参数的权值,还包含计算的流程(即计算图)。

当模型导出为 SavedModel 文件时,无需模型的源代码即可再次运行模型,这使得 SavedModel 尤其适用于模型的分享和部署。后文的 TensorFlow Serving(服务器端部署模型)、TensorFlow Lite(移动端部署模型)以及 TensorFlow.js 都会用到这一格式。

image

在Tensorflow 2.0中,推荐使用SavedModel进行模型的保存,所以keras默认导出格式是SavedModel,也可以通过显性使用 .h5 后缀,使得保存的模型格式为HDF5 。

Tensorflow模型推理

TensorFlow训练好的模型以Tensorflow原生方式保存成protobuf文件后可用许多方式部署运行,常见的推理方式有:

  1. 通过 TensorFlow for C++/Java接口,可以在C++或者Java中调用Tensorflow模型进行预测;

  2. 通过 Tensorflow-serving 可以加载模型后提供网络接口API服务,通过任意编程语言发送网络请求都可以获取模型预测结果;

  3. 通过 Tensorflow-lite 可以在移动和嵌入式设备上加载并运行TensorFlow模型;

  4. 通过 Tensorflow-js 可以用javascrip脚本加载模型并在浏览器中运行模型

TF-Serving

模型训练完毕后,最常见的部署方式就是在服务器上提供一个API,不考虑高并发和性能问题,其实配合Flask等python下的Web框架非常轻松实现。然而在服务密集,高并发等场景中并不适用。这个时候就需TF-Serving来进行加速。

image

TF-Serving是一个用于机器学习模型部署的高性能开源库,可以将训练完成的模型直接上线并提供服务;一个重要的特性是:支持热更新与模型版本自动管理,这意味着一旦部署成功,不需要再为线上服务担心,只需要关心线下的模型训练即可;

核心模块如下图所示:

  • Source用于管理本地的模型文件系统;

  • Source会对需要加载的模型创建一个Loader,Loder中会包含要加载模型的全部信息;

  • Source通知Manager有新的模型需要进行加载;

  • Manager通过版本管理策略Version Policy来确定哪些模型需要被下架,哪些模型需要被加载;

  • Manager在确认需要加载的模型是否符合加载策略,便通知Loader来加载最新的模型;

  • Client向服务器端请求模型结果,可以指定版本;

image

TF-Lite

TensorFlow Lite 是 TensorFlow 在移动和 IoT 等边缘设备端的解决方案,提供了 Java、Python 和 C++ API 库,可以运行在 Android、iOS 和 Raspberry Pi 等设备上。作为 TensorFlow 在边缘设备上的基础设施,TFLite 将会是愈发重要的角色。

image

目前 TFLite 只提供了推理功能,在服务器端进行训练后,经过如下简单处理即可部署到边缘设备上。

  1. 模型转换

  2. 边缘设备部署

image

TF-Lite转化后的模型为FlatBuffers格式。是谷歌为了游戏等高性能场景创建的序列化库,比ProtocolBuffer具有高性能和轻量性等优势,更加适合边缘设备的部署。

TF-JS

TensorFlow.js 是 TensorFlow 的 JavaScript 版本,支持 GPU 硬件加速,可以运行在 Node.js 或浏览器环境中。它不但支持完全基于 JavaScript 从头开发、训练和部署模型,也可以用来运行已有的 Python 版 TensorFlow 模型,或者基于现有的模型进行继续训练。

整体功能,只需要一个文件,几十行 HTML/JavaScript 即可实现。可以直接在浏览器中运行,完整的 HTML 代码如下:

image

Pytorch/Mxnet等模型部署

优化用于推理(或模型评分)的机器学习模型非常困难,因为需要调整模型和推理库,充分利用硬件功能。 如果想要在不同类型的平台(云/Edge、CPU/GPU 等)上获得最佳性能,实现起来会异常困难,因为每个平台都有不同的功能和特性。 如果模型来自需要在各种平台上运行的多种框架,会极大增加复杂性。 优化框架和硬件的所有不同组合非常耗时。 这就需要一种解决方案,在首选框架中训练一次后能在云或 Edge 上的任意位置运行。 此时 ONNX 便派上了用场。

image

ONNX简介

ONNX(Open Neural Network Exchange),开放神经网络交换,是微软和Facebook提出用来表示深度学习模型的开放格式。在实际业务中,可以使用Pytorch或者TensorFlow训练模型,导出成ONNX格式,然后再转换成目标设备上支撑的模型格式,比如TensorRT Engine、NCNN、MNN等格式。ONNX定义了一组和环境,平台均无关的标准格式,来增强各种AI模型的可交互性,开放性较强。

无论使用何种训练框架训练模型(比如TensorFlow/Pytorch/OneFlow/Paddle),在训练完毕后都可以将这些框架的模型统一转换为ONNX这种统一的格式进行存储。注意ONNX文件不仅仅存储了神经网络模型的权重,同时也存储了模型的结构信息以及网络中每一层的输入输出和一些其它的辅助信息。

ONNX定义了一组与环境和平台无关的标准格式,为AI模型的互操作性提供了基础,使AI模型可以在不同框架和环境下交互使用。硬件和软件厂商可以基于ONNX标准优化模型性能,让所有兼容ONNX标准的框架受益。

image

关于ONNX和PMML的区别:

  1. ONNX和PMML都是与平台和环境无关的模型表示标准,可以让模型部署脱离模型训练环境,简化了部署流程,加速模型快速上线到生产环境中。这两个标准都得到了各大厂商和框架的支持,具有广泛的应用;

  2. PMML是一个比较成熟的标准,在ONNX诞生之前,可以说是模型表示的实际标准,对传统数据挖掘模型有丰富的支持,但是因为PMML是基于老式的XML格式,使用文本格式来存储深度神经网络模型结构和参数会带来模型大小和性能的问题,目前该问题还没有一个完美的解决方案;

  3. ONNX作为一个新的标准,刚开始主要提供对深度神经网络模型的支持,解决模型在不同框架下互操作和交换的问题。目前通过ONNX-ML,ONNX已经可以支持传统非神经网络机器学习模型,但是目前模型类型还不够丰富;

TensorRT简介

TensorRT是一个高性能的深度学习推理(Inference)优化器,可以为深度学习应用提供低延迟、高吞吐率的部署推理。TensorRT可用于对超大规模数据中心、嵌入式平台或自动驾驶平台进行推理加速。

TensorRT现已能支持TensorFlow、Caffe、Mxnet、Pytorch等几乎所有的深度学习框架,将TensorRT和NVIDIA的GPU结合起来,能在几乎所有的框架中进行快速和高效的部署推理。

image

TensorRT是一个只有前向传播的深度学习框架,这个框架可以将 Caffe,TensorFlow的网络模型解析,然后与tensorRT中对应的层进行一一映射,把其他框架的模型统一全部 转换到tensorRT中,然后在tensorRT中可以针对NVIDIA自家GPU实施优化策略,并进行部署加速。

字节内部模型部署

Groot通过推理服务

Groot的特点如下:

  • 提供通用的GBDT的serving 服务,IDL未涉及业务属性,纯推理API接口;

  • 提供较高的GBDT Serving性能,基于C++最 新开发框架archon,业务通过公司统一RPC接口访问;

  • 推理服务托管于reckon平台, 支持全流程的打通: 数据流--> 模型训练 --> 模型发布 --> 在线推理服务;

  • Groot: 即GBDT通用推理服务;

详细介绍可以参考

Pilot通用推理服务

Pilot是一个通用的Inference Engine,它目前是以TensorFlow为Backend,不仅适用于WDL类计算轻量的模型,也可以用于CNN、BERT等重度计算模型。

对于Lagrange/Sail models,Pilot的上游为Marine,从头条OnlinePS获取instances fids的value,对每个slot做Sumpooling后,转化成slots和bias,作为Pilot的真正输入。

对于Lagrange lite models,Pilot目前没有特定上游,由用户自由开发Client,之后考虑开发一个Marine Lite的组件进行配合。

详细介绍可以参考

ByteNN移动端推理

ByteNN是一个致力于深度学习工程落地的高性能异构AI计算平台,支持跨平台的推理计算、端上训练能力,为公司内外AI业务提供统一的多平台快速AI部署能力,同时也提供模型压缩量化、模型转换、benchmark、性能诊断、模型加密等完备的周边工具链支持,覆盖CV、Audio、NLP等多个业务领域的常用算子,整体性能在业界持续保持领先。

详细介绍可以参考

参考文档

dmg.org/pmml/v4-1/G…

treelite.readthedocs.io/en/latest/

www.tensorflow.org/

onnx.ai/

developer.nvidia.com/tensorrt