数据安全程序员技术栈程序员

解决数据科学一公里问题-Clipper简介

2018-07-12  本文已影响3人  TalkingData

对于数据科学问题来讲,我们面临的挑战是什么? 是数据准备?是特征选取?还是算法选择?这些固然都很重要,但真正的挑战在于如何将构建好的模型应用于生产,高效的运行并产生价值。也就是如何有效解决数据科学最后一公里的问题。

随着智能数据时代的到来,越来越多的企业都开始建立自己的数据管理平台,建立自己的数据科学团队,期望结合自身的业务场景,构建解决业务问题的模型。随着数据科学工作的开始,大家往往都会面临一个问题,就是如何能够高效的将训练好的模型推到生产环境,也就是前面提到的数据科学的最后一公里的问题。在我们接触的很多客户中,模型生产化是大家普遍拥有的共性问题,我们需要给客户提供这种能力,让客户将训练好的模型能够自动部署到生产,并且方便的被使用,从而真正兑现模型的价值。

这个关于数据科学的挑战,并非偶然,UC Berkley的RISELab(AMPLab的继承者)也发现了这个问题,并且开源了应对该问题的项目-Clipper(快船)。

Clipper是什么?

从Clipper的官网上来看,Clipper对自己的定位是:面向客户应用和机器学习模型与常用框架之间的一套预测服务系统。

另外,Clipper支持数据科学家在不改变代码的前提下,将训练代码直接部署到生产环境中。

Clipper的特性

对于数据科学家在选定的框架上训练的模型,通过几行代码就可以部署到一个现存的模型容器上,或者开发自己的模型容器;

对于正在运行的应用,可以非常容易的更新和回滚模型;

可以设定服务的延迟目标,从而保证可靠的查询延迟;

每个模型都运行在一个独立的Docker容器上,从而实现简单的集群管理和资源分配;

可将模型运行在CPU、GPU或者同时运行在二者之上;

Clipper的架构

在Clipper的架构中,包含一个模型选择层(Model Selection Layer)以及一个模型抽象层(Model Abstraction Layer)。模型选择层负责在多个竞争的模型当中根据需求动态选择和组合模型,从而能够提供更精确、更鲁棒的预测。而模型抽象层则屏蔽底层的不同机器学习框架,通过抽象出一个通用的API来方便模型上层应用对模型进行调用。

Clipper为了能够实现低延时、高吞吐率的预测,在模型抽象层引入了缓存的策略。对于每一个模型,Clipper提供一个缓存层,并且通过Adaptive Batching来提高预测的吞吐率。而对于模型选择层,则引入Straggler mitigation技术,预测的请求不会路由到比较慢的模型执行上,从而能够降低延迟。

Clipper集群

Clipper集群的实现利用了现在非常流行的容器技术。一个Clipper集群由一组相互通讯的Docker容器组成。Clipper集群的核心由三个部分组成:查询前端(Query Frontend),管理前端(Management Frontend)以及配置数据库(configuration database),如下图:

其中:

Query Frontend负责接收进来的预测请求,并将这些请求路由到部署的模型上,

Management Frontend负责管理和更新Clipper集群的内部状态,当集群需要更新时,需要通过Management Frontend的REST API发送请求,状态会更新到database当中

Configuration Database是一个运行Redis实例的容器,它存储了集群所有的配置信息。

Clipper中的模型

在Clipper环境中,每个模型都会运行在一个Docker容器中。Clipper对常用的模型运行框架提供了model deployer,从而使得常用的模型类型可以方便的进行部署。目前,Clipper支持三种类型的模型环境:纯Python, PySpark和R。在模型被部署成功之后,Clipper利用容器管理来启动容器并且建立一个模型容器与Query Frontend之间的RPC连接。

在Clipper当中,模型部署好之后并不会建立一个对外的REST服务。Clipper引入了一个应用层来负责将请求路由到模型容器中。这样使得多个应用可以路由到一个模型,也可以一个应用路由到多个模型。用户需要通过ClipperConnection.register_application来注册应用,应用注册成功之后,会对应用创建一个REST服务。

通过ClipperConnection.link_model_to_app,可以将model连接到应用上,这样对于应用的访问就能够路由到模型上了。如下图:

在Clipper当中,模型支持不同是版本,当新的版本通过deploy_model被部署时,应用会将预测请求路由到新版本的模型上。另外,用户可以通过ClipperConnection.set_model_version来回滚模型。

Clipper支持针对同一个模型复制不同的副本,从而提高模型的吞吐率。通过调用ClipperConnection.set_num_replicas,Clipper可以根据设置的副本数量来启动相应数量的模型容器,如下图:

对于模型的访问,则是通过访问应用的REST API来完成,比如:http://localhost:8080/wordcount-app/predict

从前面的描述我们可以看到,Clipper的核心是实现模型的调用与模型运行态的隔离,通过逻辑层的应用,将模型的服务以REST API或者RPC的方式对调用者开放,而Clipper内部通过应用和模型的连接来灵活的实现应用对模型的路由,从而将模型和对外的服务解耦,为满足模型服务化的性能提供了基础。而底层则利用容器化的技术来实现从训练到运行态的转换工作,降低模型部署的成本。整个设计的思路从架构上来讲,如果大家面向同样的问题做架构,估计大同小异。具体的实现,由于Clipper的目的是提供高性能生产环境预测能力,整个项目利用RUST和C++来实现核心的代码,实现代码的选择非常有Geek范儿。想一下师出同门的Spark用Scala语言实现,在大约6年前,也是非常Geek的。不得不说,伯克利出品的东西,工程能力还是比较出色的。

目前Clipper这个项目仍在快速的迭代过程中,它距离一款成熟的产品还有一定距离,大家有兴趣可以到Clipper的官方网站: http://clipper.ai/,去关注这个项目的进展。

由于数据科学最后一公里问题是个共性的问题,而且客户的需求越来越迫切,TalkingData的技术团队也在利用容器技术实现自己的模型生产部署平台,并且开始在一些客户的生产环境中进行使用,如果你也面临同样的问题,欢迎与TalkingData技术团队一起进行深入的探讨。

上一篇下一篇

猜你喜欢

热点阅读