- 构建可靠的机器学习系统
- (美)凯茜·陈 (爱尔兰)尼尔·理查德·墨菲 (美)克兰蒂·帕里萨 (美)D.斯卡利 (美)托德·安德伍德
- 7948字
- 2025-06-26 18:00:38
1.1 机器学习的生命周期
机器学习永远不会真正完成。无论是技术上还是结构上,它也不会在任何一个地方开始或者停止。机器学习模型的开发人员通常希望他们的工作十分简单,只需要收集一次数据,训练一次模型。但是,这种情况很少发生。
一个简单的思想实验便可以帮助我们理解其中的原因。假设有一个机器学习模型,我们正在评估这个模型是否足够好(参考一个确定的阈值)。如果它没有达到我们的要求,那么数据科学家、商业分析师以及机器学习工程师通常会针对如何理解模型的故障并加以改进来进行协作。正如你可能想到的,这将涉及大量的工作:可能会修改现有的训练管道以改进一些功能,还可能会添加或删除一些数据,以及重构模型以迭代已经完成的工作。
相反,如果模型效果很好,整个组织都会为之兴奋。自然的想法是一次不成熟的尝试便取得了如此大的进步,那么想象一下,如果我们更加努力,使模型更加复杂的话,将会取得多么好的成果。你猜对了,这通常涉及修改现有训练管道、更改特征、添加或删除数据,甚至可能重构模型。无论哪种方式,无论相同的工作我们做了多少,我们做的第一个模型都只是下一步工作的起点。
让我们一起看一下机器学习的生命周期,或者说机器学习循环的细节(如图1-1所示)。
由于机器学习都是由数据开始,所以让我们从图的左侧开始更详细地了解这个循环。我们将详细了解每个阶段,并且在这个购物网站的背景下,解释每个阶段有哪些人参与以及他们的主要职责是什么。

图1-1:机器学习生命周期
1.1.1 数据收集与分析
首先,团队会盘点并评估所拥有的数据。团队成员需要确认所需数据是否齐全,之后优先将数据用于业务和组织需求。接着他们必须收集和处理数据。
尽管涉及程度因公司而异,但与数据收集及分析相关的工作基本上涉及了公司的所有人。例如,业务分析师会存在于金融、会计或者产品团队,每天使用平台提供的数据进行分析。还有数据和平台工程师也许会搭建可重复使用的用于提取、清洗和处理数据的工具,尽管他们可能不涉及任何的业务决策。(在小公司中,他们也许全是软件工程师或产品工程师。)有些地方会有正式的数据工程师的角色。还有一些数据科学家、产品分析师和用户体验(U X)研究员会使用这个阶段产出的数据。
对于网店运营商YarnIt,绝大多数的组织成员都参与了这一步骤,其中包括业务与产品团队这些对要优化的业务领域最了解的团队。举个例子,他们可以决定是小幅增加每单销售利润对企业更重要,还是稍微增加订单频率更有意义。他们能够指出高、低利润产品的问题与机会,并且将客户分类为高利润客户和低利润客户。产品工程师与机器学习工程师也会参与其中,考虑如何处理所有的数据。站点可靠性工程师会对整个管道提出建议和决策,使其更加可靠、易于监控和管理。
为机器学习管理数据是一个非常复杂的话题,我们会在第2章专门讨论数据管理原则,训练数据稍后将在第4章和第10章中进行讨论。目前,假设数据收集和处理系统的正确设计和管理是所有好的机器学习系统的核心要素。一旦数据被存储在合适的位置并转换为合适的格式,我们就将开始训练模型。
1.1.2 机器学习训练管道
机器学习训练管道由数据工程师、数据科学家、机器学习工程师和站点可靠性工程师指定、设计、构建和使用。它们是专用的提取、转换、加载(ETL)数据处理管道,用于读取未处理的数据,并将模型的结构与机器学习算法应用于数据[1]。它们的工作是利用训练数据生成完整的模型,以备评估和使用。这些模型要么一次生成完整的,要么以各种方式增量生成。有些模型不完整是因为它们只覆盖了一部分可用数据,而有些则是因为在范围上不完整,它们被设计为只覆盖整个机器学习的一部分。
训练管道是机器学习系统中唯一直接明确使用机器学习特定算法的部分,但即使在这里,这些算法也大部分被打包在相对成熟的平台和框架中,如TensorFlow和PyTorch。
训练管道也是机器学习系统中为数不多最初就不可避免地要关注算法细节的部分。在机器学习工程师大概依靠相对成熟的库构建并验证了一个训练管道之后,该管道可以安全地被其他人重用和操作,而不需要许多专业的统计知识[2]。
训练管道面临着与其他任何数据转换管道相同的可靠性挑战,以及一些特定于机器学习的挑战。最常见的机器学习训练管道故障如下:
● 数据缺失
● 正确格式数据的缺失
● 实现数据解析或机器学习算法时的软件缺陷或报错
● 管道或模型的错误配置
● 资源不足
● 硬件故障(由于机器学习的计算十分庞大且持续时间长,某种程度上这是一个常见故障)
● 分布式系统故障(为了避免硬件故障,会使用分布式数据处理系统进行训练,所以这经常发生)
所有这些故障也是常规(非机器学习)ETL数据管道的故障模式的特征。但是,机器学习模型可能会因数据分布、数据丢失、采样不足或常规ETL世界中未知的一系列问题而毫无征兆地失败[3]。第2章将详细介绍一个具体示例,它所依据的想法是,数据丢失、错误处理数据或无法使用数据子集是机器学习训练管道失败的普遍原因。在第7章和第9章中,我们将讨论如何通过监控训练管道来发现这些问题(通常称为分布的变化)。现在,让我们记住,由于这些不易察觉的故障模式,机器学习管道确实比其他数据管道更难可靠地运行。
如果还不清楚的话,机器学习训练管道绝对完全是一个生产系统,像服务二进制文件或数据分析一样值得关注。(如果你所处的环境中,除了你之外,其他人都不相信这一点,那么知道有足够多的反例可以最终说服他人可能会令人略感欣慰。)举个有关“如果你对生产不够重视会发生什么”的例子,我们知道有这样的故事:公司建立的模型是由已经离开公司的实习生创建的,没有人知道如何重新生成它们。这说起来好像没什么,但我们建议你永远不要陷入那种境地。养成一个习惯,把你所做的事情写下来,并将其转化为自动化的东西,这会在很大程度上避免我们之前提到的结果。好消息是,这完全可以从小规模开始,只需要手动操作,不需要特别的重复性。然而,要想获得成功,需要自动化和审计,我们认为,越早将模型训练自动化并进行一些简单的正确性检查和模型保存越好。
在任何情况下,假设我们能够成功构建一个模型,我们都需要将其集成到面向客户的环境中。
1.1.3 构建与验证应用程序
机器学习模型基本上是一组需要解锁以提供价值的软件功能。你不能只盯着模型,你需要审问它——问它一些问题。最简单的方法是提供一个直接的机制来查找预测(或报告模型的另一方面)。然而,最常见的情况是我们必须与更复杂的东西集成:无论模型具有什么目的,通常最好通过将模型与另一个系统集成来实现。将机器学习模型集成到应用程序中的工作将由产品和业务职能部门的员工指定,由机器学习工程师和软件工程师完成,并由质量分析师监督。关于这方面的更多细节,请参见第12章。
至于我们的在线购物网站yarnit.ai,各行各业和世界各地的人都可以在这里找到最好的针织或钩编纱线,所有这些都是基于AI的推荐!作为一个示例,让我们研究一个向购物者推荐额外购买的模型。该模型可以获取用户的购物历史和当前购物车中的产品列表,以及其他的一些方面,如他们通常要求配送的国家、他们通常购买的价格范围等。该模型可以使用这些功能生成一个购物者可能会考虑购买的产品的排名列表。
为了向公司和用户提供价值,我们必须将该模型集成到网站中。我们需要决定在哪里利用模型进行查询以及如何处理查询结果。一个简单的答案也许是,当用户考虑结账时,在购物车下方的水平列表上显示一些结果。这看起来是一个合理的开始,为购物者提供一些实用性,也可能为YarnIt带来一些额外收入。
为了能够确定我们在集成的相关方面做得如何,系统应该将显示的内容记录在日志中,还要将用户之后采取的行动记录下来,即他们是否将显示的商品添加到购物车并最终购买它们。通过记录这些事件,集成将为我们的模型提供新的反馈,以便它能够训练自己的推荐质量并做出改进[4]。然而在这个阶段,我们会简单地验证整个流程的有效性:加载到服务系统中的模型、由Web服务器应用程序发出的查询、显示给用户的结果、被记录的预测、被存储以用于未来模型训练的日志。接下来是评估模型质量和性能的过程。
1.1.4 质量和性能评估
机器学习模型当然只在有效时才是实用的。事实证明,要真正回答这个问题,需要进行非常详细的工作——首先我们必须决定如何量化机器学习模型的有效性,以及我们将如何根据目标结果来评估模型性能。这通常涉及识别我们试图创建的效果,并在不同子集(或切片)上利用代表性查询或用例测量它。第5章将对此进行更详细的介绍。
一旦我们确定了要评估什么,就应该进行离线评估。考虑到这一点,最简单的方法是进行一组我们认为具有代表性的查询并分析结果,将返回结果与一组“正确”或“真实”的答案进行比较。这将帮助我们确认模型在生产环境中的工作状况。当我们对模型的基本性能有信心的时候,无论是实时发布还是灰度发布,我们都可以进行初始集成。在实时发布中,该模型会占用实时生产流量,这会影响到网站和相关系统等。如果我们足够小心和幸运,那么只要监控好关键指标以确保用户体验不会受到损害,这就是一个合理的步骤。
灰度发布包括查询模型并记录结果,但当用户看到它时,不会在网站上积极地使用它。这可能让我们对模型与We b应用程序的技术集成充满信心,但对模型的质量可能不会有太多信心。
最后,还有一个中间方案:我们可以为应用程序构建有时能让一小部分用户使用模型的功能。虽然选择这一小部分用户是一个更高等级的话题,超出了本书范围[5],但总体想法很简单:在一些查询中尝试该模型,并同时在集成与模型质量方面获得信心。
一旦确信该模型不会损害用户体验,并且还会帮助用户(以及我们的收入,希望如此!),我们就差不多准备好发布了。但首先,我们仍需要关注监控、测量和持续改进。
1.1.5 定义与度量服务等级目标
服务等级目标(Service-Level Objective,SLO)是特定度量的预定义阈值,通常称为服务等级指标(Service-Level Indicator,SLI),用于定义系统是否按照要求运行。一个具体的例子是“99.99%的HTTP请求在150 ms内成功完成(即返回20开头的代码)”。SLO是站点可靠性工程师所擅长的领域,但对于指定产品需要做什么和如何对待用户的产品经理,以及数据科学家、机器学习工程师和软件工程师来说,SLO也是至关重要的。一般来说,确定SLO是具有挑战性的(https://www.alex-hidalgo.com/the-slo-book),而为机器学习系统指定SLO具有双重挑战,因为数据中甚至我们周围世界中的细微变化的方式,都会显著降低系统的性能。
话虽如此,在考虑机器学习系统的SLO时,我们可以从区分显而易见的关注点来开始。首先,我们可以使用服务、训练和应用程序之间的划分。第二,我们有四个传统的黄金指标(https://oreil.ly/hl4Vd)(延迟、流量、错误、饱和度)之间的区分,以及机器学习操作的内部区分,它们本身远不如黄金指标更加通用,但并不完全特定于某一领域。第三,我们有与机器学习应用程序优化工作相关的SLO。
让我们更加细致地看一下将这些关于SLO的想法直接应用于yarnit.ai的一些简单建议。我们应该为每个系统设置独立的SLO:服务、训练和应用程序。从模型服务来看,我们可以像对待任何其他系统一样,简单查看一下错误率。对于训练,我们应该查看吞吐量(当模型的复杂性相当时每秒训练的样例数或训练数据的字节数)。我们还可以为完成模型训练建立一个整体SLO(例如,95%的训练运行在几秒内完成)。在应用程序中,我们应该监控诸如最终显示的建议数量,以及对模型服务的成功调用数量等指标(从应用程序的角度来看,这可能与模型服务系统报告的错误率匹配,也可能不匹配)。
然而,请注意,这些示例都不是关于模型的机器学习性能的。为此,我们需要设置与应用程序本身的业务目的相关的SLO,并且这方面的度量需要的时间可能比我们预想中的要长。模型生成的建议和模型排名搜索结果的点击率对于我们网站来说也许是一个良好起点。我们还应该为该模型的收入建立一个端到端的SLO,并且不仅在总体上,还应该在我们客户的合理子集(按地理位置或按客户类型)中进行衡量。
我们将在第9章对此进行更详细的研究,但目前请你接受有一些合理的方法可以在机器学习中实现SLO,并且它们涉及许多其他非机器学习SLO话题中使用的技术(尽管由于机器学习工作的细节我们需要更久的时间探讨此类话题)。但是,不要让复杂性妨碍了基本事务。归根结底,产品和业务领导必须明确他们可以容忍哪些SLO,不能容忍哪些SLO,这样公司的生产工程资源才能集中用于实现正确的目标。
一旦收集了数据,构建了模型,将其集成到我们的应用程序中,测量了其质量,并明确了SLO,我们就可以进入激动人心的发布阶段了!
1.1.6 发布
现在,我们将第一次从客户那里直接获得输入!产品软件工程师、机器学习工程师和站点可靠性工程师都在这里一起工作,将我们最新版本的应用程序交付给最终用户。如果我们使用的是基于计算机或移动端的应用程序,这将涉及软件版本发布以及这些发布所需的所有质量测试。然而,在我们的案例中,我们发布了一个新版本的网站,其中将包含由机器学习模型驱动的推荐和结果。
发布机器学习管道与发布任何其他线上系统有共通的部分,但也有很多特定属于机器学习系统的问题。关于一般线上系统的发布建议,请参阅由Betsy Beyer等人编辑的Site Reliability Engineering:How Google Runs Production Systems一书(O'Reilly,2016)第32章(https://oreil.ly/OsNL3)。包括基本的检查/观测、发布的控制以及回滚在内的这些措施是必需的,一个没有定义回滚计划的发布是十分危险的。如果你的基础设施实现回滚操作十分困难,或者根本不允许回滚,我们强烈建议你在发布之前先解决此问题。下面将详细介绍一些特定于机器学习的问题。
模型即代码
请记住,模型与训练系统二进制文件、服务路径和数据处理的代码一样,都是代码。部署一个新模型一定会使你的服务系统崩溃并破坏你的在线推荐模型。部署新模型甚至会影响某些系统中的训练(例如,使用迁移学习开始训练另一个模型)。以相同的方式对待代码和模型发布很重要:尽管一些组织在(比如)假期发布新模型,但模型完全有可能出错,而且从某种程度上说,如果发生这种情况,就需要在短时间内进行代码修复。在我们看来,它们具有同等的风险,应该采取相同的应对措施。
缓慢发布
在部署新版本的在线系统时,我们通常能够逐步进行部署,从所有服务器或用户的一小部分开始,只有当过一段时间我们对系统的正确运行和机器学习改进的质量有信心时才会逐步扩大规模。这里要明确的是,我们需要尽力限制损失并在两个维度上获得信心:用户和服务器。如果我们碰巧生产了一个糟糕的系统或模型,我们肯定不想让它影响到所有用户;相反,我们首先将它展示给一小部分终端用户,然后逐渐增长。类似地,对于我们的服务器群,如果碰巧构建了一个无法运行或运行不佳的系统,我们也不想它影响到所有的服务器群的计算空间。
其中最棘手的方面是确保新系统在部署过程中不会干扰旧系统。对机器学习系统来说,最常见的是通过中间存储工件来实现。具体来说,格式的变化和语义的变化会导致数据解释中的错误。第2章会介绍这些内容。
发布,而不是重构
“每一次改变尽可能少”这种常见的原则适用于许多系统,但在机器学习系统中尤为明显。整个系统的行为很容易发生变化(通过底层数据的变化等),因此在任何其他环境中都很微不足道的重构可能导致无法找到问题所在。
在数据层隔离部署
在进行渐进式上线时,请记住必须在数据层以及代码/请求/服务层进行隔离。具体来说,如果新模型或服务系统的日志输出被旧版本代码或模型使用,则对问题的诊断可能会十分漫长且棘手。
这不仅是一个机器学习问题,未能将新代码的数据路径与旧代码隔离开来,在过去几年中导致了一些惊人的运行事故。尽管机器学习系统中的故障往往更微妙且更难检测,但这可能发生在任何处理数据的系统上,这些数据由系统的不同部分产生。
状态系统的渐进式部署
故事时间:本书作者之一曾参与一个支付系统的开发,该系统在新功能部署期间出现错误。虽然这出乎意料,但在运行系统的环境中并非完全没有先例,因此只需回滚更新即可轻松修复。考虑到错误随着部署进度成比例地增加,这一点尤其正确。
团队也是这么想的!但不幸的是,随着回滚完成,错误率飙升至100%,团队陷入了恐慌。经过多次调试,发现更新实际上为达成新功能的预期而更改了一些数据格式,并且与旧系统期望的格式不兼容。就像在部署期间所发生的,当较新的组件写入的日志恰好被较旧的组件读取时,就会发生错误。回滚取消了正确处理已写入的新格式日志的功能。事实上,如果团队让部署完成(或一次性完成),错误就会消失。这里的主要教训是,需要全面考虑可能需要参与回滚的所有系统组件,尤其是数据层[6]。
在发布期间测量SLO
确保你至少有一个能够显示最新和最敏感指标的仪表盘,并在发布期间跟踪这些指标。当你找出最关心的指标以及最有可能表明某种发布失败的指标时,可以将这些编码到一个服务中,如果未来出现问题,该服务会停止发布。
回顾发布
无论是手动还是自动,确保在任何类型的发布过程中进行监控。较小的组织或较大的(或更不寻常的)发布应该由人监控。如前所述,当你对其有信心时,便可以开始依靠自动化系统来完成此操作,并且可以显著提高发布速度!
1.1.7 监控和反馈循环
与任何其他分布式系统一样,关于机器学习系统功能是否正确运行的信息是有效且可靠地操作它的关键。确定“正确”运行的主要指标显然仍是产品和业务人员的职责。数据工程师将识别信号,软件工程师和站点可靠性工程师将帮助实施数据收集、监控和发出警报等。
这与之前的SLO讨论密切相关,因为监控信号通常直接用于SLO的选择或构建。在这里,我们稍微深入地探讨一下监控信号的类别:
系统健康或黄金指标信号
这些与任何非机器学习信号都没有什么不同。将端到端系统视为数据提取、处理和服务系统,并相应地对其进行监控。进程是否正在运行?他们是否有改进?是否有新数据到达等(第9章会有更多详细信息)。机器学习的复杂性很容易让人分心。然而,重要的是,要记住机器学习系统也是系统。它们具有所有与其他分布式系统相同的故障模式,以及一些新颖的故障模式。不要忘记最基本的,这是黄金指标监控方法背后的理念:找到能够代表系统整体行为的通用的、高级别的指标。
基本模型健康或通用机器学习信号
检查机器学习中的基本模型健康指标与检查系统健康等价:它不是特别复杂,也不是与领域紧密耦合,而是包括关于建模系统的基本和代表性的事实。新模型是否符合预期大小?它们可以无误地加载到我们的系统中吗?在这种情况下,关键的标准是,是否需要了解模型的内容才能进行监控。如果不需要,所做的监控就是基本模型健康问题。这种与模型内容无关的方法具有很大的价值。
模型质量或特定领域信号
最难监控和检测的是模型质量。在与运行相关的模型质量问题和改进模型质量的机会之间并没有严格的界限。例如,如果我们的模型为我们网站上购买针而不是纱线的人所生成的推荐很差,这可能是一个改进模型的机会(如果这种质量水平满足发布标准),或者这可能是一个需要立即响应的紧急事件(如果这是最近的回归)[7]。不同之处在于其背景。对于大多数站点可靠性工程师,这也是机器学习系统最难的方面:没有能够客观衡量模型质量“足够好”的标准,更糟糕的是,这是一个难以衡量的多维度问题。最终,产品和业务负责人将不得不建立真实世界的指标,以验证模型是否满足他们的要求,而机器学习工程师和站点可靠性工程师需要共同努力确定与那些要求最相关的质量指标。
作为循环中的最后一步,我们需要确保我们的终端用户与模型交互的方式能够返回到下一轮数据收集中,并准备好再次进行循环。机器学习服务系统应该记录所有其认为有用的内容,以便将来进行改进。通常情况下,收到的查询、提供的答案以及为什么提供这些答案都会被记录下来。“为什么”可以像单一的相关性评分一样简单,也可以是更复杂的甚至影响决策的因素的集合。
我们完成了第一次机器学习循环,并准备好重新开始。至此,yarnit.ai应该至少添加了最小限度的机器学习功能,我们也应该开始不断地改进它,要么通过改进第一个模型,要么通过确认可以用机器学习手段改进的网站的其他方面。