干货分享 | 追一科技王达:如何构建全流程机器学习平台
The following article is from TGO鲲鹏会 Author 王达
机器学习作为人工智能的一个子集,随着 AI 概念逐渐被大众所认知、认可,也越来越受到企业的关注。除了追随前沿技术的互联网公司之外,很多来自传统行业的公司也分别设立了 AI 相关的部门,希望能够赶上人工智能这趟快车。
随着 AlphaGo 的横空出世,越来越多的应用开始采用深度学习的方案。在大数据逐渐与深度学习融合的阶段,由于数据量越来越大,模型训练的流程越来越长,越来越复杂,对于通用的大规模机器学习平台的需求也因此应运而生。到底怎么样的平台才是一个好平台,才能真正做到易用好用?
王达带来了关于“如何构建全流程机器学习平台”的实践与思考。从对机器学习平台的认识和理解、构建机器学习平台的关键技术以及机器学习平台具体落地和优化的方案三个方面进行讲解,分享了他们是如何去构建一个满足开发、业务、运维、客户四方需求的机器学习平台。
机器学习的需求一直存在,不同的公司里也有着各种各样的相关平台,借着深度学习的东风,传统的机器学习平台需要结合新技术开出新花朵,而新的平台则想要借此机会去撼动原有的格局。一时间群雄并起,都希望能够逐鹿中原。
目前市面上的机器学习平台在界面上基本上大同小异,都是采取四栏的设计,其中 A 区域是一级功能的选择,就是跟机器学习最相关的顶级概念。比如工作流、数据及算法和模型,对于数据和模型来说,都可以纳入一个统一的资源管理系统来进行管理。需要处理的大部分是数据库的增删改查,这里不再赘述。我们主要来聊聊最重要的工作台界面。
界面设计的原则是一定要简化操作,把所有操作都放到同一个界面中,让用户以最自然的方式去使用。对于工作台来说,有几个部分必不可少。第一个是项目管理区域和算子的区域,即图中 B 区域。第二个是实际用来拖拽、构造工作流的画布区域,即 C 区域。D 区域是不同的算子的配置区域。
总体来说这种集成开发环境 IDE 有一些类似,只是我们不在 IDE 里写代码,而是把所需要的算法和数据集拖到 C 的区域,然后连线构造成一个工作流。
针对机器学习平台,基本上可以分为资源、平台、应用三个切入点。通过雷达图来看他们各自的强项。
从资源切入,在传统机器学习上,因为继承了原来的 hadoop 和 spark 生态的基础,比较占优势,对业务和运维也会比较友好。
从平台切入的这种方式在服务发布及学习以及数据挖掘的方向表现的会更好。
如果从应用切入,主要发力点有两个,一个是对深度学习很充分的支持,还有一个就是平台本身的扩展性。
这三种平台的切入方向也代表着不同的设计思路,各有侧重点。从资源和平台切入,是在大数据生态的基础上改造升级,以支持深度学习这一最新潮流。而从应用切入则一开始就是围绕着深度学习的工作流展开。
今天就结合追一科技在机器学习平台上的实践来说说如何从应用的角度切入,来构建一个满足开发、运维、业务和客户需求的机器学习平台。构建平台会涉及到方方面面的技术,我们从中挑选了五个最关键的跟大家分享。
第一个关键点是如何通过工程设计,让平台能够拥有一定程度的智能,而不只是一个资源调度和程序运行的平台。这里涉及到两个要点,一个是平台元数据和平台所管理的数据的收集与整合,二是如何在这些数据的基础上为平台本身赋能。
第二个关键点是关于平台底层的架构,在深度学习的大背景下,如何能够尽可能地提高硬件资源的利用率,加快模型的训练过程。
第三个关键点是如何能够做到闭环,即从离线到在线再反馈回来到离线这样一个闭环,让模型拥有自学习、自动更新的能力。这部分无论是对平台还是应用本身,都是有一定要求的。
第四个关键点是如何通过容器的形式来支持各种编程语言和框架,核心的思路是面向规范编程,只要符合我们定义好的接口规范,并且能够放到容器中,就可以放到平台中去使用。
最后一个关键点是平台的大脑——调度器,面对不同类型的应用,如何设计调度器来支持各类不同的需求。
通往平台智能之路并不是一蹴而就的,而是需要一层一层构建的。所谓平台,其实是一种规范,这种规范本身就是一种专业化的表现,像一只看不见的手,最终会体现到我们的产品中。
需要注意的是,定规范是为了真正用起来,这就引申出来三个要点:第一个要点就是这个规范要以够用为原则,一定是简约而不简单的,要学会抓大放小,当然也要留意长尾的问题;第二个就是一定要小心过度设计的陷阱,避免字段的线性相关;最后是我们在配合规范的时候,是采用这种资源描述的文件,而不是这种固定的字段来去做的,为未来留下更大的扩展空间。
确定了底层最基本的资源描述之后,就可以在此之上开发更加高级的应用了。比如算法推荐和自动调参。
对于算法推荐来说,我们把原来极其依赖开发人员经验的问题转化成一个目标为所使用算法的多分类问题,以及一个推荐系统机制的问题。因为有了算法,数据和工作流的统一描述,相当于把不同场景的不同任务放到了同一个坐标系中。那么就可以根据数据算法和工作流本身的特性去做智能推荐和分类。
自动调参也是如此,除了可以提供一些初始的搜索条件,供用户选择外,还可以根据以前的相似任务来进行智能的参数选择。
平台智能存在的最终意义就是让没有太多机器学习经验的用户,能够解决那些原本只能由经验丰富的算法研发人员完成的任务。从这个角度来看,算法推荐自动调参,都是为了通向这个目标的一步。这里还有很多工作需要我们去探索和挑战。
除了平台智能外,机器学习平台的另一个重要指标就是硬件资源的使用效率。对于 CPU 和内存来说,无论是基于 docker 还是基于虚拟化的方案,都已经有了比较好的支持。而针对深度学习所必需的 GPU 资源,因为与 CPU 的计算模式有比较大的差别,目前还没有一个非常完美的方案。
针对 GPU 资源的高效利用,必须要解决以下三个问题:第一个就是如何利用多张显卡加速模型的训练。第二个是如何解决集群中 GPU 资源异构的问题。第三个是如何优化 GPU 资源集群的计算效率。
第一个是多卡加速的问题。目前有两种思路,一个是数据并行,一个是模型并行,这两种方式各有其优劣,但是目前的主流来说是用数据并行的方式来做,因为数据并行的方式更加简单,也更加稳定。模型并行无法知道全局的特性,而数据并行的主要问题在于网络和 IO 的消耗巨大,但是可以采用一些工程上的优化,基本达到接近于线性的加速比。另外目前主要的深度学习框架都有支持多卡训练的机制。
第二个是集群异构的问题。在这里指的是计算资源并不一致的问题。除了 GPU 的差异之外,在容器的解决方案中,CPU 和内存的差异同样是需要考虑的。这个问题有两种解决方法。一种是将全部硬件更换至最新,这样就没有不一样的情况。另一种经济实惠的方式是结合调度器,通过给不同的 GPU 打上标签,在任务派发的时候尽可能地分配到同一组同一型号的 GPU 上,这样能更高效的利用好资源。
第三个是如何优化 GPU 资源集群的计算效率的问题。这里主要解决的问题有四个,分别是算力问题、大 batchsize 问题、扩展效率问题以及 IO 问题,下面分别来说一下简单的解决思路。
算力的问题,可以通过用 16 位来计算,32 位来更新的方法,这样计算量会小很多,更新的时候也不会降低它的精度,变相提高了计算量。大 batchsize 问题,主要用的是 lars(层次自适应速率缩放)的算法,即对不同的神经网络层用不同的学习率,配合上对应的参数,调整学习率,这样可以把大 batchsize 所带来的问题降到最低。扩展的问题,采用的是去中心化方案,通过环状的方式,就可以保证我们去掉了网络结构中的瓶颈,这样它的扩展效率会得到一个很大的提升。IO 问题,则可以把一些数据预存取到 GPU 里,减少了数据载入的时间。通过以上优化,可以对深度学习的任务在多卡执行的效率上有非常大的一个提升。
全流程闭环是着眼于构建图中所说的从离线到在线再回到离线这一流程,让模型和服务拥有越来越智能的能力。那么如何去构建这样一个全流程的流水线闭环,关键还是在第一步所说的规范。
对于传统的 spark 任务来说,我们可以利用 spark 本身对全流程进行发布,发布之后我们对在线的日志以及处理好的数据做一个收集处理,然后再由数据仓库重新滚动到下一次的训练中,这样就完成了一个闭环。
而对于深度学习的任务来说,在基于容器的方案下,可以通过微服务的形式,把整个工作流发布成一个在线的流程,让每一个步骤都可以在 K8S 里进行监控和扩展。
接下来看如何利用容器的优势来构建完整的计算任务执行机制。
Docker 自 2013 年问世以来,已经在诸多场景凸显出自己的优势,而 google 开源的 kubernetes 为机器学习平台提供了一个稳定的任务执行环境,使得整个平台的扩展性和通用性非常好。
kubernetes 的 Job 机制为单次的计算任务执行提供了完整的支持,这种 service 的机制则为模型上线提供了支持。对于每一个 Job 来说,因为我们把计算环境以及所用的算法以及对应的数据都已经完全解耦了,每次执行的时候,只要从对应的镜像仓库算法仓库和数据仓库中拉取所需要的资源,统一放到这样一个容器里,然后去执行就可以。
自定义添加到平台的算法,只要满足规范,就可以享受和系统算法一样的待遇,极大的扩展了平台能力。
最后是最核心的调度器的模块,作为整个平台的大脑,平台的高级特性都离不开调度器的支持。
具体来说,调度器可分为两个子模块,一个是在用户进行任务相关的操作后出发的,另一个则是周期执行的。调度器首先会进行权限检查和资源检查,生成对应的 task 队列或者是 service 队列,队列是带优先级排序的,可以在平台上提高它的优先级,这样比较紧急的任务可以优先去做。而周期执行的任务则是按照顺序来进行任务派发、任务状态检查、服务启动、服务状态监控这几个任务,如果有定时的任务,也会在指定的时间进入队列,并且去进行派发。
这种任务解析与任务派发的分离,使得多租户的平台拥有统一的资源调度能力,避免出现了资源竞争的情况。task 和 service 双优先队列的设计,可以最大程度的兼顾公平与效率,满足大部分常见场景的需求。
最后我们来看一下平台具体落地和优化的方案。主要包括三部分的内容,第一个是系统架构,第二个是工作流程,最后是系统部署。
系统架构图
机器学习平台的具体工作流程
怎么样去打造一个能够快速迭代部署上线的流程,这里分享一些工程化的经验和技巧。
我们在设置开发和测试流程的时候,需要把环境放到第一位,除了日常开发测试的公有云环境之外,在私有化部署的时候,单机和集群的情况其实都是需要考虑的。
针对环境问题,可以通过一种技术与四套工具来应对。一种技术便是容器化与 kubernetes,四套工具则是环境检测工具、配置生成工具、安装向导工具和回滚重试工具。环境检测工具顾名思义是用于确定系统的环境状况,包括网络磁盘端口内存等各类基础的安装包等等。环境检测通过之后,则会由配置生成工具生成对应不同环境的对应配置方被后面的安装向导工具调用。当安装出现一些意外情况的时候,可以使用回滚重试工具进行彻底的清理,保证每次安装前环境保持一致。
机器学习平台作为一个通用企业专业的平台,一般来说是需要在公司内部跨团队进行开发的。那么怎么样去跨团队做出对技术背景要求比较高的产品,在多组协同的情况下,怎么样能够保证大家在同一个维度沟通?
我们采用的是四个同一的方式,也就是同一定义域、同一流程、同一文档、同一环境。这些所有的“同一”都是力求保证大家在同一个维度去沟通。最后是工程上的四个优先,第一个是规范优先,第二个是离线优先,第三个是稳定优先,最后是测试优先。
通用组建开源,核心模块自研。
开源:Spark 生态,Hadoop 生态,Kubernetes 生态,通用算法;
自研:调度器,专用算法,资源规范;
降低开源算法和组件的接入难度。
资源粒度较粗,抽象程度不如虚拟化;
对服务器的配置要求,共享的层级较浅;
原生 docker 方案网络功能较弱。
子系统独立权限,分散的小金库而不是一个大金库;
无 cookie 无 session,https+token 验证;
自定义算子的安全性,通过 docker 进行隔离。