读数据自助服务实践指南:数据开放与洞察提效18模型部署服务
1.1. 编写一次性脚本来部署模型并不困难
1.2. 针对模型训练类型(在线与离线)、模型推理类型(在线与离线)、模型格式(PAML、PFA、ONNX等)、终端类型(Web服务、IoT、嵌入式浏览器等)以及性能要求(由预测/秒和延迟定义)的不同组合,管理这些脚本非常困难
1.2.1. 考虑到大量的组合,单个团队使用的一次性脚本很快就变成一种技术债,并且很难管理
1.2.2. 组合的数量越多,就越需要使用模型部署服务实现自动化
1.3. 痛点
1.3.1. 用于部署模型的非标准化自定义脚本需要支持一系列机器学习模型类型、机器学习库和工具、模型格式和部署终端(如物联网(IoT)设备、移动设备、浏览器和Web API)
1.3.2. 一旦部署,就没有标准化的框架来监控模型的性能
1.3.2.1. 考虑到模型托管的多租户环境,监控可以确保模型的自动扩展和与其他模型的性能隔离
1.3.3. 在数据分布随时间推移而偏移的情况下确保模型的预测准确度
1.4. 理想情况下,自助模型部署服务应该可以将经过训练的模型从任何机器学习库部署到任何模型格式中,以便在任何终端进行部署
1.5. 该服务自动监控在线推理的质量,并向数据用户发出告警
1.6. 例子
1.6.1. Facebook的FBLearner
1.6.2. 谷歌的TensorFlow Extended
1.6.3. Airbnb的Bighead
1.6.4. Uber的Michelangelo
1.6.5. Databricks的MLflow
2. 路线图2.1. 模型部署可以被视为一个一次性或连续的过程,按照计划进行
2.2. 部署的模型服务于多个客户端,并自动扩展从而及时提供预测服务
2.3. 生产中的模型部署
2.3.1. 训练结束后,模型将部署到生产中,目标是确保模型能在生产中可靠地运行,类似于在训练期间的运行方式
2.3.2. 离线模型则按计划调用,然后推理被写回数据湖中,以供下游的批处理作业使用,或由用户直接通过查询工具访问
2.3.3. 通过建立管道以获取模型推理所需的特征,数据用户需要对预期吞吐量(每秒预测)和响应时间延迟有一个大致的估计
2.3.4. 设置监控以跟踪指标的准确度并根据阈值生成告警
2.3.5. 如今,由于缺乏标准化,数据用户依赖工程团队来管理生产中的模型部署
2.4. 模型维护与升级
2.4.1. 定期对模型进行再训练,以纳入新的标签数据
2.4.2. 对于连续的在线训练,模型会在每个新的数据记录上更新
2.4.3. A/B测试比较同一功能的不同版本的性能,同时监控点击率(CTR)、转化率等高级指标
2.4.4. 分区模型以分层方式组织
2.4.5. 模型升级和A/B测试的流程是非标准的,并由不同的团队管理
3. 最小化部署耗时3.1. 部署编排
3.1.1. 包括在生产终端上部署模型,终端包括独立的Web服务、嵌入应用程序内的模型、物联网边缘设备上的模型等
3.1.2. 管理用于金丝雀部署和A/B测试的多个模型需要通过脚本来分割模型之间的流量
3.1.3. 升级模型需要以无中断的方式进行编排,以便应用程序请求不受影响
3.1.4. 一个工具能提供所有功能并不重要,重要的是要有一套能够处理工作流所有步骤的集成工具
3.2. 性能扩展
3.2.1. 包括分配适当数量的资源,以适应模型预测不断变化的负载
3.2.2. 检测减速需要考虑模型类型、输入特征基数、在线训练数据大小和其他几个因素的阈值
3.2.3. 为了处理不断变化的需求,模型需要扩容和缩容
3.2.3.1. 考虑到模型是无状态的,可以启动额外的实例来管理增加的负载,从而允许水平扩展
3.2.3.2. 对于独立服务部署,模型通常与其他模型一起部署在容器上
3.2.4. 对于独立服务部署,模型通常与其他模型一起部署在容器上
3.2.5. 为了利用GPU等高级硬件,需要对发送到模型的请求进行批处理,以在延迟范围内提高吞吐量
3.2.6. 大多数任务都是以一种即席的方式处理的,既可以是手动的,也可以是半自动的
3.3. 偏移监控
3.3.1. 包括持续验证受特征分布值变化、语义标签变化、推理数据段分布等影响的推理的正确性
3.3.2. 挑战是需要复杂的工程技术将实际结果与预测结果结合起来
3.3.3. 跟踪特征值分布和推理输入历史是即席的,通常根据数据用户的工程技能而变化
4. 定义需求4.1. 给定一个经过训练的模型,部署服务将自动执行模型到终端的部署、扩展和生命周期管理
4.2. 数据用户应该能够自助服务,而无须依赖工程团队或有技术债的即席查询脚本
4.3. 编排
4.3.1. 模型基本上可以视为算法和配置细节的组合,可以用来根据一组新的输入数据进行新的预测
4.3.2. 部署终端
4.3.2.1. 离线部署按计划生成批处理推理
4.3.2.2. 在线部署则近实时地响应应用程序预测请求(可单独发送或批处理发送)
4.3.3. 打包
4.3.3.1. 嵌入式模型
4.3.3.1.1. 模型在消费应用程序(consuming application)中构建和打包,模型代码作为应用程序代码的一部分被无缝管理
4.3.3.1.2. 此模式的一个变体是库部署,其中模型作为库嵌入应用程序代码中
4.3.3.2. 作为独立服务部署的模型
4.3.3.2.1. 模型被打包到一个服务中,该服务可以独立于消费应用程序进行部署,因此允许独立发布模型的更新
4.3.3.3. 发布/订阅模型
4.3.3.3.1. 模型可以被独立地处理和发布,但是消费应用程序接收来自数据流的推理,而不是API调用
4.3.4. 模型格式
4.3.4.1. 模型需要序列化成多种不同的格式来实现互操作性
4.3.4.2. 模型格式可以分为语言无关的交换格式和语言相关的交换格式
4.3.4.3. PMML
4.3.4.3.1. 预测模型标记语言(Predictive Model Markup Language,PMML)
4.3.4.3.2. 最初被认为是一种“事实上的标准”,它提供了一种共享模型(如神经网络、支持向量机(SVM)、朴素贝叶斯分类器等)的方法
4.3.4.3.3. 基于XML的,鉴于XML不再被广泛使用,因此PMML在深度学习领域并不受欢迎
4.3.4.3.4. 继任者—可移植格式分析(PFA)基于Avro格式,并由同一个组织开发
4.3.4.4. ONNX
4.3.4.4.1. Facebook和微软联手创建了ONNX(开放神经网络交换),它使用谷歌的协议缓冲区作为一种可互操作的格式
4.3.4.4.2. 专注于推理所需的功能,定义了一个可扩展的计算图模型,以及内置运算符和标准数据类型的定义
4.3.4.4.3. ONNX受到广泛支持,可以在许多框架、工具和硬件中找到它的身影
4.3.4.5. 语言相关的交换格式类别中的常用格式
4.3.4.5.1. Spark MLWritable是Spark附带的标准型号存储格式,仅限于在Spark内使用
4.3.4.5.2. MLeap为导出和导入Spark、scikit-learn和TensorFlow模型提供了一种通用的序列化格式
4.3.4.5.3. Pickle是一个标准的Python序列化库,用于将scikit-learn和其他机器学习库中的模型保存到文件中
4.3.5. 模型部署场景
4.3.5.1. 无中断升级
4.3.5.1.1. 使用最新的版本更新已部署的模型,不影响依赖模型的应用程序
4.3.5.1.2. 尤其适用于打包为独立服务的模型
4.3.5.2. 影子模式部署
4.3.5.2.1. 此模式捕获了生产中新模型的输入和推理,而不实际为这些推理提供服务
4.3.5.2.2. 如果检测到bug,就可以对结果进行分析,且不会产生重大后果
4.3.5.3. 金丝雀模型部署
4.3.5.3.1. 金丝雀发布将新模型应用于一小部分服务请求
4.3.5.3.2. 它需要成熟的部署工具,但可以最小化当错误发生时所产生的后果
4.3.5.3.3. 典型的方法是使用切换Web服务和两个单独模型终端进行金丝雀测试
4.3.5.4. A/B测试部署
4.3.5.4.1. 不同的用户组可以使用不同的模型
4.3.5.4.2. 支持A/B测试需要编排服务的粘性,即构建用户存储桶(bucket),将它们粘贴到不同的终端,并记录各自的结果
4.3.5.4.3. 一个关键要求是能够将多个模型部署到同一个终端
4.4. 模型扩展与性能
4.4.1. 计划部署多少个模型
4.4.2. 这些模型中离线与在线的比例是多少
4.4.3. 模型需要支持的每秒预测的最大预期吞吐量是多少
4.4.4. 是否需要实时提供服务的在线模型
4.4.5. 最大可容忍的响应时间延迟有多大
4.4.6. 模型在反映新的数据样本方面的新鲜度如何
4.4.7. 对于模型的在线训练,将使用的大概数据量是多少
4.4.8. 模型预计多久更新一次
4.4.9. 如果部署在受监管的环境中,审计请求服务所需的日志记录级别是多少
4.5. 偏移验证
4.5.1. 数据偏移
4.5.1.1. 在数据偏移的情况下,数据会随着时间的推移而演变,可能会引入以前看不到的变体和新的数据类别,但对之前标记的数据没有影响
4.5.2. 概念偏移
4.5.2.1. 在概念偏移的情况下,数据的解释会随着时间而变化,即使数据的总体分布没有变化
4.5.3. 根据不同的应用程序,可能需要检测数据偏移和概念偏移
4.6. 非功能性需求
4.6.1. 鲁棒性
4.6.1.1. 服务需要能够从故障中恢复,并优雅地处理部署过程中遇到的暂时性或永久性错误
4.6.2. 简单直观的可视化
4.6.2.1. 服务应该有一个自助用户界面,服务于具有不同程度工程专业知识的广泛数据用户
4.6.3. 可验证性
4.6.3.1. 服务应该可以测试和验证部署过程的正确性
5. 实现模式5.1. 通用部署模式
5.1.1. 部署使用不同编程平台和终端类型开发的模型类型
5.1.2. 通用部署模式标准化了数据用户部署模型的方法,而不局限于特定的编程工具或终端
5.1.3. 模型序列化
5.1.3.1. 模型被编译成单一的序列化格式,可以在不同的终端部署
5.1.3.2. 跨编程框架和部署的单一打包标准
5.1.3.3. 将模型的多种格式打包在一起,并视情况应用于终端
5.1.4. 模型识别
5.1.4.1. 金丝雀部署和A/B测试场景可以部署多个模型
5.1.4.2. 在部署时,模型由通用唯一标识符(UUID)和可选标签识别
5.1.4.3. 一个标签可以与一个或多个模型相关联,通常使用具有相同标签的最新模型
5.1.4.4. 对于在线模型,模型UUID用于标识将用于服务预测请求的模型
5.1.4.5. 对于离线模型,所有部署的模型都用于对每个批处理数据集进行评分,预测记录包含了用于结果过滤的模型UUID
5.1.5. 终端部署
5.1.5.1. 模型可以部署到不同类型的终端
5.1.5.2. 验证前步骤确保将模型推送到终端的准确性
5.1.5.3. 对于独立部署,可以同时将多个模型部署到给定的服务容器中,也可以将现有模型替换为预测容器,自动从磁盘加载新模型并开始处理预测请求
5.1.6. MLflow Model
5.1.6.1. 多种风格打包在一起
5.1.6.2. 定义了一个协议,允许我们以不同的风格保存模型,以便被不同的下游终端理解
5.1.7. TensorFlow Extended
5.1.7.1. 单一格式集成
5.1.7.2. 与编程环境集成,以生成可以部署在多个TFX终端中的模型
5.1.8. 通用部署模式的优势在于它的灵活性—构建一次,部署多次(类似于Java“一次编写,随处运行”的价值主张)
5.1.9. 该模式的缺点是在没有通用解决方案的情况下与多个编程库产生的集成成本
5.1.10. 对于数据用户处理使用各种库构建的异构模型并在不同终端上部署来说,该模式是必需的
5.2. 自动扩展部署模式
5.2.1. 上下扩展模型部署以确保SLA性能
5.2.2. 在部署之后,机器学习模型既要满足以每秒预测次数度量的吞吐量SLA,也要满足以TP95响应时间度量的预测延迟SLA
5.2.3. 与离线模型相比,在线模型的SLA要求更加严格
5.2.4. 自动扩展部署模式确保模型性能能够自动扩展,以适应不断变化的调用需求,并能够自动缩减以节省成本
5.2.5. 检测减速
5.2.5.1. 它持续度量模型性能并根据定义的阈值检测减速
5.2.5.2. 阈值因模型的复杂度而异
5.2.5.3. 在线模型的TP95延迟是毫秒级的,并且支持每秒十万次的预测
5.2.6. 定义自动扩展策略
5.2.6.1. 自动扩展策略会根据吞吐量或由减速检测触发时向上或向下调整服务模型实例的数量
5.2.6.2. 该策略定义了每个实例的目标吞吐量,并为每个生产变体的实例数量提供了上限和下限
5.2.6.3. 无论是在线模型还是离线模型,机器学习模型都是无状态的、易于扩展的
5.2.7. 隔离和批处理
5.2.7.1. 模型部署在多租户环境中
5.2.7.2. 使服务器的单个实例同时服务于多个机器学习模型可能会导致跨模型干扰,并且需要模型隔离,以便一个模型的性能特性对其他模型的影响最小
5.2.7.3. 通常是通过为模型单独配置专用线程池来实现的
5.2.8. 优势在于它提供了性能和成本的最佳组合
5.2.9. 该模式的缺点是在检测到饱和时,需要时间来启动和扩展模型性能
5.2.10. 对于特征存储是扩展瓶颈的场景,该模式无济于事
5.2.11. 该模式可以自动处理性能问题,否则需要数据用户在生产中花费大量时间进行监控和配置
5.3. 模型偏移跟踪模式
5.3.1. 验证模型预测的准确度,以便在问题影响到应用程序的用户之前主动检测问题
5.3.2. 模型偏移跟踪模式确保部署的模型正常工作
5.3.2.1. 第一是机器学习模型对于不同范围特征值的准确性
5.3.2.2. 第二是跟踪预测值的历史分布,也就是说,当模型预测输入特征的相似值较高或较低时,会检测趋势
5.3.2.3. 第三,由于训练数据分布、数据管道代码和配置、模型算法和模型配置参数的变化,在重新训练之后,模型行为可能会发生变化
5.3.3. 数据分发和结果监控
5.3.3.1. 监控模型特征的分布变化
5.3.3.2. 假设当模型被要求对不属于训练集的新数据进行预测时,模型性能会发生变化
5.3.4. 模型审计
5.3.4.1. 捕获与每个模型推理相关的配置和执行日志
5.3.4.2. 所使用的指标应该与问题相关,而且合理定义损失函数是模型优化的基础