图片描述git
「观远AI实战」
栏目文章由观远数据算法天团倾力打造,观小编整理编辑。这里将不按期推送关于机器学习,数据挖掘,特征重要性等干货分享。本文8千多字,约须要16分钟阅读时间。
机器学习做为时下最为火热的技术之一受到了普遍的关注。咱们天天打开公众号都能收到各类前沿进展、论文解读、最新教程的推送。这些文章中绝大多数内容都跟酷炫的新模型、高大上的数学推导有关。可是Peter Norvig说过,“We don’t have better algorithms. We just have more data.”。在实际机器学习应用中,对最终结果起到决定性做用的每每是精心收集处理的高质量数据。github
从表面看好像也不难,但略微深究就会发现机器学习系统与传统的软件工程项目有着很是大的差别。除了广受瞩目的模型算法,良好的工程化思考与实现是最终达到机器学习项目成功的另外一大关键因素。算法
谷歌在2015年发表的论文《Hidden Technical Debt in Machine Learning Systems》中就很好的总结了机器学习工程中的各类不佳实践致使的技术债问题。主要有如下几种:安全
在传统的软件工程中,通常会进行细致的设计和抽象,对于系统的各个组成部分进行良好的模块划分,这样整个系统的演进和维护都会处于一个比较可控的状态。但机器学习系统自然就与数据存在必定程度的耦合,加上自然的交互式、实验性开发方式,很容易就会把数据清洗、特征工程、模型训练等模块耦合在一块儿,牵一发而动全身,致使后续添加新特征,作不一样的实验验证都会变得愈来愈慢,愈来愈困难。多线程
传统的软件工程开发中,能够很方便的经过编译器,静态分析等手段获取到代码中的各类依赖关系,快速发现不合理的耦合设计,而后借助于单元测试等手段快速重构改进。在机器学习系统中这类代码耦合分析一样不可或缺。除此以外还多了数据依赖问题。架构
好比销售预测系统可能会对接终端POS系统数据,也会引入市场部门的营销数据,还有仓储、运输等等多种数据来源。在大多数状况下这些数据源都是不一样部门维护的,不受数据算法团队的控制,指不定哪天就悄悄作了一个变动。若是变动很大,可能在作数据处理或者模型训练时会直接抛出错误,但大多数状况下你的系统仍是能正常运行,而获得的训练预测结果极可能就有问题了。框架
在一些复杂业务系统中,这些数据自己还会被加工成各类中间数据集,同时被几个数据分析预测任务共享,造成复杂的依赖关系网,进一步加大了数据管理的难度。机器学习
胶水代码:随着各类开源项目的百花齐放,不少机器学习项目都会调用各类开源库来作数据处理、模型训练、参数调优等环节。因而天然而然在整个项目中大量的代码都是为了把这些不一样的开源库粘合在一块儿的胶水代码,一样会致使以前提到过的边界模糊,与特定的库紧耦合,难以替换模块快速演进等问题。分布式
流水线丛林:在数据处理特征工程与模型调优的迭代演进过程当中,稍不注意你的整个系统流水线就会变得无比冗长,各类中间结果的写入和先后依赖极其复杂。这时候想添加一个新特征,或是调试某个执行失败都变得如此困难,逐渐迷失在这混乱的丛林中……若是只具有机器学习知识而缺乏工程经验,用这种作实验的方式来开发系统显然是不靠谱的,必须有良好的工程化思惟,从整体上把控代码模块结构,才能更好的平衡实验的灵活性与系统开发效率,保证总体的高效运做。 函数
失效的实验性代码路径:这一点也是承接前面,不少时候若是以跑实验的心态来给系统“添砖加瓦”,极可能到后面各类小径交叉的代码库就这么出现了,谁都搞不清楚哪些代码有用哪些是不会执行到的。如何复现别人的实验结果,要用哪些数据集和特征,设置哪些变量、作哪些微调都会成为难解之谜。
缺少好的系统抽象:我的以为sklearn的各类API设计还算蛮好的,如今不少其它库的高层API都参考了这个准业界标准来实现。文中主要提到在分布式训练中缺少一个很好的业界标准,好比MapReduce显然是不行的,Parameter Server看起来还算靠谱但也还未成为标准。没有好的抽象标准也就致使了各类库在功能、接口设计时不一致,从而有了以上提到的一系列边界模糊,胶水代码等问题。
相对于传统软件系统,机器学习系统的配置项每每会更多更复杂。好比要使用哪些特征、各类数据选择的规则、复杂的预处理和后置处理、模型自己的各类参数设置等等。所以除了工程代码外,配置项的精心设计、评审也成了一个不容忽视的点。不然很容易形成系统在实际运行中频繁出错,难以使用。
机器学习系统不少时候都是直接与外部世界的数据作交互,而外部世界老是变化无常。并且机器学习系统自己的输出也会影响到外部世界,从而进一步回馈到机器学习系统的输入中来。好比推荐系统给用户展现的内容会影响用户的点击行为,而这些点击浏览行为又会成为训练数据输入到推荐系统来。如何获取到外部世界变化的信息,进而及时改进甚至自动更新算法模型就成了一个很是重要的问题。
在谷歌的这篇原始论文中对各类坑都给了一些解决的建议,概括总结一下,整体上来讲就是要转变团队总体的文化氛围,强调良好的工程思惟和实践。一个设计良好的机器学习项目系统中每每真正跟机器学习相关的代码只占了很小的一部分。
图片描述
新模型当然酷炫,可是机器学习工程实践的总结与推广与它在整个项目中扮演的角色的重要性显然是不成正比的。因此今天咱们要着重来说一下这个方面:机器学习系统的最佳工程实践是什么样的?
这时候就要请出谷歌的另一篇论文《The ML Test Score》了。前一篇论文在具体实践落地方面缺少细节,在这篇论文里,谷歌总结了28个很是具体的机器学习系统相关工程实践准则,可谓是干货满满,十分接地气。
文中给出的28个建议都是针对机器学习系统的,没有包含通用软件工程里那些单元测试,发布流程等内容,在实践中这些传统最佳实践也一样很是重要。这些实践在谷歌内部团队普遍使用,但没有一个团队执行的覆盖率超过80%,所以这些测试点都是很是值得关注并有必定的实践难度的。
特征指望值编写到schema中:不少特征的分布状况或数值指望是有一些先验知识能够去校验的。好比通常人身高都在0-3米的范围内、英语中最多见的词是”the”、总体的词频通常服从幂律分布等。咱们能够把这些先验领域知识,或是从训练集中计算出的数学指望值编写在数据schema文件中,后续对于新的输入数据,构建完特征后的模型训练数据以及最终上线使用模型时都能进行自动化的检查,避免由于数据不符合预期而致使的错误预测状况。
确保全部的特征都是有用的:在以前的机器学习技术债论文中也有提到研发人员老是倾向于不断往系统中添加新的特征,尤为在上线时间比较紧迫的状况下,缺乏细致的特征选择和有效性验证工做。这会致使特征数量愈来愈多,构建训练集须要花费的时间也愈来愈长,后续的维护成本也会更高。因此跟业务代码同样,没有帮助的特征也要及时清理,轻装前行。文中给出的方法基本是常见的特征选择法,好比计算特征相关度,使用单独或小批量特征来跑模型看是否有预测能力等。
去除性价比低的特征:计算添加任何一个特征都须要消耗资源,包括生成和训练模型开销,模型预测开销,甚至还要考虑到对上游数据的依赖,额外的库函数引入,特征自己的不稳定性等等。对于任何一个特征的添加,都要综合考虑这些开销与它能带来的性能提高来决定是否引入。若是只是很是有限的效果提高,咱们应该果断放弃那些过于复杂的特征。
特征必须遵循业务规范需求:不一样的项目对机器学习系统可使用的数据可能有不一样的规范需求,好比可能有些业务禁止咱们使用从用户数据中推演出来的特征。因此咱们也须要从代码工程层面把这些规范需求进行实现,以免训练与线上特征出现不一致或违反了业务规范等问题。
数据流水线必须有完善的隐私控制:与上一条相似,机器学习系统从数据源获取用户相关隐私数据时已经经过了相应的控制校验,后续在系统内部流水线作处理时咱们也要时刻注意对隐私数据的访问控制。好比各类中间数据集,数据字典的存放与访问控制,上游系统的用户数据删除可以级联更新到机器学习系统的整个链路中,诸如此类须要特别注意的问题。
可以快速开发新特征:一个新特征从提出到实现,测试,上线的整个流程所须要花费的时间决定了整个机器系统迭代演进,响应外部变化的速度。要实现这一点,良好的工程结构、不一样模块的抽象设计都是很是重要的。文中没有给具体的例子,不过咱们能够借鉴sklearn中pipeline模块设计的思想,以及相似FeatureHub这样的开源系统的实现来不断优化完善特征工程实践。
为特征工程代码写相应的测试:在实验探索阶段,咱们常常会写完一个特征以后,粗略地取样一些数据,大体验证经过后就认为这个特征基本没有问题了。但这其中可能就隐藏了很多bug,并且不像业务代码中的错误,要发现这些bug极其困难。因此必须养成良好的习惯,在特征开发阶段就写好相应的测试代码,确保特征的正确性,后续应对各类系统变动也都能很快经过测试来进行快速验证。
图片描述
模型说明必须经过review并记录在案:随着机器学习模型技术的发展,各类复杂模型,大量的参数配置每每让模型训练和执行变得无比复杂。加上在多人协同的项目中,不少时候须要使用不一样的数据,或者作一些特定的调整来从新评估模型效果,这时候有详细的模型说明记录就显得尤其重要了。除了简单的文本记录,市面上也有很多开源项目(好比ModelDB,MLflow等)专一于帮助开发者管理模型,提升实验的可复现性。
模型优化指标与业务指标一致:不少机器学习的应用业务中,实际的业务指标并不能直接拿来做为目标函数优化,好比业务营收,用户满意度等等。所以大多数模型在优化时都会选择一个“代理指标”,好比用户点击率的logloss之类。所以在建模,评估过程当中必需要考虑到这个代理指标与真实业务指标是否有比较强的正相关性。咱们能够经过各类A/B测试来进行评估,若是代理指标的改进没法提高真正的业务指标,就须要及时进行调整。
调优模型超参数:这点相信你们都会作,毕竟各类机器学习教程中都会有很大篇幅讲解如何进行调参来提高模型效果。值得注意的是除了暴力的网格搜索,随机搜索一样简单而效果每每更好。另外还有许多更高级的算法例如贝叶斯优化,SMAC等也能够尝试使用。对于同一个数据集,在使用不一样的特征组合,数据抽样手段的时候理论上来讲都应该进行参数调优以达到最佳效果。这部分的工做也是比较容易经过自动化工具来实现的。
对模型时效性有感知:对于不少输入数据快速变化的业务例如推荐系统,金融应用等,模型的时效性就显得极其重要了。若是没有及时训练更新模型的机制,整个系统的运行效果可能会快速降低。咱们能够经过保留多个版本的旧模型,使用A/B测试等手段来推演模型效果与时间推移的关系,并以此来制定总体模型的更新策略。
模型应该优于基准测试:对于咱们开发的复杂模型,咱们应该时常拿它与一些简单的基准模型进行测试比较。若是须要花费大量精力调优的模型效果相比简单的线性模型甚至统计预测都没有明显提高的话,咱们就要仔细权衡一下使用复杂模型或作进一步研发改进的必要性了。
模型效果在不一样数据切片上表现都应达标:在验证模型效果时,咱们不能仅依赖于一个整体的验证集或是交叉验证指标。应该在不一样维度下对数据进行切分后分别验证,便于咱们对模型效果有更细粒度上的理解。不然一些细粒度上的问题很容易被整体统计指标所掩盖,同时这些更细粒度的模型问题也能指导咱们作进一步细化模型的调优工做。例如将预测效果根据不一样国家的用户,不一样使用频率的用户,或者各类类别的电影等方式来分组分析。具体划分方式能够根据业务特色来制定,并同时考察多个重要的维度。咱们能够把这些测试固化到发布流程中,确保每次模型更新不会在某些数据子集中有明显的效果降低。
将模型的包容性列入测试范围:近些年来也有很多关于模型包容性,公平性相关问题的研究。例如咱们在作NLP相关问题时一般会使用预训练的word embedding表达,若是这些预训练时使用的语料与真实应用的场景有误差,就会致使相似种族,性别歧视的公平性问题出现。咱们能够检查输入特征是否与某些用户类别有强关联性,还能够经过模型输出的切分分析,去判断是否对某些用户组别有明显的差别对待。当发现存在这个问题时,咱们能够经过特征预处理(例如文中提到的embedding映射转换来消除例如性别维度的差别),模型开发中的各类后置处理,收集更多数据以确保模型能学习到少数群体的特性等方式来解决这个问题。
图片描述
模型训练是可复现的:在理想状况下,咱们对同一份数据以一样的参数进行模型训练应该能获取到相同的模型结果。这样对于咱们作特征工程重构验证等都会很是有帮助。但在实际项目中作到稳定复现却很是困难。例如模型中用到的随机数种子,模型各部分的初始化顺序,多线程/分布式训练致使的训练数据使用顺序的不肯定性等都会致使没法稳定复现的问题。所以咱们在实际工程中对于这些点都要额外注意。好比凡是用到了随机数的地方都应该暴露接口方便调用时进行随机数种子的设置。除了尽可能写能肯定性运行的代码外,模型融合也能在必定程度上减轻这个问题。
模型说明代码须要相应测试:虽然模型说明代码看起来很像“配置文件”,但其中也可能存在bug,致使模型训练没有按预期方式执行。并且要测试这种模型说明代码也很是困难,由于模型训练每每牵涉到很是多的外部输入数据,并且一般耗时较长。文中提到谷歌将会开源一些相关的框架来帮助作相关的测试,一些具体的测试方法以下:
机器学习pipeline的集成测试:一个完整的机器学习pipeline通常会包括训练数据的收集,特征生成,模型训练,模型验证,部署和服务发布等环节。这些环节先后都会有必定交互影响,所以须要集成测试来验证整个流程的正确性。这些测试应该包括在持续集成和发布上线环节。为了节约执行时间,对于须要频繁执行的持续集成测试,咱们能够选择少许数据进行验证,或者是使用较为简单的模型以便于开发人员快速验证其它环节的修改不会引发问题。而在发布流程中仍是须要使用与生产环境尽量一致的配置来执行总体的集成测试。
模型上线前必须验证其效果:这点看起来应该是你们都会遵照的原则。惟一要注意的是须要同时验证模型的长期效果趋势(是否有缓慢性能降低),以及与最近一个版本对比是否有明显的性能降低。
模型可以对单个样本作debug:这个就有点厉害了,当你发现一个奇怪的模型输出时,你怎么去寻找问题的缘由?这时候若是有一个方便的工具能让你把这个样本输入到模型中去,单步执行去看模型训练/预测的过程,那将对排查问题带来极大的便利和效率提高。文中提到TensorFlow自带了一个debugger,在实际工做中咱们也会使用eli5,LIME之类的工具来作黑盒模型解释,但从方便程度和效果上来讲确定仍是比不上框架自带的排查工具。
模型上线前的金丝雀测试:这点在传统软件工程中基本也是标配,尽管咱们有测试环境,预发布环境的各类离线测试,模型在正式上线时仍是须要在生产环境中跑一下简单的验证测试,确保部署系统可以成功加载模型并产出符合预期的预测结果。在此基础上还能够进一步使用灰度发布的方式,逐渐把流量从旧模型迁移到新模型上来,增长一层保障。
模型可以快速回滚:与其它传统软件服务同样,模型上线后若是发现有问题应该可以快速,安全回滚。要作到这点必须在开发时就确保各类上下游依赖的兼容性。而且回滚演练自己也应该成为常规发布测试的一环,而不是到出了问题才去手毛脚乱的操做,引出更多意料以外的问题。
图片描述
依赖变动推送:机器学习系统通常都会大量依赖于各类外部系统提供的数据,若是这些外部系统的数据格式,字段含义等发生了变化而咱们没有感知,很容易就会致使模型训练和预测变得不符合预期。所以咱们必须订阅这些依赖系统的变动推送,并确保其它系统的维护者知晓咱们在使用他们提供的数据。
训练与线上输入数据分布的一致性:虽然模型内部运做过程极为复杂,难以直接监控其运行时正确性,可是模型的输入数据这块仍是比较容易监控的。咱们能够用以前定义的特征数据schema文件来对线上输入数据进行检测,当出现较大误差时自动触发告警,以便及时发现外部数据的变化状况。
训练与线上服务时生成的特征值一致:在机器学习项目中常常会出现同一个特征在训练时和在线上使用时所采用的计算生成方式是不同的。好比在训练时特征是经过处理以前的历史日志计算出来的,而到了线上的时候一样的特征可能来自于用户实时的反馈。或者是训练时采用的特征生成函数是很是灵活,易于作各类实验尝试的,而到了线上则改用固化的优化计算性能版本以下降服务响应时间。在理想状况下,虽然采用了不一样的计算方式,但生成的特征值应该是相同的,不然就会出现训练和预测使用的数据有偏移,致使模型效果变差等问题。因此咱们须要经过各类手段来监控线上线下数据的一致性。
例如能够经过对线上数据进行采样打标记录,来与训练集中的对应条目进行直接比较,计算出有误差的特征数量,及这些特征中相应的有误差的样本占比数量。另外也能够经过计算线上线下各个特征的统计分布的差异来衡量是否有这类问题的产生。
模型的时效性:这一点与以前的模型测试中的时效性相似,咱们能够直接使用其中获取到的模型效果与时间推移关系来推断理想状况下模型训练更新的频率,并以此来对模型持续运行时间进行监控和告警。要注意过长的更新周期会提高模型的维护难度。另外哪怕模型自己更新比较可控,可是模型依赖的数据源也有相似的时效性问题,咱们一样须要对其进行监控以避免出现数据过时的问题。
数值稳定性:在模型训练中可能会在没有任何报错的状况下出现奇怪的NaN,inf值,致使非预期的参数更新甚至最终获得不可用的模型。所以咱们须要在训练中监控任何训练数据中包含NaN或者inf的状况进行适当的处理。同时对于各模型参数的取值范围,ReLU层后输出为0的单元数量占比等指标进行检测,一旦超出预期范围就进行告警,便于及时定位排查相关问题。
模型性能相关监控:机器学习模型的训练速度,预测响应时间,系统吞吐量,以及内存占用等性能指标对于总体系统的可扩展性来讲都是相当重要的。尤为是随着数据量的愈来愈大,愈来愈复杂模型的引入,更加重了各类性能问题的出现。在模型演进,数据变化以及基础架构/计算库的更迭中,须要咱们谨慎的评估模型性能变化,进行快速响应。在作性能监控时不但要注意不一样代码组件,版本的表现,也要关注数据和模型版本的影响。并且除了容易检测到的性能突变,长期,缓慢的性能降低也须要引发足够的重视。
模型预测质量的回归问题:整体的目标是但愿新部署的模型相对于过去的模型在预测性能上没有降低。但验证集相对于线上的真实状况来讲老是有所区别的,只能做为一个性能评估的参考。文中列举了几种手段来作监控:
最后总结一下前面提到的各类监控,基本上还有两个共通点,一是各类告警的阈值要作精心选择,太低的阈值容易出现警报泛滥致使根本没人去管的状况,而太高的阈值又会掩盖系统中已经存在的各类问题。二是除了短期内明显的指标急剧降低外,同时也要关注长期的缓慢的降低,后者更难以发现,应该引发足够的重视。
图片描述
文章后续还给出了这28个测试指标的具体评分标准,帮助你们在实践中更好的对照,应用这些最佳实践。还有不少在谷歌内部使用这套评分系统的各类反馈,以及他们各个团队的平均得分状况等。
图片描述
对于这个平均得分状况,做者强力安利了一把谷歌自家的TFX。
图片描述
好比基础架构的集成测试,谷歌内部的得分也很低(满分为1的状况下平均为0.2分)。TFX能够方便的实现整个工程的pipeline,天然也很容易在此基础上完成相应的集成测试了。除了TFX,像Uber的Michelangelo,Facebook的FBLearner Flow也都是相似的机器学习平台,虽然没有开源,但都有比较详细的介绍文章能够学习参考。
![图片描述][9]
这些框架基本能够看做各家公司作机器学习工程的最佳实践总结,整体架构基本都遵循“数据管理->模型训练->模型测试验证->部署上线”这样的流程。不过他们在具体设计实现上各有千秋,例如文中做者认为“线下线上训练数据分布误差监控”是最为重要但却鲜有实现的一个测试点,在不少项目组都曾经由于缺乏这个监控而出现过屡次线上故障。所以TFX提供了数据验证模块来专门解决这个问题。而像Uber的Michelangelo则侧重快速开发特征这个点引入了Feature Store模块。在实际应用中咱们能够根据不一样的业务特色灵活的选择工程方案来进行实现。
参考资料:https://papers.nips.cc/paper/...
https://ai.google/research/pu...
本文做者:观远数据算法天团-zijie
关注机器学习与分布式系统方向
知乎号:zijie0 | Blog:zijie0.github.io
观远数据合伙人 / 知乎5000赞文章博主
观远算法天团又称余杭区五常街道数据F4,成员多来自于帝国理工大学、纽约大学、清华大学、浙江大学、上海交大等国内外知名学府,并有阿里大数据产品与技术研发的从业背景。2018年凭借先进的算法能力,在微软大中华区智慧零售(Smart Retail)AI挑战大赛中,两度斩获冠军,并从1500多家创新公司中脱颖而出,全票入选腾讯AI加速器第二期。做为本专栏特邀产出者,观远算法天团将在将来持续为你们分享更多精彩干货,敬请期待!