MLOps极致细节:0. 背景介绍
此章节中,我们将介绍:MLOps的背景以及为什么使用MLOps。
文章目录
1 背景:AI的兴起与算力需求的指数级增加
1.1 时代背景与必然趋势
我们说,硬件和软件总是相辅相成的。过去二十年,我们亲身经历身边越来越多与AI相关的应用走进寻常百姓家,从SIRI语音助手,扫地机器人,机器人客服,到无人超市,无人驾驶,可见,机器翻译,图像处理,语音识别等等领域已经被越来越多的证明AI的价值。软件的成功离不开硬件。OpenAI的公开资料显示,对算力的指数级增长(18个月增长了35倍)远远超过摩尔定律(18个月增长2倍)。在这样的时代背景下,以AI为中心的应用程序也成为了必然的趋势。
那么问题就来了,如果说上上个时代,我们通过使用瀑布来开发产品,上个时代,我们通过敏捷来进行小团队的产品迭代,以满足客户多变的需求,那么,在这个以AI为中心的产品开发时代中,我们应该如何协作,来尽可能保证开发出来的模型的可迭代型,开发流程的可复用性,以及开发出来的产品的稳定性呢?这就是为什么DevOps的呼声越来越高的原因了。
1.2 软件开发的发展经历
既然提到了软件开发流程,这里不得不多说几句,免得引起歧义。实际上,不管是瀑布开发也好,或者门径开发,到现在的敏捷开发,以及这里开始着重讲的DevOps,没有哪个是落伍,或者谁更先进的说法,只是,不同的产品开发流程都是在不同的时代背景,对应不同的需求而生的。
瀑布开发:应该是迄今为止用到最多的软件开发流程了,通过收集需求、设计、开发、测试的线性方式进行。因为整个流程的“一气呵成”,就像瀑布一样水银泻地,我猜这就是为什么当时被称为瀑布开发的原因。这种开发模式很适合需求明确且具体的情况。这种开发模式几十年前可以说是绝对的流行,但随着时代的变化,开发周期越来越短,公司的扁平化,开发人员提倡以小组为单位以提高效率,而用户的需求变化越来越快,这种时候,单纯地使用瀑布开发就不够了。
敏捷开发:提倡一种迭代的概念。我们来看一下敏捷宣言就完全理解了:
个体和互动 高于 流程和工具
工作的软件 高于 详尽的文档
客户合作 高于 合同谈判
响应变化 高于 遵循计划
我个人至今觉得,如果只用敏捷去开发产品,很可能不适合我们目前环境下的软件开发方式,但敏捷的理念,工具,以及其优点应该被融入到标准的瀑布开发流程中。我认为其中最重要的四点是:(1)需求迭代;(2)以用户为中心;(3)通过将项目切分为定期交付的不同模块,可以实现解决方案或项目的模块化;(4)过程和结果的透明可见。
DevOps:如果只是像上面那样只是纸面描述,那我们很难看到敏捷有多大用处,而DevOps的出现升华了它。DevOps使软件开发人员可以彼此展开(远程)协作,使用 CI/CD 流程构建应用程序并实现可复制性,与可重复使用。DevOps汇集了开发、IT 运营、质量工程和安全性,以提高软件交付的效率和质量。这里不多赘述DevOps的细节,但这东西,用过的人都说好。
2 MLOps概念
2.1 为什么MLOps
刚才简单列举了几种典型的产品开发流程,那么我们就要问了,这些开发流程在机器学习,或者深度学习解决方案(这里不单指软件APP)开发中是否可以被完美使用?为什么还会有MLOps的推出?
传统的软件解决方案开发,比如,我们开发一个网页,代码总是大头,数据是小头。当然,可以有海量的用户数据的产生,这些数据在被允许的情况下可以储存在本地SQL,或者传入云端进行数据分析(这部分的数据使用和维护就和这个网页应用无关了)。
机器学习/深度学习解决方案的开发不同在于,代码和数据都是大头。比如,我们需要训练一个识别轧钢缺陷的模型,然后部署到我们的一个APP中。那么,这整个过程涉及到训练数据的采集与格式转换,标注,模型训练,模型再训练,模型打包,模型注册,模型部署,应用发布,监控与维护等模块。所以说,数据是机器学习/深度学习模型的基础,而代码的好坏让我们更好地去拟合数据,挖掘出最优,或者说,最大概率正确的结果。
2.2 MLOps介绍
如果我们在网上搜索MLOps
,可以搜出来一堆图和概念,在其中我挑出了一张最简明扼要的:
MLOps是机器学习(Machine Learning)和生产(Operation)的结合。它是一组用于自动化机器学习算法在生产中的生命周期的方法,从初始模型训练到部署,再到针对新数据进行再培训。所以,简单地来说,MLOps就是机器学习版本的DevOps。从上图我们可以更直观地看出,通过DEV
,我们将ML
与OPS
串联起来,最终实现机器学习与再学习的自动化,以及通过CI/CD持续集成与交付流程实现更高效地部署。
ml
: Experiment,即项目设计,包括需求收集,场景设计,数据可用性检查等;DEV
: Development,即模型开发,包括数据工程,评估验证,以及PR/CI流程等;OPS
: Operations,即模型运维,包括模型部署(CD流程),监控与调度触发等。
3 MLOps工作流
在本章节中,我们将引入MLOps工作流。通过此工作流的运行,可以实现更高效的原型制作,测试,验证,以及生产环境中的部署。为了让描述更加形象生动,我们以轧钢表面缺陷检测作为一个案例,对整个工作流进行描述。简单地讲,我们希望在轧钢的生产流水线上增加一道质量检测环节,通过采用高速线阵CCD摄像机,实时采集流水线上的图像数据,并通过机器视觉技术实时地检测出可能的缺陷,比如伤痕、裂纹、孔洞、轧痕、划痕、氧化皮、针孔、麻点等。
3.1 需求
需求部分不一定属于MLOps的范畴,更多属于标准的产品管理。我发现,绝大多数介绍MLOps的文章也并没有把这部分囊括进来。但是,对于产品开发,需求收集和定义至关重要,这直接决定了接下来的所有步骤和结果是否有意义。所以我将需求作为一个模块罗列在MLOps的流程中,并强调它的重要性。
这里的需求,包含了需求的采集和分析。
需求采集:一般我们有定性和定量的方式对需求进行采集,一些方法包括:用户访谈,可用性测试,调查问卷,数据分析等。最终我们对于采集完的需求做一个整理,包括:场景描述,需求产生原因,(可以是模糊的)需求验收标准,重要性,紧迫性,需求关联的人,事,物。
需求分析:包括需求转化,即把客户需求转化为产品需求;确定基本属性,即模块名称,描述,提出者等;分析商业价值,即重要性,紧急性,持续时间;初评实现难度,即评估技术可行性,开发量;计算性价比,即商业价值%实现难度。
3.2 训练
从训练模块开始,我们真正意义上进入MLOps。训练模块其实就是一个机器学习/深度学习管道。该管道仅用于训练和打包ML模型以及对其进行版本控制。它由运行 ML训练和管道所需的计算(例如,云CPU或GPU或者分布式计算)资源提供支持。
数据准备/数据引入:这一步骤中,我们通过提取、转换和加载 (ETL)操作,为下一阶段的模型训练提供准备。在这一步中,我们也需要将数据拆分为训练集以及测试集(或验证集),训练集用于下一步的模型训练,测试集(或验证集)用于之后的模型验证。需要注意,这些数据都进行版本控制,以确保操作的可追溯性。在我们的例子中,带有缺陷的数据集照片可以来源于现场采集,筛选,标注之后的照片与标签,存储于数据湖中。利用数据管道,我们可以提取、转换和加载 5000张轧钢表面图像。这5000张图像应尽量均衡地包含各种类别地缺陷图片,并且尽量保证小的相关性。将这些数据拆分为训练集和测试集(拆分比例可以为80% 和20%),注意进行版本控制。更进一步,我们将此模块分为如下几个子步骤:
- 数据整理(Data Wrangling):一般分为数据收集,数据评估,以及数据清理。
- 探索性数据分析(Exploratory Data Analysis):对数据进行清洗,对数据进行描述(描述统计量,图表),查看数据的分布,比较数据之间的关系,培养对数据的直觉,对数据进行总结等。
- 数据可视化(Data Visualization)
- 数据预处理(Data Preprocessing)
- 数据转化(Data Transformation)
并不是说每一个步骤都需要用,适合自己的项目就是最好的。
模型训练:无论是否使用MLOps,模型训练总是必不可少。对于机器学习/深度学习来说,模型训练一般会包括:预处理:数据增强,灰度,尺寸变化等;特征提取,也有人称之为特征工程,比如用HOG,SIFT去提取轮廓特征(对于传统的机器学习来说);模型训练:选取合适的机器学习模型,进行迭代训练,优化超参数。除此之外,MLOps可以提供的帮助包括:
- 模型开发过程中的结果评估与分析,包括指标误差分析,模型解释工具,可视化等。
- 模型本身的各类元数据管理,实验信息,结果记录(指标,详细数据,图表),文档(model card)等。
- 模型训练的版本化管理,包括各种依赖库,训练代码,数据,以及最终生成的模型等。
- 模型在线更新和离线再训练,增量训练的支持。
- 一些模型策略的集成,例如embedding的提取与保存,stratified/ensemble模型支持,transfer learning之类的增量训练支持等。
- AutoML类的自动模型搜索,模型选择的支持。
模型测试/模型评估:我们使用测试数据(数据准备/数据引入
步骤中从原数据中拆分出来)来对上一步骤中训练出来的模型进行评估。在轧钢表面缺陷检测的案例中,我们最关注的是精度和召回率。如果数值达到我们预期,那么我们就可以往下到下一步。当然,模型的评估可以远比这个复杂。有一篇谷歌的论文,名为The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction
,感兴趣的可以看一下。这里不做过多赘述,这篇博客也可以看看。
模型打包/模型注册:将测试完通过标准的模型序列化为文件,或进行容器化,以导出到生产环境中。在我们的用例中,我们可以将训练完的文件保存至ONNX格式,或进行TensorRT加速(出于在生产环境中实时性的要求),以供在生产环境中进行下一步的部署。有的时候,你的模型不仅仅由一个文件组成,可能会包括矢量程序、模型权重和序列化模型文件,这个时候,可以将这些文件注册为一个模型。
3.3 部署
此模块中,我们将训练,验证,并打包好的模型部署到生产环境中。
生产测试:在我们将打包好的模型部署到生产环境之前,必须通过测试来检验其稳健性和性能。根据不同规模和背景的项目,有的项目,我们会在预生产环境(一个类似生产环境的测试环境)对所有已训练的模型进行试运行。如果测试通过,那么我们再将这个模型部署到真正的生产环境中。用于测试的模型在测试环境中作为API或流服务部署到部署目标,如Kubernetes群集、容器实例或者可扩展的虚拟机或边缘设备(具体取决于需求和用例)。在部署了模型以供测试后,我们使用测试数据(这些数据不用于训练模型 ;测试数据是来自生产环境的样本数据)对部署的模型进行预测,在此期间还会进行批量或定期模型推理,以测试部署在测试环境中的模型的稳健性和性能。在我们这个案例中,我们可以将模型以及应用封装成容器,推到边缘设备中进行运行。在正式的“上线”之前,我们可以使用专门测试用的边缘设备,对这个模型以及应用的整体性能做一个评估,也可以直接用产品级的边缘设备,如果经验充足(毕竟我们已经使用了容器来保证环境的独立性以及可复制性),但必须要对真实的场景或者起码非训练集的测试数据/现实场景中的真实数据进行测试,并进行准确度、公平性和错误分析。在这一步结束后,质量保证专家对模型是否符合标准进行了认证。
生产发布:生产测试通过后,我们的应用就可以部署到由CI/CD管道提供支持的生产环境中了。在我们的案例中,即我们将模型以及应用封装成容器,推到边缘设备中进行运行。该部署的模型从现场的摄像头直接读取视频流,并通过训练好的模型实时进行模式识别。当检测到瑕疵后,随即保存截图,响警报,以及其他相关反应(属于监控的范畴)。
3.4 监控
作为一个端到端的闭环系统,监控包括了观察/监控机器学习/深度学习模型,应用程序,乃至边缘设备的性能;根据部署的应用程序产生的元数据(metadata)制作可视化界面,分析和挖掘更深层的价值;以及,根据不同项目的需要,在一定条件下触发的警报,或者类似信号。这里我们就不进行赘述了。对于不同类型的项目,会有不同类型的反馈信号。比如在我们的案例中,我们可以让边缘设备传回其GPU,CPU使用情况,以及温度等硬件信息,以观察设备的健康状况(在工业环境中,尤其是粉尘,防爆环境中,硬件设备的健康状况需要重点关注);另外,根据对部署模型的准确度、精准率和召回率分数的分析,当模型的性能降至预定义的阈值以下时,将会定期(每天一次)生成警报,比如,通知产品所有者当前模型的偏差度超过了X%。然后,产品所有者可以选择触发重新训练管道,对模型进行再训练。
3.5 驱动因素
为了保证上述的MLOps流程的运行,不同的步骤会生成或需要不同的“产品”,比如各种数据,模型,中间件,以及支撑模型训练以及部署背后的基础结构/算力平台等。
- 数据:整个MLOps流程中最起码涉及原始数据,训练数据集,验证数据集,测试数据集,以及监控数据(或者元数据)。原始数据可能是结构化的,也可能是非结构化的。我们需要进行数据注释、数据编录、数据准备、数据质量检查、数据采样和数据扩充等步骤,使其变成可以作为机器学习/深度学习模型训练输入的数据集。图中的训练数据集和验证数据集来自于我们实现准备好的原始数据中,而测试数据集则定义模糊。可以来自于原始数据,但一定不能让其经过模型训练;或者也可以来自于后期收集的真实现场数据。此测试数据集的主要用途在于打包好的模型再预生产环境的测试。
- 工件/模型:整个MLOps流程中最起码涉及已训练的模型,已打包的模型,以及生产模型。
- 中间件:使用
Git
进行源代码管理,使用VNet
启用所需的网络配置,使用Docker
对我们的模型进行容器化,以及使用Kubernetes
编排容器以自动执行应用程序部署、扩展和管理。 - 基础结构:为了确保 MLOps 管道能够成功运行,我们需要使用必要的计算和存储资源来训练测试并部署 ML 模型。通过计算资源,我们能够训练、部署并监控 ML 模型。