第 1 章 入门
本章将介绍机器学习流水线并给出框架性的构建步骤。我们将讲解如何将机器学习模型从一个小实验转变成健壮的工业级生产系统。同时,本章也将介绍一个贯穿全书的示例项目,通过这一项目来演示本书要介绍的各个准则。
1.1 为什么要用机器学习流水线
机器学习流水线的关键性优势建立在模型生命周期的自动化上。当有新的训练数据可用时,一个包含数据校验、预处理、模型训练、分析和部署的工作流就会被触发。我们观察到有许多数据科学团队手动做这些工作,不仅费时费力而且容易出错。下面来看看使用机器学习流水线的一些具体的好处。
只需专注于新模型而不用维护既有模型
自动化的机器学习流水线将数据科学家从烦琐的模型维护任务中解放出来。我们观察到很多数据科学家将精力花在了更新之前已经开发完成的模型上。他们会手动运行脚本去预处理训练数据、使用一次性的部署脚本或者手动微调模型。自动化的流水线可以让数据科学家专注于开发新模型,这是他们最喜欢做的事。最终,这将带来更高的工作满意度,并在激烈的人才市场中保持较低的人才流失率。
预防 bug 的产生
自动化流水线可以预防 bug 的产生。正如在后续章节中将看到的,新创建的模型会受到版本化数据的约束,预处理步骤也会受到已开发模型的约束。这意味着如果有新的数据,那么将生成新的模型。如果预处理步骤更新了,那么从原始数据经过预处理得到的训练数据将变得无效,因此还是需要生成一个新的模型。在手动机器学习工作流中,一个常见的 bug 来源是在模型训练完成后对预处理步骤的变更。在这种情况下,和模型一起部署的预处理步骤将和模型训练时的预处理步骤不一致。这些 bug 可能很难发现和调试,因为虽然预处理步骤不一致,但依旧可以进行推算,只是最后的推算结果不正确。通过使用自动化的工作流,可以有效地预防这种错误。
有用的记录文档
实验记录和模型发布管理单元将生成一份记录模型变化的记录文档。实验将记录模型的超参数的变化、所使用的数据集和模型的性能指标(比如损失值或者准确率)。模型发布管理单元将追踪哪一个模型最终被选用并部署。记录文档在数据科学团队需要重新创建模型或追踪模型性能时特别有用。
标准化
标准化的机器学习流水线可以改善数据科学团队的体验。受益于标准化的设置,数据科学家可以很快上手或者进行跨团队合作,找到相同的开发环境。这会提高效率并缩短新项目的启动时间。另外,这也能够降低人才流失率。
流水线对团队的影响
自动化机器学习流水线将对数据科学团队产生 3 个关键性的影响:
● 拥有更多的时间去开发具有创新性的模型;
● 简化了更新已有模型的流程;
● 缩短了在复现模型上所用的时间。
所有这些方面都将降低数据科学项目的成本。不仅如此,自动化机器学习流水线还会带来如下好处。
● 帮助检测数据集或者训练模型中的潜在偏见。发现偏见问题可以避免使用模型的人们受到伤害,比如亚马逊的基于机器学习的简历筛选器就被发现存在对女性不利的偏见。
● 创建记录文档(通过实验记录和模型发布管理单元创建)将有助于解决数据保护法律[比如欧盟的《通用数据保护条例》(General Data Protection Regulation,GDPR)]产生的一些问题。
● 可以为数据科学家节约更多的开发时间并提高他们的工作满意度。
1.2 什么时候考虑使用机器学习流水线
虽然机器学习流水线具有多种优势,但并不是所有的数据科学项目都需要使用流水线。有时候数据科学家只是想实验一个新的模型、研究一种新的模型架构或者复现最近的学术成果。在这些情况下,流水线并不是很有用。然而,只要模型已经有了用户(比如,已经在一个应用中使用),它就需要持续地更新和微调。在这些情况下,我们又回到了之前讨论过的场景:持续更新模型和减轻数据科学家在这些任务上的负担。
随着机器学习项目的增长,流水线变得越来越重要。如果数据集或资源需求很大,我们所讨论的这些方法就可以轻易地随着基础架构扩展。如果可重复性很重要,那么它可以通过机器学习流水线的自动性和审计日志来实现。
1.3 机器学习流水线步骤概述
机器学习流水线开始于对新训练数据的获取,结束于接收关于新模型性能表现如何的某种反馈。这种反馈既可以是产品性能指标,也可以是来自用户的反馈。机器学习流水线包含多个步骤,比如数据预处理、模型训练和模型分析,当然还包含不可或缺的模型部署步骤。可以想象,手动执行这些步骤将是多么麻烦且容易出错。本书将介绍使机器学习流水线自动化的工具和解决方案。
如图 1-1 所示,整条流水线实际上就是一个无限循环。由于可以持续地收集数据,因此机器学习模型也能被持续地更新。生成更多的数据通常意味着可以获得更好的模型。因为数据不断地流入,所以流程自动化变得异常关键。在真实世界的应用环境中,你总是想频繁地重新训练你的模型。如果不这样做,在多数情况下模型的准确率将慢慢降低,因为模型训练时的数据和推算时的数据在分布上已经存在差异。如果重新训练模型的过程是手动的,那么就需要数据科学家或机器学习工程师手动校验新的训练数据或分析更新后的模型。因此,他们就没有时间为完全不同的业务问题开发新的模型了。
图 1-1:模型的生命周期
一条机器学习流水线通常包含以下几个步骤。
1.3.1 数据读取和版本控制
数据读取(参见第 3 章)是每一条机器学习流水线的开始。在这一步骤中,我们将数据处理成后续组件能够读取的格式。数据读取步骤不会执行任何特征工程(其会在数据校验步骤后进行)。这也是进行输入数据版本控制的最佳时机,在流水线末端训练得到的模型将和这个数据快照联系在一起。
1.3.2 数据校验
在训练新的模型版本前,需要校验新的数据。数据校验(参见第 4 章)将专注于如何检查新的数据在统计意义上是否满足期望(比如范围、类别数量和类别分布)。如果数据校验工具检测到异常的情况,它会警示数据科学家。如果你在训练一个二分类模型,那么你的训练数据应该包含 50% 的 X 类样本和 50% 的 Y 类样本。如果新数据的类别划分比例发生了变化,比如说两个类别的比例为 70∶30,那么数据校验工具将发出警示。如果模型在这样一个严重不均衡的训练集上训练,并且数据科学家并没有采取措施去调整模型的损失函数或者采用过采样/欠采样的方案去调整分类 X 和分类 Y,那么模型的预测结果可能会偏向样本数量更多的类别。
常见的数据校验工具还允许你比较不同的数据集。如果你有一个包含优势分类的数据集,并想将这个数据集分成训练集和校验集,那么你需要确认两个数据集间的分类分布情况大体相同。数据校验工具允许你比较不同的数据集并找出其中的异常部分。
如果数据校验发现了异常,那么流水线将停止处理并会向数据科学家发出警告。如果发现数据分布出现漂移,那么数据科学家或机器学习工程师可以改变每个类别的抽样方式(比如,从每个类别中抽取相同数量的样本),或者改变模型的损失函数,开始构建新的模型流水线并重启生命周期。
1.3.3 数据预处理
新收集的数据通常无法直接用于机器学习模型的训练。在绝大多数情况下,数据需要经过预处理才能用于训练。标签往往需要先转换成 one-hot 向量或者 multi-hot 向量 1。这一过程同样适用于模型的输入数据。如果训练文本模型,那么需要将文本中的字符转换成索引或者将文本标记转换成词向量。因为预处理过程只需要在训练模型前执行一次,而无须在每轮训练中重复执行,所以将预处理过程放在模型训练前独立运行很合理。
1在将结果同时分成多个类别的监督分类问题中,需要将类别转换成如 (0, 1, 0) 这种 one-hot 向量,或者将一个类别列表转换成如 (1, 1, 0) 这种 multi-hot 向量。
数据预处理工具的种类繁多,从简单的 Python 脚本到复杂的图模型都有。大部分数据科学家很关心所选工具的处理能力,但预处理步骤的改动和已处理数据之间的双向连接同样重要。这意味着如果有人改动了预处理步骤(比如,在 one-hot 向量转换中增加了额外的标签),那么之前的训练数据应该无效并会强制更新整条流水线。第 5 章将进一步描述数据预处理步骤。
1.3.4 模型训练和模型调优
模型训练(参见第 6 章)是机器学习流水线的核心。这一步骤将训练模型读取输入并以尽可能低的误差预测输出。随着模型(尤其是那些使用大规模训练数据集的模型)的增大,这一步骤将很快变得越来越难以管理。对于计算而言,由于单机内存通常是有限的,因此高效的分布式模型训练将成为关键。
因为可以获得显著的性能提升和提供竞争优势,所以模型调优近年来获得了极大的关注。根据机器学习项目的不同,可以选择在考虑使用机器学习流水线之前调优或者将之作为流水线的一部分。得益于优秀的底层架构,本书介绍的流水线是可以扩展的,模型可以大规模地并行或顺序启动。这样一来,便可以为最终的生产模型找出最优的模型超参数。
1.3.5 模型分析
通常情况下,使用准确率或者损失值来确定最优的模型参数集。但当模型的最终版本确定后,进行深度模型性能分析(参见第 7 章)将非常有用。这可能包括计算其他指标,比如精度、召回率和曲线下面积(area under the curve,AUC),或在一个更大的数据集(而不是训练时用的校验集)上计算性能。
进行深度模型性能分析的另一个原因是要检查模型预测的公平性。对数据集进行分组并对每组数据独立评估后才能分析出模型在组间的不同表现。通过调查模型对训练中所用特征的依赖,可以解释改变单个训练样本的特征将如何影响模型的预测结果。
与模型调优以及最终选择最优模型的步骤一样,这一步骤也需要数据科学家参与。然而,后面将演示如何将整个分析自动化,仅在最后审核时才需要人参与。这一自动化过程使模型分析变得统一且具有可比较性。
1.3.6 模型版本控制
模型版本控制和验证的目的是追踪哪种模型、哪个超参数集以及数据集将被选择作为下一个要部署的版本。
软件工程中的语义化版本控制要求使用者在其 API 中做出具有不兼容性的改变或者在重大特性发布时增加主版本号,否则就增加次版本号。模型发布管理还有另外一个自由度:数据集。在一些情况下,无须改变模型参数或者模型架构,仅通过大幅增加或者提供更好的数据集就可以显著提升模型性能。这种性能提升是否意味着需要增加模型主版本号呢?
对于上述问题,不同的数据科学团队可能有不同的答案,但记录新版模型的所有输入(超参数、数据集、模型架构)并将其作为版本发布的一部分是非常必要的。
1.3.7 模型部署
在完成模型的训练、调优和分析后,就到了收获成果的黄金时刻。不过,因为有太多的模型是通过一次性实现工具 2 完成的部署,所以模型更新成了一个容易出错的过程。
2比如临时写的脚本等。——译者注
使用现代模型服务器,无须编写 Web 应用代码就可以部署模型。通常情况下,模型服务器会提供多种 API,比如描述性状态迁移(REST)或者远程过程调用(RPC)等协议,并支持同时运行相同模型的多个不同版本。同时运行多个模型版本有助于对模型做 A/B 测试,并针对如何改善模型提供很有价值的反馈。
在模型服务器的帮助下,可以直接更新模型版本,而无须重新部署应用。这可以缩短应用的停机时间并减少应用开发团队和机器学习团队间的沟通。第 8 章和第 9 章将详细介绍模型部署。
1.3.8 反馈循环
机器学习流水线的最后一步常被人忘记,但它对于数据科学项目的成功至关重要。这个流程需要闭环,从而在评估新部署模型的有效性和性能时得到有价值的信息。在一些场景中,还能获得新的训练数据,以用于扩充数据集和更新模型。这个过程既可以有人参与,也可以全程自动。详细信息参见第 13 章。
除去需要人参与的两个步骤(模型分析和模型反馈),整条流水线都可以自动化。这样一来,数据科学家就能够专注于新模型开发,而不是更新和维护现有的模型。
1.3.9 数据隐私
在撰写本书时,数据隐私还未纳入标准的机器学习流水线。随着消费者越来越关心自己的数据如何被使用以及限制个人数据使用的法律法规的出台,数据隐私越来越引起人们重视。在这种趋势下,隐私保护方法终将加入构建机器学习流水线的工具中。
第 14 章将讨论为机器学习模型增强隐私性的几种方法。
● 差分隐私:通过数学方法保证模型的预测结果不会暴露用户数据。
● 联邦学习:原始数据只在本地被使用,不会上传到云端或分享给其他设备。
● 加密机器学习:整个训练过程全部在加密的空间中进行,或者训练数据是加密的。
1.4 流水线编排
前面描述的所有机器学习流水线组件都需要有序执行或者说编排,这样众多组件才能按照正确的顺序运行。组件的输入数据必须在组件执行前就通过计算得到。对这些步骤的编排是通过诸如 Apache Beam、Apache Airflow(参见第 11 章)或 Kubernetes 基础架构中的 Kubeflow Pipelines 等工具(参见第 12 章)来完成的。
数据流水线工具在不同的机器学习流水线步骤间协调,如 TensorFlow ML MetadataStore 的流水线工件仓库会捕获每个处理过程的输出。第 2 章将概述 TFX 的 MetadataStore 并深入学习 TFX 和它的流水线组件。
1.4.1 为什么使用流水线编排工具
2015 年,谷歌的一群机器学习工程师得出结论:众多机器学习项目失败的一个原因是使用自定义代码去连接不同的机器学习流水线步骤。3 然而,这些自定义代码无法轻易地从一个项目迁移到另一个项目。研究人员在其论文“Hidden Technical Debt in Machine Learning Systems”4 中总结了他们的发现。作者们在论文中辩称这些流水线步骤间的胶水代码通常很脆弱并在超出特定范围后无法扩展。随着时间的推移,人们开发了诸如 Apache Beam、Apache Airflow 和 Kubeflow Pipelines 等工具。这些工具可用于管理机器学习流水线任务,允许使用标准的编排工具并对任务间的胶水代码进行抽象。
3谷歌于 2007 年开始了一个名为 Sibyl 的内部项目,该项目的目的是管理内部机器学习产品流水线。2015 年,这个话题在 D. Sculley 等人发布了他们的机器学习流水线文章“Hidden Technical Debt in Machine Learning Systems”后引起了广泛的关注。
4D. Sculley 等,“Hidden Technical Debt in Machine Learning Systems”,谷歌公司(2015 年)。
尽管学习一个新工具(比如 Beam 或 Airflow)或者一个新框架(比如 Kubeflow),以及建立一套额外的机器学习基础架构(比如 Kubernetes)看起来很麻烦,但投入这些时间会很快得到丰厚的回报。如果不采用标准的机器学习流水线,那么数据科学团队需要面对不统一的项目设置、随意放置的日志文件、各不相同的调试步骤等数不完的混乱。
1.4.2 有向无环图
诸如 Apache Beam、Apache Airflow 和 Kubeflow Pipelines 等流水线工具使用任务间的依赖图来控制任务的执行流程。
如图 1-2 所示,所有的流水线步骤都是有向的。这意味着从任务 A 开始到任务 E 结束的流水线,其任务间的依赖清晰定义了流水线的执行路径。有向图避免了任务开始时其依赖项还没有完成计算的情况。由于我们知道训练数据的预处理必须先于模型训练执行,因此通过有向图的表示,可以避免模型训练在数据预处理完成之前执行。
图 1-2:有向无环图示例
流水线图也必须是无环的,这意味着图不能连接至先前已经完成的任务。5 有环意味着流水线会一直执行且永不停止,因此工作流也就永远不能完成。
5无环图中不能存在直接或间接的环状依赖,也就是说 A 依赖 B 的同时 B 也依赖 A。——译者注
由于这两个约束条件(有向和无环)的存在,流水线图被称为有向无环图(directed acyclic graph,DAG)。有向无环图是大部分工作流工具最核心的概念。第 11 章和第 12 章将讨论更多关于有向无环图的细节。
1.5 示例项目
为了能更好地理解本书内容,我们提供了使用开源数据的示例项目。数据集收集了美国消费者关于金融产品的投诉,内容上既包含结构化数据(分类/数值数据),也包含非结构化数据(文本数据)。数据来自美国消费者金融保护局。
图 1-3 展示了数据集中的部分样本。
图 1-3:数据样本
这里的机器学习问题是给定关于投诉的数据,预测消费者是否对公司的回复有异议。在本数据集中,大约 30% 的消费者对回复有异议,因此数据是不均衡的。
1.5.1 项目结构
示例项目已经上传至 GitHub 仓库,通过下列命令可以克隆该项目。
$ git clone https://github.com/Building-ML-Pipelines\ building-machine-learning-pipelines.git
Python 包版本
本示例项目使用 Python 3.6~3.8、TensorFlow 2.2.0 和 TFX 0.22.0。项目会持续更新,但无法保证兼容其他编程语言或包版本。
示例项目包含如下部分:
● chapters 目录包含第 3 章、第 4 章、第 7 章和第 14 章的样例 notebook;
● components 目录包含诸如模型定义之类的常用组件的代码;
● 一条完整的交互式流水线;
● 一个机器学习实验的示例,其是整条流水线的起点;
● 由 Apache Beam、Apache Airflow 和 Kubeflow Pipelines 编排的完整的流水线;
● utility 目录包含下载数据的脚本。
在后面的章节中,我们将逐步指导你通过必要的步骤将一个基于 Keras 模型架构的 Jupyter Notebook 的样例机器学习实验转换成完整的机器学习流水线。
1.5.2 机器学习模型
示例深度学习项目的核心是由位于 components/module.py 中的 get_model 函数生成的模型。
模型通过如下特征来预测消费者对于回复是否存在异议。
● 金融产品
● 子产品
● 公司对于投诉的回复
● 投诉类型
● 消费者所在的州
● 消费者所在地邮政编码
● 消费者投诉的内容
为了构建机器学习流水线,假设模型架构设计已经完成并且不再修改。第 6 章将详细讨论模型架构的细节。但实际上在本书中,模型架构是非常小的知识点。本书主要讨论的是在模型已经存在的情况下该做什么。
1.5.3 示例项目的目标
本书将演示持续训练示例机器学习模型的必要框架、组件和基础架构元素。图 1-4 展示了本书将在架构图中使用的软件栈。
图 1-4:示例项目的机器学习流水线架构
本书会尽量保持示例项目中机器学习问题的通用性,以便你将之替换成自己的机器学习问题。构建机器学习流水线的结构和基本步骤是不变的,可以很容易地迁移到你的实际案例中。每个组件将需要一些自定义操作(比如,从哪里读取数据),但正如后面将讨论的,这些自定义操作需要被适当地限制。
1.6 小结
本章介绍了机器学习流水线的概念并解释了其中的步骤,同时也展示了自动化流水线的优势。本章为后续章节做好了铺垫,并在介绍示例项目的同时简单介绍了每章的大体轮廓。第 2 章将开始构建流水线!