模型生产环境中的反馈与数据回流

前言

当机器学习模型部署在生产环境之后,它可能会在毫无预兆的情况下,业务指标快速下降,直到为时已晚。这就是为什么模型监控是机器学习模型生命周期中的关键步骤,也是MLOps的关键部分:

机器学习模型需要在两个方面进行监控:

  • 资源类监控:确保模型在生产环境中正确运行,具体包括:系统是否仍是监控? CPU、RAM、网络和磁盘空间是否符合预期?请求是否以预期的RT处理等
  • 指标类监控:随着时间的推移,模型是否依然有效。包括:模型是否仍适配新进的线上数据?指标是否与设计阶段一样好?
    资源类监控是DevOps中所涉及到的。而指标类监控更复杂,模型的指标表现通常依赖于其数据, 由于数据通常在不断变化,如果没有持续的新数据来训练模型,不再更新的模型无法学习到新的数据模式。模型指标类监控试图跟踪这种衰减,并且在适当的时候,使用更具代表性的新数据对模型进行再训练,阻止模型指标的衰减。

模型应该多久重新训练一次?

关于监控和再训练的其中一个关键问题是:模型应该多久再训练?这个问题取决于许多因素,包括:

  • 业务领域:网络安全、股票实时交易等领域的模型需要定期更新,以适应这些领域的即时变化。而如语音识别这类模型,通常更稳定,模式不会经常突然改变。但是,更稳定的模型需要更加强大:比如需要支持咳嗽场景下语音识别;
  • 再训练成本:需要考虑再训练的成本是否值得。例如,整个数据管道并重新训练模型需要一周的时间,但是仅能提升1%或者更低;
  • 模型指标:在某些情况下,模型指标在很少新的训练样本下很难有提升,是否重训练的还取决于收集足够的新训练样本;

在再训练频率方面,还需要考虑两个极限情况:

  • 上限:模型每年重训练一次, 但是要确保你的团队以及你的基础设施能够保证训练的时候,团队和基础设施能够有用;
  • 下限:以具有近乎实时反馈的模型为例,例如推荐引擎,用户在预测后几秒钟内点击产品,相关部署方案应该包括A/B Test,以确保模型按预期执行,考虑到这些验证属于统计验证,需要时间来处理收集所需的信息,计算相关的验证指标,另外即使是最简单的部署,该过程也可能允许一些人工验证或手动回滚的可能性。这些决定再训练的下限;

除上,还有一个规则之外的,就是”在线训练“:团队通过使用更自动化的ML管道,来构建能自我迭代的业务训练能力。虽然听起来很有吸引力,但这些算法的上线成本更高:模型设计者不仅要在测试数据集上测试模型的指标,还要在数据变化时验证模型的指标。 (后者是必需的,因为一旦部署了算法,就很难减轻不良学习的影响,而且当每次训练递归地依赖于前一次训练时,也不可能重现所有行为,因为你不可能让用户行为无法重复发生)。
没有标准的方法——类似于交叉验证来做模型验证,所以设计成本会更高。在线机器学习是挑战性很高的一个分支, 需要强大的基建与标准化的流程才能保证。

无论如何,一定频率的模型再训练绝对是必要的——这不是是否的问题,而是合适在训练的问题。好消息是,如果有可能在第一次模型训练时,收集到足够多的训练数据,那么大多数场景下,使用新的数据来进行再训练的解决方案是合适的。
因此,作为 MLOps和算法模型生命周期的一部分,机器学习各方参与者应该尽可能全面理解模型指标衰减。实际上,每个部署的模型都应该带有监控指标和相应的警告阈值,以尽快检测到业务性能下降。接下来的文章,用于在特定模型下,如何定义指标理解模型衰减。

理解模型退化

一旦机器学习模型在生产中得到训练和部署,有两种方法可以监控其性能下降:真实数据评估和输入漂移检测。了解这些方法背后的理论和局限性对于确定最佳策略至关重要。

真实数据评估

真实数据再训练依赖训练数据标签。例如,在欺诈检测模型中,训练数据标签是特定交易是否是欺诈性的。对于推荐引擎,则是客户是否点击或最终购买了推荐产品。

收集到新的训练数据标签后,下一步是根据训练样本数据评估模型的指标,并将其与训练阶段的模型指标进行比较,当差异超过阈值时,模型可以被认为是过时的,应该重新训练。

需要监控的指标通常有两种:

  • 统计类指标,如准确度、AUC、logloss 等。由于模型设计者可能已经选择了其中一个指标来选择最佳模型,因此它是监控的首选候选者。对于更复杂的模型,整体指标不够,可能需关注由子群体计算的指;
  • 业务指标,例如成本效益评估。 例如,信用评分业务已经制定了自己的特定指标;

统计类指标的优势是它与领域无关。为了获得最早的有意义的警告,甚至可以计算p值来评估观察到的下降不是由于随机波动引起。 而缺点是其指标下降可能在统计上显着而在业务层面没有任何明显的影响,或者更糟的是,再训练的成本与再部署相关的风险可能高于预期收益。 而业务指标更有用,它们通常具有商业价值,能够帮助业务人员在模型指标与再训练的成本上平衡。
如果可能的话,真实样本数据评估是最好的解决方案。 但是通常存在三个主要挑战:

  • 真实样本数据并不总是立即可用。对于某些业务场景,团队需要等待数月(或更长时间)才能获得真实的样本数据,如果模型指标训练下降,这可能意味着重大的经济损失;
  • 真实样本数据和样本标签是分离的。为了计算已部署模型在新的样本数据上的指标,需要样本数据与其对应的样本标签匹配。在生产环境中,这是一项具有挑战性的任务,这两条数据是在不同的系统中以不同的时间戳生成和存储的。对于低成本或短期模型,可能不值得自动收集真实数据与样本,并相互关联,这带来的成本提升,可能无法被模型指标带来的增益所cover;
  • 真实样本数据与标签仅部分可用。 在某些情况下,为所有算法场景过滤出可用的样本数据与标签,成本极大。比如,在推荐场景中, 这意味着选择要标记哪些样本是真实被用户观察过并且被用户选择或者未选择,这其中的困难将偏差引入系统;

无论如何, 进入模型再训练的真实样本子集需尽可能涵盖所有可能的情况,以便经过训练的模型无论后续样本如何都能做出符合预期的预测;

输入漂移检测

鉴于真实数据评估的成本以及局限性,一种更实用的方法是对样本输入进行漂移检测。
假设一种业务场景, 其目标是使用UCI葡萄酒质量数据集作为训练数据来预测波尔多葡萄酒的质量。
每种葡萄酒都有以下特征:类型、固定酸度、挥发性酸度、柠檬酸、残糖、氯化物、游离二氧化硫、总二氧化硫、密度、pH、硫酸盐和酒精度。为了简化建模问题,假设质量分数等于或大于 7 的葡萄酒是好酒。因此,目标是建立一个二元模型,从葡萄酒的属性中预测该标签。
为了演示数据漂移,我们明确地将原始数据集分成两部分:

  • wine_alcohol_above_11,其中包含所有酒精度为11% 及以上的葡萄酒;
  • wine_alcohol_below_11,包含所有酒精度低于11% 的葡萄酒;
    我们通过酒精度数超过11%来训练和评估我们的模型,低于11%数据将被视为部署模型的新的传入数据。
    这样的处理方式人为地制造了一个大问题:葡萄酒的质量不太可能独立于酒精度数。更糟糕的是,酒精含量可能与两个数据集中的其他特征有不同的相关性。所以,在超过11%的数据集上学到的模型能力(“如果残糖低且 pH 值高,那么葡萄酒好酒的概率就高”)可能在另一个数据集上完全是错误的。
    从数学上讲,不能假设每个数据集的样本来自相同的分布(即它们不是“相同分布的”)。而确保算法模型能取得预期效果的前提是:独立同分布,即要求训练与部署后接触的真实数据数据分布尽可能一致。而这里我们在第一个数据集上训练模型,然后在第二个数据集上部署它, 由此产生的偏移称为数据漂移。如果酒精水平是 ML 模型使用的特征之一(或者与模型使用的特征强相关),则称为特征漂移,而模型训练学习的模式本身不再成立时,则成为概念漂移

真实场景的漂移检测

如前文描述,为了能够及时做出反应,模型行为可仅基于输入数据的特征值进行监控,而无需等待真实样本数据与标签。
其正常逻辑是,如果数据分布(例如,均值、标准差、特征之间的相关性)在模型训练和验证阶段与真实部署场景所面对的数据之间存在差异,则表明模型的指标在这两种场景下是不可能相同的。

产生数据漂移的原因示例

数据漂移有两个常见的根本原因:

  • 样本选择偏差,其中训练样本不能代表总体样本。选择偏差通常源于数据收集管道本身,在葡萄酒示例中,酒精含量高于11%的原始数据集样本无法代表整个葡萄酒群体。请注意,这种原因在现实生活中说起来容易做起来难,因为有问题的通常是未知的、与场景相关、并且被检测的;
  • 非稳定环境,其中从数据源收集的训练数据不代表目标源。这通常发生在具有强烈季节性影响的时间相关任务。回到葡萄酒的例子:可以想象这样一种情况,原始数据集样本只包括特定年份的葡萄酒,这可能代表一个特别好的(或坏的)年份,在这些数据上训练的模型可能无法推广到其他年份;

输入漂移检测技术

在理解可能导致不同类型漂移的可能情况之后,接下来 的问题是:如何检测漂移? 本节介绍两种常见的方法,如何选择取决于对可解释性的需求:需要对结果进行解释的方法的情况应该更偏向单变量统计测试,而如果同时涉及多个特征的复杂漂移,或者如果数据科学家可以忍受黑盒,那么域分类器方法也可能是一个不错的选择:

单变量统计检验

此方法需要对来自每个特征的源分布和目标分布的数据进行统计。当这些评估存在严重偏差时,则说明存在较为严重的输入漂移。
假设检验在学术界进行了广泛研究,但基本方法依赖于这两个检验:

  • 对于连续特征,Kolmogorov-Smirnov检验是一种非参数假设检验,用于检查两个样本是否来自同一分布;
  • 对于离散类特征,卡方检验是一种实用的选择,用于检查目标数据中离散特征数据分布是否与源数据数据分布相匹配;
    通常会尝试使用p值来辅助进行漂移检测, p值的主要优点是它们有助于尽快检测漂移,主要缺点是没有量化效果的能力。因此,在真实场景下,有必要用具有业务意义的指标来补充p 值。

领域分类器

这类方法和最近比较火的对抗式的方法比较类似:训练模型,该模型试图区分原始数据集(输入特征和可选的预测目标)和开发数据集。换句话说,他们堆叠两个数据集并训练一个旨在预测数据来源的分类器。将模型的指标(例如其准确性)视为漂移水平的指标。如果该模型在其任务中是成功的,则具有较高的漂移分数,意味着可以区分训练时的数据和真实模型面对新数据,因此可以说新数据已经漂移。而为了获得更多信息,特别是要识别导致漂移的特征,可以使用该模型的特征重要性分数。

结果解释

领域分类器和单变量统计测试都指出了特征或标签对解释漂移的重要性。 归因于标签的漂移很重要,因为它通常直接影响业务。例如,考虑信用评分:如果整体评分较低,授予贷款的数量可能会较低,因此收入也会较低。)而归因于特征的漂移通常有助于减缓漂移的影响:

  • 根据此特征重新加权(例如,如果 60 岁以上的客户现在代表 60% 的用户,但在训练集中仅占 30%,则将其权重加倍并重新训练模型);
  • 删除该特征并在没有它的情况下训练一个新模型;
    在几乎所有场景下,即使检测到漂移,也不太可能存在自动操作。 如果部署再训练模型的成本很高,则仅当基于真实场景的指标下降或检测到显著漂移时,才会根据新的样本数据对模型进行再训练。

数据反馈

来自生产环境的数据需要流回模型原型环境进行进一步改进。
从下图可以看出,在监控和反馈中收集的数据被发送到模型开发阶段。相关系统分析模型是否按预期工作:如果是,则无需执行任何操作,如果模型的指标下降,则将自动或手动触发更新。 在实际场景中,要么使用新的样本数据重新训练模型,要么开发更强大的新模型。

无论哪种情况,数据监控与反馈系统的核心是能够捕捉即时的数据模式,并确保业务不会受到负面影响。 该系统的基础架构由三个主要组件组成,对构建强大MLOps能力至关重要:

  • 从多个生产服务器收集数据的日志系统;
  • 在不同模型版本之间进行版本控制、模型评估的模型评估系统;
  • 在线网环境中进行模型比较的在线系统,可以使用影子评分系统(冠军/挑战者)或A/B 测试;

日志系统

如今,随着生产基础设施变得越来越复杂,多场景、多版本、多数据源的模型同时部署在多个服务器上,有效的日志系统比以往任何时候都更加重要:
来自这些真实线网环境下的数据需要集中进行分析和监控,使得机器学习系统的持续改进成为可能,机器学习系统的事件日志是带有时间戳和以下信息的记录。

  • 模型元数据:型号和版本的标识;
  • 模型输入:新数据的特征值,可被用来判断新传入数据是否是模型所期望的,从而允许检测数据漂移;
  • 模型输出:模型的预测,连同后来收集的样本数据与标签,能够帮助计算模型在线网环境中的真实指标;
  • 系统动作:模型预测几乎不会是机器学习相关应用的最终产品,更常见的情况是系统会根据这个预测进行下一步操作。例如,在欺诈检测用例中,当模型给出高概率时,系统可以阻止交易或向银行发送警告。这类信息很重要,因为它会影响用户反应,从而间接影响反馈数据;
  • 模型解释: 在金融、医疗、自动驾驶等一些高度监管的领域,模型预测必须带有解释(即哪些特征对预测影响最大),此类信息通常使用Shapley等技术进行计算,并应记录下来以识别模型是否存在潜在问题(例如,偏差、过度拟合);

模型评估

一旦日志系统到位,它会定期从生产环境中获取数据以进行持续监控。直到有一天数据漂移警报被触发:传入的数据分布正在偏离训练数据分布,模型指标可能正在下降。
经过审查,算法同学通过重新训练模型来改进模型:对于几个经过训练的候选模型,下一步是将它们与部署的模型进行比较。 在实践中,这意味着在同一数据集上评估所有模型(候选模型集和部署模型)。如果其中一个候选模型的离线指标优于已部署的模型,则可以在生产环境中更新模型,通过冠军/挑战者或 A/B Test设置进行在线评估,这就是模型评估系统, 它允许算法同学进行以下操作:

  • 将多个新训练的模型版本与现有部署的版本进行比较;
  • 将模型与样本数据上的其他模型版本进行比较;
  • 随时间跟踪模型指标;

机器学习优化范式

构建机器学习相关应用程序是一个长期的迭代过程,从部署到生产、监控性能以及寻找改进系统如何解决目标问题的方法。迭代优化的方法有很多,包括:

  • 在新数据上重新训练相同的模型;
  • 向模型添加新特征;
  • 开发新算法模型;
    由于这些原因,机器学习场景随着时间不断变化。需要有一套成熟的机器学习优化的方法论来对机器学习业务进行优化, 这里称之为机器学习优化范式
    机器学习优化范式与以往我们解决其他软件任务的模式不同:让我们回到前面介绍的 wine 示例:部署三个月后,存在酒精含量较低的葡萄酒的新数据流入系统后,我们可以在新数据上重新训练我们的模型,从而使用相同的模型获得新的模型版本,也可能创建新的数据特征来添加到模型中,或者我们可能决定使用另一种机器学习模型(如深度学习模型)而不是 XGBoost。
    因此,该模型的机器学习优化范式
  • 线上模型不做任何修改;
  • 基于原始模型模板、新数据重新训练;
  • 使用新机器学习模型并且联合新数据进行训练;

模型评估存储系统

提醒一下,模型评估存储系统是集中管理模型生命周期相关的数据, 这些数据是允许被比较的。模型评估存储系统的两个主要任务是:

  • 随着时间的推移对按机器学习优化范式的优化行为进行版本控制:每个记录版本都必须附带其训练阶段的所有基本信息,包括:
    • 使用的所有特征;
    • 每个特征的预处理技术;
    • 使用的算法以及选择的超参数;
    • 训练数据集;
    • 用于评估训练模型的测试数据集;
    • 评估指标;
  • 比较机器学习优化范式重产生的不同版本之间的指标, 要决定部署哪个版本,必须在同样数据集上评估所有的这些版本(候选者和部署的模型)。
    选择要评估的数据集至关重要:如果有足够多的真实场景数据可以对模型指标进行可靠估计,因为它最接近我们在生产环境中数据;否则,我们可以使用部署模型的原始验证数据集,在数据没有漂移假设下,这让我们对候选模型与原始模型相比的指标有具体的了解。
    确定最佳候选模型后,工作尚未完成,在实际场景中,模型的离线和线网指标通常存在很大差异,因此,线网环境的测试至关重要, 线网环境的评估给出了关于候选模型在面对真实数据时的行为的最真实的反馈。

线网评估

从业务角度来看,生产模型的线网评估至关重要,而技术角度来看可能具有挑战性,在线评价主要有两种模式

  • 冠军/挑战者(也称为旁路测试),其中候选模型旁路部署并对相同的实时请求进行打分;
  • A/B测试,其中候选模型对线网部分实时请求进行打分,已部署的模型对其他请求进行评分
    这两种情况都需要真实数据反馈,因此,线网评估结果具有滞后性。

冠军/挑战者测试

冠军/挑战者(旁路测试)涉及将一个或多个候选模型(挑战者)部署到线网环境,候选模型接受与已部署模型(冠军)相同的请求。但是,它们不会向系统返回任何响应或预测结果。只需记录预测打分以供进一步分析。
冠军/挑战者测试被用来做两件事:

  • 验证候选模型的指标优于或至少与已部署模型一样好。因为这两个模型是在相同的数据上打分的,因此可以直接比较它们在线网环境的指标。当然,这也可以通过使用由冠军模型打分的新请求组成的数据集, 在候选模型来离线打分完成;
  • 测量候选模型如何处理线网实际负载(如rt、cpu使用率)。考虑到新模型可能有新的特征、新的数据预处理逻辑,甚至是新的模型结构,请求的预测时间不会和已部署模型一样,是否符合能上线的要求也是需要验证的;

A/B测试

A/B 测试(测试两个变体 A 和 B 的随机实验)是软件应用优化中广泛使用的技术:

  • 对于类似推荐场景的应用,模型给出了给定客户可能会点击的item列表。因此,如果商品没有出现,就不可能知道客户是否会点击。在这种情况下,进行A/B测试,其中一些客户会看到模型A的推荐,而一些客户会看到模型B的推荐;
  • 优化的目标仅与预测的指标间接相关:如广告引擎,它可以预测用户是否会点击广告,假设它是根据购买率来评估的,即用户是否购买了产品或服务,而每一次,不可能记录用户对两种不同模型的反应;
2022/04/04 posted in  mlops

mlops之监控与数据回流

12345678 90
但是机器学习模型部署到生产的创新之后模型会从开始的性能比较好快速的跌到性能比较差因此我们的模型系统需要进行一个完整的监控

2022/03/26 posted in  mlops

为机器学习量身定做的ops工具:cml & dvc

动机

写这篇文章初衷是最近工作在做一些关于机器学习流程化的工作。现阶段,算法上的创新一天一个样,很多时候,算法同学会去试, 如何能搞提升较高的效率, 每个算法同学的手段都不同,回想计算机科学发展至今天,从野蛮生长到模块化、流程化、标准化。机器学习无外如是。而最近工作涉及到关于mlops相关的事情,其难度很大,不在乎技术本身,当中涉及到太多的以往的技术债。很难去设计本来mlops应该做的东西,另外在某个微信群里讨论,算法同学应该怎样增加工程能力
IMG_1454
其实个人认为算法相关的工程能力也不是去一定专注model service,写部署服务这些,个人认为凡是提升算法工程当中的效率,皆可以算作工程能力。基于这两个原因以及自己的职业规划,细了解了开源相关的工作,窃以为开源虽然有时候很难落地企业实际场景,但是其思想很纯粹, 值得我们去学习,这一系列的文章应该会比较多,今天先介绍cml 和dvc。

cml 第一次尝试

git clone https://github.com/burness/example_cml

定义一个train-my-model的workflow:

name: train-my-model
on: [push]
jobs:
  run:
    runs-on: [ubuntu-latest]
    container: docker://dvcorg/cml-py3:latest
    steps:
    - uses: actions/checkout@v2
    - name: cml_run
      env:
        repo_token: ${{ secrets.GITHUB_TOKEN }}
      run: |
        pip install -r requirements.txt
        python train.py

        cat metrics.txt >> report.md
        cml-publish confusion_matrix.png --md >> report.md
        cml-send-comment report.md

几个关键点:

  1. 定义一个train-my-model的工作流,该工作流在代码被push到仓库当中任一分支时触发;
  2. 启动dvcorg/cml-py3:latest 容器,使用action/checkout@v2,拉取项目源码(这个是在github专门提供的机器上完成的,github hosted runner和self hosted runner的差异);
  3. 从requirements.txt安装项目所需python包,运行train.py, 并将结果(metrics.txt, cufusion_matrix.png)重定向到report.md,然后将report转换为下图的评论;

修改代码当中模型某一参数后, 提交后,触发该工作流:

查看任意工作流的日志记录:


pip install -r requirements.txt

python train.py

dvc

dvc demo演示

第一节介绍了基于github actions,如何去做持续机器学习的工作流,算是一个简单的demo,接下来演示,当训练数据过大时,github无法使用时,应该如何处理,这里我们先做个演示,后续再来讲解。

先安装个dvc

pip install dvc

dvc init 有个报错
ERROR: unexpected error - 'PosixPath' object has no attribute 'read_text', 这里后面遇到experiments,又跳转会pip安装,并且卸载 pathlib即可: pip uninstall pathlib.
改用安装包

git clone https://github.com/burness/mlops_tutorial2

在google 云硬盘上创建一个目录, 复制folders之后的字段

dvc remote add -d mlops_toturial2 gdrive://1ybWU9o_A38z0VIzXpBzRMsoTdcrjKqC7

commit and push

运行代码get_data.py, 下载需要使用的数据文件

运行dvc add data.csv

commit and push:


dvc 推送数据到google drive:


由于是第一次登陆, dvc需要你将图上链接粘贴到浏览器,然后得到一个验证码,复制进来,然后就开始数据push:

名字有一个变化:

因为我在公司,可以看外网资料, 这边没有两台电脑,为了方便演示, 我从github上clone项目代码到另一个目录:

dvc pull:

dvc 功能详解

数据与模型版本管理:

如前面一小节里, 我们dvc add data.csv, 生成data.csv.dvc, 那么我们看下对应dvc里面的内容:

那么,我们现在对数据 做一些更改,删除两行数据后,重新dvc add:


git 提交, dvc push:

我们到google drive上看, 又多了一个版本:

到现在为止, 我们有那个dataset, 怎么转回到之前的那个数据集呢?先git checkout 某个版本,然后dvc checkout即可

我们的数据就回来了,更好地一种是通过branch 来管理,这里就不尝试了,大家可以试试。

数据、模型访问

dvc list https://github.com/burness/mlops_tutorial2可以直接列出,项目当中使用dvc保存的数据文件,而注意这些文件并没有保存在github上。

dvc get https://github.com/burness/mlops_tutorial2 data.csv,可以在任意路径来download数据:

其他命令,如dvc import可以具体去看相关帮助信息了解;

数据结合pipeline

前面演示了如何使用dvc管理你的dataset文件,当然model文件也可以同样管理,但是这还不够,接下来会演示dvc如何保存数据的pipelines,在演示之前,我们拿到演示需要的代码:

 wget https://code.dvc.org/get-started/code.zip
 unzip code.zip
 rm -f code.zip

安装数据处理所需的依赖:

pip install -r src/requirements.txt

运行命令:

dvc run -n prepare \
          -p prepare.seed,prepare.split \
          -d src/prepare.py -d data/data.xml \
          -o data/prepared \
          python src/prepare.py data/data.xml

将数据文件按对应参数,切分成train.tsv与test.tsv:


对应dvc.yaml里内容记录:

下一步,将prepare的数据进行特征处理:

dvc run -n featurize \
          -p featurize.max_features,featurize.ngrams \
          -d src/featurization.py -d data/prepared \
          -o data/features \
          python src/featurization.py data/prepared data/features

yaml文件如下:

继续增加训练过程:

dvc run -n train \
      -p train.seed,train.n_est,train.min_split \
      -d src/train.py -d data/features \
      -o model.pkl \
      python src/train.py data/features model.pkl

相关产出:

dvc.yaml文件如下:

接下来只需要执行dvc repro,即可重现dvc pipeline:

我们修改下params里面的参数split:0.20->0.15, n_est:50->100:

最后dvc dag:

pipeline与metric、parameter、plots结合

继续上面的演示来, 我们构建如上图的一个pipeline之后,接下来做模型的评估, 其中-M指定该文件为metric文件, --plots-no-cache 表明dvc不cache该文件:

dvc run -n evaluate \
      -d src/evaluate.py -d model.pkl -d data/features \
      -M scores.json \
      --plots-no-cache prc.json \
      --plots-no-cache roc.json \
      python src/evaluate.py model.pkl \
             data/features scores.json prc.json roc.json

dvc.yaml又增加evaluate过程, 其中evaluate生成对应的score.json, prc.json, roc.json:

查看score.json:

dvc plots modify prc.json -x recall -y precision
dvc plots modify roc.json -x fpr -y tpr

运行dvc plots show:

修改params.yaml中的max_features=1500, ngrams=2。
重新运行整个pipeline:

dvc repro

git保存&提交:

git add .
git commit -a -m "Create evaluation stage"

再次修改params.yaml中的max_features=200, ngrams=1, 运行整个pipeline:

dvc plots diff画出不同参数版本的效果差异:

dvc与experiments

在dvc中,使用experiments来构建不同实验组,来进行超参的调试:

dvc exp run --set-param featurize.max_features=3000 --set-param featurize.ngrams=2将max_features配置为3000, 并且运行整个pipeline:

对比实验:

缓存实验队列:

dvc exp run --queue -S train.min_split=8
dvc exp run --queue -S train.min_split=64
dvc exp run --queue -S train.min_split=2 -S train.n_est=100
dvc exp run --queue -S train.min_split=8 -S train.n_est=100
dvc exp run --queue -S train.min_split=64 -S train.n_est=100

开始运行, 其中并行任务为2, 这里遇到个小插曲,改用pip安装即可,写在pathlib即可:

dvc exp run --run-all --jobs 2

我们看到最好的auc 效果为79d541b, 实验id为exp-f6079, 我们将这个持久化,并且查看现在score.json:

dvc push 保存至远端

这里我push失败dvc exp push gitremote xx, 应该是和我项目git remote前后不一致相关,,dvc exp pull gitremote xxx ,小问题, 这里不影响 不做过多计较;

##总结
不知道大家有没有把文章看完,很长(后续应该还有cml和dvc其他方面的实践,比如self-hosted runner, 太长了就拆开)。不过归根到底,无非就是那么几块东西:

  1. 如何将你的算法代码、数据、配置、模型、实验管理起来;
  2. 将你所管理的信息,能够分享、复制、快速复现;
  3. 所有的流程都可以记录,可以版本管理;

文章上面相关的技术工作是iterative.ai/这家公司的成果。虽然无法直接拿到企业中使用,但是其中的思想以及设计理念值得学习。接下来的文章,我将参考他们的设计思想,试着去设计符合企业界的mlops。 有兴趣,欢迎讨论。

2021/07/21 posted in  mlops

[toc]

技术调研报告

需求场景

云音乐在边缘计算上的需求较为丰富,主要集中在两个点上:

  1. 边缘数据处理;
  2. 边缘模型推理;

前者主要目的是缓解基础数据处理在服务端压力, 并且在越来越严的监管压力下,进行某些数据的脱敏处理之后上传,如某些poi,在边缘端在客户端完成提取之后,脱敏上传,扫描更多用户信息,提取相关标签;
边缘模型推理,主要是指将模型部署下发到移动侧,完成推理,如检测直播中是否有人脸出现、评论是否涉黄涉恐等;
本报告接下来分为三个部分来描述业界类似的场景需求,以及相关的技术方案;

边缘数据处理###

业界需求

边缘数据处理

场景一

工业设定的边缘环境(例如海上石油勘探平台)往往缺乏
充足的计算,存储和网络资源有限,且设备生成数据量极大,全部传输不仅占用极大资源,且意义不大,所以业务开发边缘分析程序来进行关键数据的分析、脱敏等操作,之后将处理完成的数据传输至服务器端进行进一步挖掘;

场景二

自动驾驶侧,由于驾驶本身对反馈数据的时延要求极高,将数据传回网络侧进行计算处理,再反馈相应处理逻辑整体耗时随着网络的不稳定而变化极大,在边缘侧计算关键数据的计算,包括模型推理,进行及时的决策反馈;

场景三

欧盟GDPR法规,限制欧盟之外的任何公司, 针对于不符合在隐私数据上规范的公司处以最高罚款为其全球收入的4%或2000万欧,两者取高者。政策越来越严的规范, 数据不离开用户设备必然会成为后续的趋势,这对于推荐、搜索、广告等核心互联网业务会造成毁灭性的打击,边缘侧进行必要的数据处理,传回有价值的、脱敏、符合政策法规的数据,

####云音乐场景####

需求一: 辅助埋点完成脏、乱数据治理,数据生产侧完成数据质量保障

和团队@董有现讨论,目前埋点逻辑由相关产品收集, 反馈至客户端,客户端完成相关功能开发后,由数据团队进行数据质量检查,完成检查之后上线,数据埋点日志落存储,大数据同学再进行相关功能的开发,数据同学反馈会存在很多异常情况(本身数据质量:如数值为空情况、数据明显异常如播放点负数、), 是否能将脏、乱数据治理,直接落地在边缘侧处理, 脏、乱数据治理,埋点同学最熟悉,可以在此完成逻辑的闭环,如下图展示:
埋点改造

需求二:边缘侧进行数据聚合, 生成更详尽指标
单个指标通常应用到算法,会经过一些基本的聚合处理,比如按时间构造多尺度(天级别、周级别)播放时间、按多source聚合指标,此类指标仅依赖用户本身行为,可选择在边缘侧进行数据聚合,如下图:可以选择边缘侧进行时间聚合、多source聚合,在边缘侧可进行数据异常处理、这部分工作如何在大数据上去做,其实相对还是比较复杂的,因为埋点逻辑不可避免地会落地异常数据,其实在大数据侧很难完全处理掉这部分数据,因而不仅仅是效率问题,边缘侧的数据聚合能够有效地将客户端处理逻辑闭合,提供更高智能、更易用的数据,另一方面,在大数据环境下进行相关数据的聚合,整体资源消耗较大;
边缘数据处理-详尽数据

需求三:数据敏感,减少法律法规风险
目前国内外隐私相关法律法规如GDPR针对Google、Facebook天价罚款,《中华人民共和国民法典》对隐私权与个人信息保护越来越严,互联网公司尤其是移动侧数据采集,必然越来越严格。对整体数据应用会有极大地影响。移动侧后续在数据采集上,可能需要考虑关键数据的脱敏,同时保证尽可能少地影响算法效果;

###边缘模型推理###
####为什么云音乐需求边缘模型推理####

  1. 脱机可用性:这可能是最明显的论点。如果无论条件和连接性如何都需要应用程序可用,则必须将智能放置在本地设备中。由于远程蜂窝数据不稳定,DDoS攻击后服务中断或仅仅是因为你的设备正在地下室中使用,会导致连接中断!对于基于云的解决方案来说,这是一个巨大的挑战。但是,如果将智能放在本地设备上,则无需担心;
  2. 降低云服务成本:云服务非常方便(可扩展性,可用性),但是却代表着相当安规成本,随着越来越多的人使用解决方案,这种成本将会增加,尤其是AI类的推理应用, 这些成本将持续到产品的整个生命周期, 而边缘侧进行模型推理,利用了用户本身的算力来完成相关模型的推理计算,大大降低在类似场景下的成本付出;
  3. 降低连接成本:边缘侧完成模型就散,仅发送AI的计算结果,就地处理信息可以将带宽消耗除以100倍(对于视频则更多),尤其是对于视频类应用,通常计算集群和存储集群是分开的,完成相关的推理计算,需要频繁地拷贝,若在边缘侧完成模型的推理计算,需要传输的数据将从兆字节的视频将转换为几个字节,比如主播人脸是否存在,而不是将视频数据拷贝至相应地计算集群,完成模型推理,仅仅需要边缘侧完成计算即可;
  4. 处理机密信息:当可以在本地收集和处理关键信息时,无需将数据传至数据中心处理,但是依然能完成相关地逻辑需求,如通过判断直播场景下是否有人,而非将直播关键的数据实时传输到计算集群上,来进行相关计算,这个成本是极其昂贵的;
  5. 响应时间至关重要:在本地收集和处理数据很会缩短响应时间,从而改善用户体验,目前的手机侧通常拥有比较不错的算力,能应付一些模型的推理计算;
  6. 环保:中小型物联网设备每天将发送1MB或更少的数据,大约可以每天估算20g的二氧化碳,经过一年的计算,10,000台设备可产生多达73吨的二氧化碳!在本地进行处理可以将其缩小到730kg, 数据中心电力的消耗也极大,尤其是在进行密集型计算时,单个gpu设备可能达到250w的工作效率,而基于视频或图像的解决方案可能会产生更大的影响,未来在数据搜集上都可能缴税的政策锋线上,碳排放、电力消耗的缴税风险可能更大,其成本也不容忽视;
  7. 硬件优化到一定程度;

可行性分析

###边缘数据中心与数据处理:进一步贴近接入层###

学术界与行业相关工作
前两年在学术界有相关的文章,如Secure and Sustainable Load Balancing of
Edge Datacenters in Fog Computing
,提出Edge Data Center的概念;Potentials, Trends, and Prospects in Edge Technologies:
Fog, Cloudlet, Mobile Edge, and Micro Data Centers
也提到边缘侧数据中心,更近地贴近边缘侧完成部分数据的存储、计算,来提供移动侧内计算能力,减少传统数据中心的数据计算压力,提供更稳定时延服务;
业界包括华为、https://www.siemon.com/zh/home/applications/edge在5g上的布局也包括边缘侧完成部署计算,包括组件边缘数据中心,详情见[面向5g的边缘数据中心基础设施](https://e.huawei.com/cn/material/networkenergy/e7940fd56def4524aa1d0e4a8f835f99)、[边缘数据中心](https://www.siemon.com/zh/home/applications/edge)。
边缘数据中心,其目的在于减少边缘侧数据存储计算的时延,尤其是在占大量带宽的数据计算、视频分析等关键AI应用上,相关行业目前技术尤其是数据存储、计算,确实有向边缘侧靠的趋势。

云音乐实际情况
而针对云音乐目前的痛点,尤其是在数据处理时,集群压力极大,目前整体,移动端进行必要的部分数据存储以及部分指标的计算,是比较合理的

  1. 目前,边缘侧数据处理仅基于用户尺度做较为简单地数据聚合、数据加密、脱敏操作,其计算复杂性不高,理论上可以适合计算;
  2. 边缘侧完成的更高级指标的计算,能够被大数据工作流直接使用,比原先大数据侧进行数据去脏、去错再进行相关计算,理论上精确度更高;
  3. 边缘侧完成相关数据的计算前提在于其对数据质量、数据内容有极高的保障,并且有相应地去脏除错逻辑,在此背景下,更易于大数据埋点需求做到解耦合;
  4. 边缘侧目前cpu、gpu性能较为强劲,边缘侧已经能支持较为复杂的矩阵线性计算,如大kernel cnn,理论上简单地数据处理逻辑理论上不在话下;

###边缘模型推理###

标准化的开发流程
边缘模型推理目前是各大互联网公司着力落地的点,需求比较明显,这里就不详述,主要是将部分模型的推理部署在移动侧,减少由于网络传输带来的安全风险以及时延问题,目前整体的技术方案如下图大概分成以下几个部分,下面会详细描述:

边缘模型推理流程

  1. 离线特征处理:主要目的是生产训练样本,如评论是否涉黄、涉恐分类模型,需要收集评论数据,并标准为相关类别;
  2. 离线模型训练:使用包括TensorFlow、Paddle、Pytorch等在内的框架来训练相关离线模型;
  3. 离线模型评估:将训练好的模型在指定的验证集上进行模型评估,得到离线评估指标;
  4. 模型转换:将训练出来的模型转换为移动侧支持的模型,并附上指定SDK Demo;
  5. 模型验证:在指定SDK上验证转换生成的模型文件,开发对应的数据处理逻辑,完成模型功能、以及时延验证;
  6. 模型下发:验证完成之后,通过专有平台将模型批量下发给客户端;
  7. 模型更新:下发完成后,进行模型文件更新, 将新版本的模型文件以及对应逻辑的包更新;

####离线特征处理####
主要负责生产训练样本,包括特征的基本处理以及样本的标准,如在直播场景下,检测视频当中是否出现主播人脸,人脸检测在直播场景,需要提前标注一定量级的的人脸标注照片, 下图中红框、红点为关键点检测标注信息:

完成标注之后,通常我们会将标注数据处理成适合某些框架训练的数据格式,如TensorFlow下tfrecord。

####离线模型训练####

离线魔性训练,通常我们会用TensorFlow或者Pytorch构造合适的神经网络结构,如针对人脸检测比较出名的MTCNN,MTCNN网络复杂性设计的比较好, 可以在中端手机上部署,完成20~30FPS的检测速率:

####离线模型评估####
离线模型训练之后,我们会在一个合适的数据集上进行模型评估,待数据集上指标满足要求之后,再开始考虑上线,离线评估数据集通常是业务落地时面对的真实数据集,在这个数据上的评估指标,最接近真实数据,通常在满足指标要求,都会经过多轮的迭代,通过data augmentation等数据增广,或者直接补齐某些效果不好场景下的训练数据,来逐步提升模型在各类场景下的鲁棒性;

####模型转换####

模型转换目的是为了将适合服务端计算的模型文件转换为专门针对移动端进行算子优化的框架,如paddle lite提供将其他框架如TensorFlow、Caffe等转换为paddlepaddle的原生工具X2Paddle, 且在转换过程中支持包括量化、子图融合、Kernel优选的优化手段,优化之后的模型更轻量级、耗费资源更少、更适合在移动侧部署,目前比较流行的移动侧框架,网商的某个性能对比:

为了防止对业务造成影响,一般都是单线程使用,且关闭openmp防止帧间波动影响体验,整体结论:

paddle-lite>mnn>ncnn>tflite

另外的如apple本身的Core ML,因为仅支持ios。

####模型验证####

模型验证主要是进行移动端编译的验证,通过这个过程,框架侧会提供一个最简化的演示的sdk,支持build成移动侧的app,然后通过比如adb在手机侧进行推理,评估资源消耗、耗电以及模型推理耗时。
比如paddle lite的一个demo: https://github.com/PaddlePaddle/Paddle-Lite-Demo/tree/master/PaddleLite-android-demo/face_detection_demo

####模型框架集成####

模型验证完成之后,集成到客户端app中,这里需要考虑引入新的模型框架带来的app包体积增大以及app耗时增加的问题,如目前paddle-lite 目前整体包ARMV7只有800K,ARMV8下为1.3M

####模型/框架热更新####

模型部署成功之后,后续模型框架、模型文件更新是比较频繁的,不可能每次发版本来更新客户端的离线模型,主要包括两个部分:

  1. 模型文件的更新:模型推理框架无需更新,仅更新模型文件;
  2. 模型推理包的更新:需要更新推理框架以及模型文件;

挑战

###边缘数据处理###

  1. 相关开源项目比较少, 且活跃度不高:
    目前边缘数据处理开源的不多,并且活跃度不大,如下面的apacheEdgent,边缘计算相关的开源框架和产品主要集中在如何组装,采用类似于K8S编排设备的技术来完成边缘设备的编排,主要是针对有限网络下快速的组网、设备管理等工作,做数据处理的封装目前没看到太多的解决方案:

    1. apacheEdgent: https://edgent.incubator.apache.org/
    2. Akraino Edge Stack:https://www.lfedge.org/category/akraino-edge-stack/
    3. AWS IoT Greengrass: https://aws.amazon.com/cn/greengrass/
    4. Azure IoT Edge: https://github.com/Azure/iotedge
    5. baetyl: https://github.com/baetyl/baetyl
    6. Macchina.io: https://macchina.io/

    目前,在云音乐的需求中,边缘的主要针对于做用户维度的、时间维度的聚合操作,这里需要一些专门的算子,如map、reduce,用于专项处理埋点数据中的转换、聚合操作,这里需要联合客户端同学,可先完成相关功能的封装,建议开始按功能如按天聚合播放时间等case by case 开发,后续抽象出来,由数据组提供相应sdk;

  2. 脱敏加密数据上传涉及到的隐私保护计算,目前整体积累较差,相关的技术水平要求高:

    1. 如手机号、身份证这类数据,可在端侧进行脱敏处理,类似手机号、身份证无论在算法还是数据处理上,其实仅充当统一性表示ID, 进行脱敏处理不影响其落地应用,但是否有涉及到比如推送号码包类似应用需要,如有需要,在此类场景下需提供专门解码方法完成加密数据的解码;
    2. 如有数据保存至公有平台进行数据分析时,可采用同态加密技术,同态加密技术旨在分析可以在不拿到明文数据的前提下,进行数据分析等相关操作;
  3. 目前无法很好地评估,增加边缘侧数据处理带来的性能问题,如电量耗损、cpu占用过多影响体验、磁盘读写占用等等问题; // 使用闲时处理、闲时上传;

  4. 边缘侧数据处理和原先类似埋点开发过程中,需要保持一致性的地方,这一块如何保证;

  5. 原始埋点数据上,增加业务场景线上,两条路走;

###边缘模型推理###

边缘模型推理目前挑战点主要在于:

  1. 目前虽然移动侧模型推理较为流行,但是并不是所有的训练框架算子均支持移动侧部署,或已在移动侧深度优化,边缘侧部署需要和模型训练侧深度合作;
  2. 边缘模型将部分模型的app打包到本地,模型以及相关包均在用户侧,这其中可能涉及到模型的相关风险,在一些核心应用,例如身份验证这类场景下,涉及到相关的安防技术,如目前通过deepfake技术使一些人脸识别系统出错, 如何安全的访问模型请求也是现有的挑战;
  3. 模型定时更新涉及到大规模的模型下发,尤其在云音乐这种规模下的模型下发,这块我们不太熟悉,无法评估风险;
  4. 模型推理下放到边缘端计算,必然在资源上消耗较多,如果减少资源负载也是必须要要考虑的问题;
2020/09/18 posted in  mlops