绝大部分机器学习模型都用于推理预测,即输入数据,机器学习模型给出结果。模型创建好后,还需要部署后进行推理应用,产生价值。部署并不只是将模型复制到线上,还涉及到线上模型的管理等功能。
持续集成是将新的模型自动的、可控的集成到生产环境的过程。与之相对的是手工集成,即每次有新模型后,需要人工配置,将新模型一次性发布到生产环境中。
新模型的集成对于某些业务是非常关键的,需要非常小心的测试、发布。虽然可以在模型的建模试验环节中进行很多试验,但模拟的试验和实际环境不完全一样。如果贸然发布,有可能给业务带来负面冲击。如,电子商务网站有几十万种商品,用户需要搜索才能找到自己想要的商品。如果发布的模型不能找出用户真正想要的商品,业务量会立刻出现显著的下降。
在发布业务敏感模型时,通常需要平台能控制到达新模型的用户请求数量,从而观察新模型对业务的影响是正面的还是负面的,再决定是进一步部署新模型,还是撤回模型。在平台的运维体系还不能精确获得业务影响指标时,可以多花一些时间,进行灰度发布,将业务分阶段切换到新模型上。在灰度发布的过程中,逐步验证新模型能够正常使用,响应速度上没有显著下降,对业务没有显著负面影响,最终完成新模型的部署。
有时候发布的新模型是和新代码相配合的,如果要回滚新模型,还涉及到将新代码同时回滚。操作上会更复杂,需要强大的运维体系和实践准则来保证整个过程的顺利进行。
除了模型的持续集成外,还包括数据的持续集成,即将模型持续的在最新数据集上训练,这样可以响应最新的热点数据。平台要将数据的采集工作打通,能够不断的将新数据集成到生产环境中。另外,在生产环境中要控制好进行数据持续集成所需的资源,避免需求的资源过大,影响整个服务的性能。
对模型效果的精确评估,有助于确定模型是否可以上线,或哪些方面需要继续改进。
有些应用可以马上获得用户的标记结果,就能即时评估模型的效果。平台需要将模型的推理结果和用户标记结果组合到一起,汇总出模型的效果数据。平台可提供可视化的界面,帮助部署过程决策。
对于不能获得用户标记结果的模型,要寻找评估模型效果的方法,要能近实时的看到模型效果。如,对于商品推荐模型,需要提高用户点击推荐商品的比例。要把点击数量汇总起来,用于评估新的推荐模型的有效性。如果暂不能评定模型效果,可以用A/B测试的方法,让两个模型在线上共存一段时间,随机接受输入。最后再评估通过哪个模型对最终业务绩效的影响更好。
除了模型效果外,还需要评估计算资源负载和响应速度。如果模型有了较大的改动,可能会在执行性能上有较大变动。在资源紧张的情况下,如果没有注意到这些因素,可能会因为模型发布而造成服务负载过高,甚至影响会扩展到全线服务上,影响整个业务的稳定。
在一些复杂的多模型组合下,特别是有很大的团队在平行开发模型时,就需要更复杂的模型评估方法。如,一些大型搜索引擎,会有多至数十个团队在改进搜索引擎的排序算法,可能每天都有新模型要发布。这时候需要建立一套强大的模型效果验证工具,假设评估中的模型之间没有关联,可以让小部分用户的输入随机使用这些模型的组合。然后通过算法计算出每个模型对结果的影响数据,从而决定模型最终是否能上线。
下表为灰度发布比例与评估重点的建议。
发布比例 | 评估重点 | 系统要求 |
---|---|---|
1~5% | 响应速度 模型效果 | 能够观测到单个请求的延迟情况,或对某类请求能聚合计算。模型效果的评估需要用户标记的支持。数据延迟在分钟级。 |
10~20% | 系统资源负载 | 能够按服务器进行单台流量切换,从而能够观测到服务器的负载变化情况。 |
50% | 对业务的影响 | 有模型以及整个业务的指标定义和收集方式。 |
通过特征工程定义的数据加工流程后,数据才能作为模型的输入。在部署后的模型应用时,生产数据也需要通过一致的特征抽取过程,才能输入到模型中。如果有成熟、高效的数据加工过程,可直接将数据加工过程的代码用于生产环境,与模型一同发布即可。
但是,在模型应用时的性能要求比试验更高,或者有可能运行环境不一致。比如,试验时可能用的是Python,而应用时需要C#。这时需要通过一组特征工程的数据测试集,来保证试验时和应用时的特征抽取工程能得出一致结果,从而能够给模型输入同样格式的数据。否则,模型的正确率可能会比试验时低,甚至有明显的差距。
在模型应用中,大部分要进行实时处理。如,搜索引擎、图片识别、相关推荐等功能,都需要将结果尽快返回给用户。这对响应速度等各方面要求都较高。而有些应用不必给用户实时返回结果。比如,个性化的商品推荐邮件,可以在每天的访问低峰时段完成计算并发送给用户。
在产品设计时,如果实在达不到实时返回的响应速度,可以将一些需要实时返回的结果做到近实时。比如,在一些依赖第三方数据的机票查询功能中,会设计搜索进行中的界面,管理好用户的期望。有些应用,对时间不是特别敏感,可以先行计算并缓存结果,这样也能做到近实时的效果。
服务即通过web服务开放出的推理应用接口。现代运维体系对于如何提供内部服务有很多的沉淀,有包括虚拟化、容器化、微服务管理等各种工具和设计思想的支撑。本节会结合机器学习进行简单的介绍。
负载均衡(Load Balancing)是现代服务的重要概念,即将访问请求通过一组服务器来支持,而不是依靠单台服务器。负载均衡的主要原理是通过中心点来统一提供服务,而真正实现访问请求的节点在中心点上注册,并定期向服务器发送信息,刷新节点健康状态。实际的访问请求有的通过中心点直接转发给节点。有的服务会将节点地址给到访问请求方,由访问请求方再次向节点地址发送请求。
通过负载均衡可实现高可用、灾备、A/B测试、灰度发布等各种功能。负载均衡的实现方案也非常多,包括DNS、硬件集群、反向代理、服务发现等等,都是负载均衡的实现方案。理解了负载均衡的原理和多样的实现方式,以及不同方式间的优缺点,就可按需组合一些方法来实现高可用、灰度发布等功能。
负载均衡的中心点也需要备份来提供高可用服务,不能依赖于单个节点。有的通过网络层的负载均衡来实现,即所有的请求会送达所有服务器,但只有真正处理访问请求的服务器进行答复。服务器间通常用对等组网的方式来选举出主服务器。数据包会同时发送到多个节点上,根据算法会有选中的服务器响应请求。如果选中的服务器没有响应,依据算法下一台可用的服务器来响应。
容器化管理是在操作系统级实现的虚拟化,如Docker(在算力管理中也提到了它)。通过容器化,可将服务分散在多个节点上。在此基础上来实现负载均衡,将新节点注册到服务上,新节点就可以马上对接用户请求,开始提供服务。
通过容器化的服务,可随时更新服务的系统级依赖,如操作系统的补丁、硬件升级等。而且可提供从开发到服务的完全一致的环境,减少因为操作系统等不一致造成的生产环境问题。另外,通过容器化管理,可以轻松的进行服务扩容。只需要在服务器上使用同样的配置创建新的实例,即可实现扩容。在发布时的版本更替过程也类似,通过创建新Docker实例,关闭旧的实例,即可完成版本发布。在这个过程中,只要保证服务器是无状态的、可共存的即可。
在服务的不断开发中,根据新需求,会出现修改API接口的场景。而在复杂的应用中,API会被不少下游的服务或客户端调用。这时,要管理好API更改,防止造成服务的中断。一般的API更改都要分步骤进行。在发布新API时,要同时支持旧API。即使旧API不能加入新的功能,也需要保证它继续可用。发布后,通知并帮助下游团队尽快迁移到新API。最后,在数据上看到旧API已经没有访问量时,才可删除旧API及其对应的数据、模型等。
因此,在API升级过程中,有一段时间新旧API会共存,甚至需要维护好两套数据加工流水线,要注意保证版本替换过程中服务的顺畅。
在提供服务时收集到的数据,是用户场景下真正的数据,对改进模型的帮助非常大。收集数据时,可通过数据加工流水线将数据传送到模型试验、批处理训练直接使用。
如果能收集到用户标记数据,则需要将用户原始输入数据与用户标记关联起来保存。一般来说,用户输入数据和用户标记数据会在两个请求中,因此,要注意进行正确的关联。特别是在用户有多次请求时,需要通过关联的id找到正确的标记与数据对。
近年,机器学习领域的变化非常大,新的算法、框架、硬件、理念等层出不穷。一个好的机器学习平台应该有足够的扩展能力,才能跟随时代演化。不求站在技术的最前端,但也不至于在出现颠覆式创新时,整个平台需要推倒重来。
在建设平台时,要把握的第一个方向就是,要通用平台,还是垂直场景下的专业平台。通用平台 ,即尽可能的支持所有的机器学习框架、硬件、网络结构。而垂直平台,即将某个方面实现好,做到极致。比如对TensorFlow支持到极致,或者对图像识别支持到极致等等。这和公司业务方向有很大的关系,在每一层都可以进行通用、垂直的选择。
通用,意味着平台只做最少的工作,通过Kubernetes这样的容器编排软件来支持不同框架的配置镜像,并支持基础的硬件资源分配,任务管理等工作。平台会有最大的通用性,几乎能适应未来的任何变化。如,最近在研究上很热的自动化建模,超参自动搜索等,很可能会颠覆未来的建模过程。一旦有了成熟的方案,通用平台可以快速集成。但在使用通用平台时,需要自己配置docker镜像,并学习任务配置等功能,有一定的学习培训门槛。
专业,即对某些框架、硬件提供深度的支持和定制,甚至对于某些场景做更多的定制化工作。如专门用于处理图像识别的平台,可直接在界面上提供上传图片、标记数据、性能对比等功能。定制的平台还可以很容易的集成选定框架下的模型优化、代码生成工具。这样能提供最好的使用体验,也能深度挖掘框架、硬件的功能,提高效率。但不足的是,如果和框架、硬件、业务绑定太紧,在有了重大变化时,平台能重用的部分可能会比较少。如,出现了新的硬件能显著降低计算成本,或业务上有了其它机器学习建模需求。
通用和专业,一横一纵的两个方向并不是完全冲突的。这也要看团队当前所处的阶段。是在各种框架、算法间不断探索的试验阶段,还是已经找到了比较成熟的方案,应用上慢慢定型的应用阶段。如果框架选型已经完成,业务形态已经初步具备,构建专业化的平台会带来更高的生产力。也可以先构建一个通用平台,在上面对框架、硬件、业务组合做进一步的深度定制。在定制时,要考虑到框架、硬件、业务间不要耦合太紧,这样在某部分需要改动时,能最大程度的重用现有平台。当然,同时也不能为此而过度设计,重点是要支持好业务。比如:以前的ODBC(开放数据库连接)是一个几乎能兼容任何关系型数据库的协议,号称有了它之后,底层数据库可以轻松切换。但在实际应用中,需要切换数据库的情况非常少。而且当需要切换时,真正麻烦的并不是如何连接数据库,而是如何改动现有的SQL语言来兼容新的数据库系统。