你可能不知道,你的外卖早就用上了深度学习!
技术
作者: 江骏
译者:
2017-11-07 07:07

 


| 为  |  容  |  器  |  技  |  术  |  而  |  生  |


江骏 / 「饿了么」资深后端工程师
嘉宾介绍:
曾在携程系统研发部任职。获 2016 年「饿了么」黑客马拉松冠军(在初赛中使用了 TensorFlow)。擅长 Cloud 领域(Kubernetes、OpenStack),热衷开源社区,有一些贡献。近一年多来,为「饿了么」打造深度学习平台,在 TensorFlow 与 Kubernetes 结合方面,积累了丰富的经验。
阅读字数:4710 | 5 分钟

讲师:江 骏

校对:夏 天


大家下午好!来到杭州这个地方让我想到马云和阿里巴巴,十多年前他从美国看到了互联网,中国没有,他回来把互联网和电子商务带给大家。
在 AI 这方面,我想也是到了这样一个时间点,每个公司里都有大数据平台已经开始做一些这样的事情,但是绝大多数公司的大数据部门是一个大部门在做某几个业务训练、某几个模型,而 Google 内部已经有 4000 多个 Model 了,这 4000 个 Model 不可能都是 Google 的算法工程师贡献的,一定有非常大的数量是“普通”工程师(就是不搞算法的)贡献的。国内的互联网公司做机器学习、Deep Learning 怎样才能达到这样一个水平,我们离这一步为什么这么遥远?或者为什么我们迟迟走不到这一步?这跟我们的深度学习平台有关。


深度学习平台 ≠ 跑任务平台


最近半年,机器学习平台、深度学习平台有点像雨后春笋,各大公司都在搞,陆陆续续有一些他们的 PPT。
我自己总结一下总体上分两大派别:

  • 一、是 Apache  系列。因为在 Deep Learning 之前,伴随着大数据时代,非常多的企业已经搭建了非常好的基于 Apache 系列的大数据平台,然后继续利用已有的 Apache 这套生态继续开发机器学习平台;
  • 二、是「饿了么」现在做的,专注于 TensorFolw、MXNet、PyTorch 这些新的 Deep Learning 框架,为它做好一系列的平台服务,像 Google、Caicloud 也是这个方向。因为我在做 Deep Learning 的时候,发现用老的系统很多是不能满足这个需求的,所以我们需要为 Deep Learning 专门设计平台。

如果你也是做深度学习平台的同行,可能企业内部或者用户最容易问你的一个问题就是:“这个不就是一个跑任务的平台吗?”至少,对于「饿了么」深度学习平台来说,这是最大的误解。
往往我们在讲深度学习平台的时候,调度任务其实是最简单的事情,甚至我不太把它当做功能点特意介绍,我们现在有了 Kubernetes,知道了想运行一个进程是件多么简单的事情。这不像当年只有虚拟机,然后需要写一套系统去创建 VM,然后通过 Agent 才能下发任务,才可能运行一个用户需要的深度学习的进程。现在运行一个进程相比以前轻松很多了,而且现在可以运行得非常好,还有各种方便的分布式存储以及调度机制。


大数据平台 ≠ 深度学习平台

那么,在 Kubernetes 的帮助下,「饿了么」 Elearn 为什么还需要做成一个平台?既然已经能够跑业务了,还有什么工作量要做?这里的误差在于大家经常把深度学习平台和大数据平台画上等号。互联网企业有非常多的结构化数据,把数据的获取和一些并行预处理,这些是放在大数据平台中;而数据出来了后,要用这些数据如何给深度学习平台,进行训练,这两件事不能划等号,而且各自的技术内容也是不一样的。
在我之前的 Kubernetes Meetup 分享中,有详细介绍「饿了么」深度学习平台—— Elearn。


从这张图可以看到 Elearn 的位置,以及它与大数据平台是怎样相处的。左边是大数据平台,在经过 Hadoop、Spark、Storm 这些预处理后,把处理好的数据放在 Elearn 的存储中,然后交给 Elearn 来做模型 Training,Validation。如果得到一个比较好的模型,我们有模型的版本管理,最后可以用 Elearn 进行线上 Serving,这样模型就可以接收线上的实时请求,做出预测。深度学习平台应该做的至少包含这些事情, 而它的内容和传统的大数据平台做的内容往往没有什么太大关系。 

深度学习平台与通常代码开发

刚才大家已经听到了一点点深度学习平台要做那些东西,比如说刚才说到模型版本管理、模型 Serving 等等,这些东西直接关系到这个企业要你的深度学习干什么,或者有了算法工程师怎样才能够变成产品。就像不管是老百姓还是开发者,其实都不需要虚拟机,他们其实本质上需要的是能够运行他代码的地方,这是我们为什么容器一出来,就能一下子抢占了很多场景,很多场景只需要用容器运行就可以了。


在深度学习中也是一样的,大家要那个模型干嘛?公司要那个模型也没有用,算法工程师要那个模型也没有用,我们要的,是把那个模型训练好了以后,让它可以在线上发挥作用,服务于业务。算法工程师现在如果做一个业务,一套完整的流程,从看完了需求,到实验环境进行实验,定期训练模型,训练以后上线,这些过程怎么做一直都没有一个统一的答案,尤其之前大数据时代的时候,几乎这些方面是需要每个工程师自己来写一整套服务的。


这长表格是一个比较,左边是我们经常写的业务代码开发,右边是 Deep Learning 的开发,我们现在的业务代码的开发是一套非常成熟、非常完整的体系。


1. 开发环境
先来看开发环境,普通的业务代码,开发者可以用虚拟机;但是如果开发 Deep Learning、AI 代码的时候,就不仅仅是给他一台虚拟机就够的,比如说线上海量数据,再写代码的时候就往往希望拿到一份真实的数据,而且算法工程师还有对数据进行分析的需求,这时候,他就需要看整个一张表的数据分布情况、缺失值情况等,这些和普通写代码是不一样的,他需要很方便的看到线上数据,知道线上数据存在表里的结构,而不是去猜想。所以开发环境如何提供?如果光是这第一步就这么困难,就更不要说模型更新或者新算法的探索了。


2.版本管理
如果说,上面这是工作流程上的不同,那我们再看版本管理这块。现在大家敢想象如果没有 Git,你现在还怎么在公司写代码?这样的协作项目,你还敢发布吗?敢做版本的更新吗?现在来说,没有代码的版本管理,这是完全不可能的事情,这会导致你连线上跑的哪个版本都不知道,有哪些 API,API 应该接什么请求都不知道。那么,现在 Deep Learning 有模型版本管理吗?现在一个业务模型上了线,它的预测质量直接影响你们公司的销量、体验等等,如果你不知道线上跑的是哪一个版本的模型,这个问题也是可想而知的。我这样一说,你看出来了,模型版本管理是 Deep Learning 和写传统的业务代码相比,成熟度上差距是最大的一个方面。 

3.发布
最后是发布。正常的业务代码,有各种各样的灰度发布的形式,甚至可以自己写一些逻辑。而 Deep Learning 的 Model 的发布不同,基本上是分两大类:

  • 一种,把一个 Model 直接打包进业务代码,直接伴随着业务代码发布上线了,上线以后接收请求;
  • 另一种,比较好的,可以把 Model 单独通过一个服务把它 Serving 起来,暴露出 rpc 服务端口,线上的业务 Call 这个服务。

Deep Learning Platform 基本功能


这是「饿了么」 Elearn 平台包括的基本功能组件:

一,Distributed Training。这个不一定必须要求是分布式的 Training,单机也可以跑。但是支持分布式 Training 是一个平台非常重要的功能点。因为如果是单机就是运行一个进程,对我来说没有什么太好研究的东西。但是,分布式训练,你要很方便的让用户尽量少改代码,他的代码可以分布式运行,发挥你的 Cloud 计算能力。这就有很多讲究了。
第二,Model Version Controlling,这个有点像要给深度学习的 Model 带来一个  Git。Version Control 上面是 Model Serving,公司要 Model 是没有用的,是要用起来才能够有用, Model Serving 刚才说到了两种,其一就是打成 jar 包,随着业务代码一起发布,这种方式最大的缺陷是什么?理想情况下,Model 是可以天天训练的,而如果你的一次 Model 的发布相当于一次代码的发布,这是一件“大事”。
仔细想想,如果只是更新一个 Model,其实你是用不着重新发布源代码、重启所有服务的。而如果通过 rpc 的方式,把 Model 变成服务,就只需要一个配置中心,就能轻松切换不同的 Model,这个才让你的模型版本的发布从此方便起来了。很多公司为什么有很多场景不敢大范围的使用 Model,就是太麻烦了,模型一步一步训练,最后要上线,上线了就不要再动了、不要再更新了,更新一次非常头疼,这些问题都出在这个地方。
另一方面看,电商或者互联网每个业务 KPS 特别高的时候,要起非常多的业务实例来支撑请求量。如果把 Model 嵌入在业务代码中,模型启动的时候会消耗内存,相当于线上每一个业务的实例身上都背负一个完整的 Model,这是完全用不着的。业务的实例数与 Model Serving 的实例数,应该是不相干的。业务上来了以后,你的业务实例可以增加,但是同时, Model Serving 服务的实例数应该根据情况调整。这样不会让每一个业务变成一个占用资源的“巨无霸”。


Deep Learning 任务调度

Deep Learning 任务的调度,虽然运行进程简单,但确实还是有一些特殊的需求。机器学习任务的性质本身就有很大区别:第一,它比其他业务更加需要一个分布式存储,而且是大容量的;第二,Restart Poliy,在 Kubernetes 中有两大类,一大类就是可重启,另外一大类是不可重启的,这个和深度学习场景有一些不一样,深度学习往往不需要反复重启。这里面可以对已有的一些 Controller 做一些改造,也可以自己写一个,这个见仁见智解决。
此外,Kubernetes 的 Quota 功能本身也是不够用的。比如,分布式训练要同时启动好几个不同的实例,只有都成功启动才行。而 Kubernetes 的 Quota 目前只能管相同配置的多个实例在启动时资源够不够,情况是不一样的。


我在后来做实际做深度学习业务的过程当中,也在思考为什么需要平台?什么是一个平台?我想应该是这样来考虑:如果公司可以有一个工程师对 Kubernetes 非常熟悉,而且他仅仅用 Kubernetes 就能做到你的平台绝大多数的事情,那就不需要这个平台。而如果发现,光有 Kubernetes,你还有太多事做不了,这就是一个平台价值的体现。


所以,一个平台,重要的,不是它对 API 的封装,不是它的界面,应该是它带来的附加值。像 Kubernetes,我印象中到 1.4 才慢慢有了能够用的 Dash Board,你可以想象在中国的公司做一个项目,没有 Dash Board 能撑这么久的吗?而 Kubernetes 这么有魅力的原因,就是因为它带来的附加值,为 Container 的调度、网络、存储增加的巨大附加值。


Hyper Parameter Tuning

「饿了么」Elearn 还有一个 Hyper Parameter Tuning 功能,这是最近新增的功能,这里可以进行模型的批量化训练自动调优,根据 Google Vizier 做的,做这个东西期间也经历了一些曲折,包括让大家慢慢接受它。






而现在我们已经有了几个用 Hypertuning 训练的模型。图片上就是其中某一个模型的情况。模型的准确率范围从 0.7 到 0.8 之间都有,你所要的,就是那准确率最高的几个。


可以做的还有很多


还有很多可以在 TensorFlow Summit 的官方视频中看到,Google 讲了非常多的 TensorFlow 工程化的东西。

我是这么觉得的, Google 发一次系列视频,足够我们全国的互联网公司好好做一年才能够追上他们的理念。
以上就是我的分享,谢谢大家!

Q&A


Q1:第一个问题,我训练好一个新的模型以后,重启 Server,有一段时间模型缺失,这个时候怎样协调更新模型?我们要重新载入新模型,原来的模型正在服务器上,但是一个新模型加载进来的话,如果重启服务的话,中间差一秒钟。
A:在 Model Serving 这里有一个 Serving 项目的,这是 Google 的工程师写的。这个项目做得事情看起来很简单,就是从目录里读到 Model 以后 Serving起来可以接受 GRPC 请求,这样一个活儿,似乎任何一个人都会写,为什么需要 Google 的工程师帮助你写好?就是因为 Google 在做 Serving 这个项目的时候做的非常细致,其中考虑了Serving 多个版本的问题,这个 Serving 定期检查你的 Model 目录,有没有新的 Model 进来,会 Serving 起来,每个 Model 有 Name,请求的时候告诉它你请求的是哪一个。
当你这个进程在进行模型版本更新的时候,Serving 在这方面也是做了优化的,有一篇文章中 Google 的工程师有讲到,他们为什么做这个优化?因为他们线上这个 Serving 开了 10 个进程,会周期性更新到最新的状态,他们发现一个问题,监控图表上,每天到一个固定时间就会有锯齿状的一次一次请求延迟高峰,这是为什么?后来 Google 工程师发现,有个工程师每天在那个时候进行一次新模型的发布,就导致了升级新模型的时候消耗了太多的资源。
Google 的工程师做了改进并放到 Serving 里,比如说,起 10 个进程,那 Serving 就会自动限制最多只能用两个进程更新 Model,要确保时时刻刻至少有8 个进程还在Serving 线上的请求。把这个功能加上,请求延迟就平稳了。而这些功能都已经集成到了 Google 开源出来的 TensorFlow Serving。直接用就可以了。


Q2:对于数据和模型版本有什么比较好的建议?一份数据可以训练很多模型,版本有一些是不统一的,有什么比较好的实践?
A:我理解您的问题是关于数据的问题,还有一个个关于模型版本的问题。数据也可以分不同的版本,这个也确实是一个潜在问题,有一些场景是传统机器学习所不会遇到的,比如深度学习很多需要图像和语音的数据,而且这些数据往往体积比较大,假如公司里有好几个算法工程师都要研究这批图片数据,不可能每一个人都拷贝一份,这个时候,这类训练数据如果能放在分布式存储中,并且管理起来,是非常重要的。
「饿了么」 Elearn 的模型版本管理,有模型维度,也有版本维度。每当训练完成以后,必须做保存模型的操作才能够确保这个模型不会丢,否则这个模型是不归 Elearn管的,因为你可能训练出很多没用的模型,到时候就删掉了,你只要用 Elearn 保存最好的模型就好了。


内容来源:2017 年 10 月 15 日,「饿了么」资深后端工程师 江骏在 “首届 Kubernetes 中国用户大会” 进行的《Where we are today with Machine Learning and Kubernetes》为主题的演讲分享。「K8sMeetup 中国社区」经演讲者审阅授权发布。



END


 

500 comCount 0