阅读 776

携程AI模型引擎设计与实践

原文链接: mp.weixin.qq.com

作者简介

 

李媚,酒店数据智能组应用开发工程师。2016年加入携程,先后负责了酒店交叉推荐,优选频道个性化酒店排序等服务开发工作。

一、前言

近年来人工智能的发展成果在互联网行业得到了广泛的推崇和应用,各大巨头纷纷借助AI打造个性化、精细化服务, 加速扩张生态领域。从推荐系统到实时风控,从广告系统到图像处理,模型服务在携程各个业务领域发挥着日益重要的作用。然而回顾现有的模型上线模式,不难发现仍存在一定的缺陷:

1、训练数据准备工作需要手工完成。数据清洗和特征挖掘是模型训练的前期工作,既包括从原始数据清洗出特征数据,也包括对清洗出的特征进行处理。由于缺乏统一的特征管理平台,目前训练需要的原始数据仍需算法工程师自行收集、整理、清洗。

2、不少模型处于离线预测阶段。相对于离线预测,实时预测能够依据用户的实时行为和最新的数据信息作出下一步预测,有效提高预测的准确性。但实时数据存在复杂、多变等特性,以及实时预测对性能上的要求更加严苛,工程技术门槛高,不少团队选择了相对容易实现的离线预测方式。

3、实时模型服务的开发周期长。实时模型服务离不开实时特征准备、业务逻辑开发、模型调用开发等步骤。实时特征一般由各项目的开发工程师自行维护,不可避免地存在特征重复开发的现象,带来开发资源和存储资源的浪费。此外,一个预测场景一般由一个模型服务提供支持,新的模型服务需求需要完全从头开始开发,开发周期较长。

结合上述现状以及在酒店个性化推荐、信息与图片等领域积累的丰富的模型上线经验,携程数据服务组推出了模型引擎平台——旨在通过搭建一个综合性的模型服务平台减少模型上线过程中的重复工作,实现模型的快速上线迭代,健全线上模型的监控评估机制。

二、平台构建

设计目标

作为一个综合型的平台,模型引擎致力于提供从数据处理、模型训练到模型上线的全闭环服务,为此我们制定了如下目标:

1、服务于产品经理、数据科学家、开发工程师、测试工程师团队,通过服务全景图的形式串联各环节;

2、作为一个实时预测平台,模型引擎服务接受秒级延迟的实时数据,毫秒级地返回预测结果;

3、广泛地适用于携程各类业务场景,支持包括ABTesting、模型灰度上线、多模型融合等功能。

总体架构

针对上述设计目标,模型引擎设置了特征管理、工程管理、模型管理、产品管理四大模块,总体逻辑架构图如下:

1、特征管理

特征管理模块主要解决特征准备问题,对应了逻辑架构图中的特征库一层。

根据使用场景,特征分为离线特征和在线特征。离线特征主要在模型训练阶段使用,数据科学家对存储在Hdfs中的静态数据、落地的消息数据等尝试不同的样本选择、变换处理和组合等,再配合算法及参数进行模型训练。训练完成后,数据科学家将最终的特征方案交给开发工程师,再由开发工程师将离线特征搬移到在线环境,如Redis,ES,Aerospike等。

在线特征开发工作既包括将离线存储中的特征导入到实时存储,也包括对实时消息(Kafka、Qmq),例如用户点击、下单、酒店起价变化等进行处理,不断更新在线数据。

模型引擎维护了一个公共的特征库,支持算法工程师通过界面操作的方式添加离线特征,复用已有特征;同时也实现了通过配置自助导出离线特征到实时环境的功能和对流信息的实时处理功能,接入方借助提供的API就可以进行数据访问。

同时,对重要特征进行监控与有效性分析是保障模型服务质量的首要环节。相对于离线特征,实时特征有时效性和一致性等要求;而且实时特征一般以KV形式存储,不能简单地通过SQL语句进行统计。如果每个工程师单独为自己维护的特征开发监控Job,那么开发工作量就会大大加重。模型引擎由于维护了公共的特征库,可以对特征池中的特征建立了统一的长效监控机制,常见的监控指标,如缺失率、新鲜度、活跃度等,都可以通过模型引擎平台查看和增添。

2、工程管理

工程管理模块主要解决模型的工程实现问题,对应了逻辑架构图中的模型服务一层。在实时场景中,模型服务一般以SOA服务形式供使用方调用,包含了建立本地缓存、实现业务逻辑、调用模型、返回预测结果等步骤,如下图所示。

针对这些典型的开发步骤,模型引擎提供了通用的组件辅助开发工程师,降低工程实现难度。

在实时批量预测场景中一次调用需要用到大量的原始数据,从外部存储获取数据难以保证服务性能,因此工程师会选择建立本地缓存减少数据拉取时间。然而维护本地缓存会带来了不少额外负担,例如不同数据源对新鲜度的要求不同,本地缓存的更新机制要区分设计;本地缓存数据量大时,需要考虑JVM参数的配置,以避免频繁的Full GC和长时间的GC。为此,模型引擎开发了Feature Bus组件,通过统一的XML配置,支持自动构建本地缓存,同时也屏蔽了底层存储的读取细节,免去繁琐的本地缓存开发工作。

在调用模型方面,模型引擎提供了Code Gen服务,支持模型服务的自助生成。各模型采用的算法虽然林林总总,但在工程上调用的方式却不外乎几种,例如PMML、Python包、Xgboost等等。模型引擎对常用的调用方式进行了封装,供开发工程师在项目中直接使用。一方面开发工程师不再需要对没有接触过的模型调用方式进行摸索,另一方面对业务逻辑和模型调用进行了解耦,后续算法升级只需要简单地升级模型服务的版本。而且在生成的模型服务中嵌入了统一的监控,对线上模型服务的质量可以进行集中的管理。

此外,最终进入模型的待预测数据也是算法工程师所关心的。不少原始数据经过了开发工程师手动编码加工,在遇到模型预测效果与线下不一致时首先需要确定这部分数据的正确性。在模型服务中会收集这部分数据并上传,配合平台提供的可视化界面供算法工程师和测试工程师判断数据的健康情况。进一步地,也可以利用这些数据实时更新模型,实现自动化模型训练。

最后,模型拆分、多模型融合功能也在这一层支持。总之,开发工程师只需要将主要精力放在业务逻辑的实现上,以及借助组件串通完整流程。

3、模型管理

模型管理模块主要实现了模型文件的上传、关联特征、模型发布、迭代回退等功能,对应了逻辑架构图中的模型管理一层。

结合携程的文件服务系统,算法工程师可以在模型管理模块便捷地上传模型。在迭代模型时,为了减少再次测试、发布的环节,模型引擎平台支持算法工程师更替、回退模型文件,实现模型文件的实时生效。在操作的安全性方面,在上传新模型之后,平台会根据样本输入输出数据进行自动校验,确保模型文件的正确性;也会对模型的调用进行压测,符合预设结果的模型才可以进入部署阶段。此外,因为模型文件一旦发布就会即刻生效,为了避免误操作,由测试工程师进行最后的审核上线操作。

现有的机器学习中很多模型的使用都类似黑盒,尽管经过了离线数据的训练以及测试环境的验证,对于模型在实时环境中的预测效果依然难以预料。为此,模型管理模块提供了模型灰度上线功能,支持在正式对外发布前对模型进行内部验证。算法工程师只需要简单配置白名单和上传堡垒模型文件就可以在生产环境直观体验新模型的效果,既不需要开发工程师的介入,也不会影响外网用户。

4、产品管理

产品管理模块主要实现了场景的创建和管理。在模型引擎中一个具体的模型预测业务称为一个场景。项目一般由产品经理发起,所以由产品经理负责创建场景,填写项目信息,并关联相应的开发人员。创建完毕后,算法工程师和开发工程师登录平台就可以在模型管理和工程管理模块下进行操作,为场景实现添砖加瓦。

在模型引擎最初设计中,一个场景仅支持一个模型,根据实验版本不同上传不同的模型文件。然而随着预测业务精细化,在一些场景中,为了达到最优效果,会对模型进行进一步的细分,拆分出多个模型,这些模型的大部分业务逻辑和模型特征都相同,或者模型间存在着依赖关系,因此不适合将这些模型独立为各个场景。因为模型引擎中采用了子场景的概念来支持一个场景下多个模型的情况。其中子场景间的关联关系又分为并行、串行、融合、switch等多种类型,由此可以支持串行模型,多模型融合等。其中多模型融合的调用方式如下:

此外,产品管理模块还可以展示模型服务场景的全景图。为了帮助用户清晰地了解各个环节,产品管理关联了一个场景下的特征模块,模型模块,工程实现模块和监控模块,完整串联起了模型上线的整个生命周期,通过点击就可以跳转查看各个模块的明细信息和运行状态;尤其是多子场景的结构展示,可以方便地让相关人员了解整体结构和模型调用链路。

三、主要组件

Model Service

Model Service即CodeGen自助生成的模型服务,它支持主流机器学习算法的调用,如Pmml,Python包,XGB等,结构图如下。

当模型确定时,在工程中实现的方式也就确定了,此时开发工程师只需要根据模型的类型,生成对应的模型服务。出于性能上的考虑,目前的实现方式是将生成的服务包引用到工程中,在本地调用。在调用时,将处理好的待预测数据输入,就可以得到预测结果,支持单条或批量调用。当然,模型算法在不断演进中,模型引擎开发组也会负责升级模型服务,此时使用方只需要简单地升级版本即可。

同时,模型服务也封装了最新模型版本的获取功能,自动感知和下载最新的模型文件,实现模型文件更替的分钟级别生效,屏蔽特征不变场景下版本迭代的细节。此外,不同实验版本调用不同模型文件,内测人员和外网用户调用不同模型的支持也由模型服务控制,调用方只需将实验版本和用户ID传入即可。

对待预测数据、预测结果的记录上传和模型服务的监控也由模型服务统一负责。通过规则设定,对上传的数据进行实时判断,及时发现异常。当然开发可以根据各场景的调用量、调用耗时要求选择抽样记录部分数据,避免对存储造成压力。

除了传统意义上的模型,规则和公式也可以认为是广义上的模型。相对于狭义上的模型,公式和规则训练复杂度低,实现简单,在现阶段上线模型代价比较高昂的情况下,是不错的选择。为了支持公式、规则变更等能够实时生效,模型服务也会在后续的版本中增加对其的支持。

Feature Bus

Feature Bus组件可以协助开发人员自动构建本地缓存,托管数据加载问题,其结构图如下所示。

通过配置XML文件指定数据源的存储方式、存储格式、本地缓存格式,结合Feature Bus的jar包,开发工程师可以轻松地在服务中构建本地缓存。大批量数据缓存在本地容易产生FullGC,进而引起服务响应的暂停,因此Feature Bus采取了堆内缓存+堆外缓存的设计方式。堆外内存把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机),能够在一定程度上减少垃圾回收对应用程序造成的影响。对于不需要缓存的轻量级数据,也可以通过Feature Bus直接读取。通过统一的API方式,开发工程师不再需要为不同的存储方式编写不同的读取代码。

另外,在实时服务中,缓存数据需要保证数据的实时性和一致性。缓存数据的更新又分为批量更新和增量更新。批量更新一般适用于相对静态的数据,例如对酒店静态信息,需要一天更新一次。Feature Bus支持在XML中指定更新的频率,根据实际需求进行批量更新。增量更新数据一般以消息的形式存在,例如用户点击行为,酒店起价变动数据等。在模型引擎的设计中,对这部分数据处理的延迟要求是秒级。Feature Bus支持在XML中配置消息来源、Topic、格式,进而对指定的实时消息进行监听,实时更新本地缓存,有效地将延迟控制在1秒以内。不管是批量更新还是增量更新对使用方都是透明的,使用方只需要评估使用场景,进行合理的配置即可。

四、总结展望

模型引擎是携程数据服务组对日常开发工作经验的总结和升华,从最贴近实际的场景出发,为模型上线的各环节提供便利。同时,作为一个综合性平台,模型引擎也从特征质量监控、模型调用监控等方面完善了对模型服务质量的把控。

项目自2017年年底启动,已经打通了模型上传、审核上线、更新迭代流程,支持AB实验,模型灰度验证上线、多模型融合、模型特征在线诊断等功能,接入了酒店排序类、图像识别类、广告类项目等十个项目。

目前模引擎平台已经进入了二期迭代,将在丰富特征库、支持更多类型的模型、完善模型质量在线评估等方面继续发力,并积极推广到其他BU。

【推荐阅读】