Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >干货 | 携程AI模型引擎设计与实践

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

作者头像
携程技术
发布于 2018-07-05 08:31:26
发布于 2018-07-05 08:31:26
1.6K0
举报
文章被收录于专栏:携程技术携程技术

作者简介

李媚,酒店数据智能组应用开发工程师。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。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 携程技术中心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python垃圾回收机制详解「建议收藏」
  平时在写代码的时候,关注的是写出能实现业务逻辑的代码,因为现在计算机的内存也比较宽裕,所以写程序的时候也就没怎么考虑垃圾回收这一方面的知识。俗话说,出来混总是要还的,所以既然每次都伸手向内存索取它的资源,那么还是需要知道什么时候以及如何把它还回去比较好。嘻嘻。
全栈程序员站长
2022/11/19
2K0
Python垃圾回收机制详解「建议收藏」
Python 的垃圾回收机制
如果减引用之后计数器不为0就会通过 _Py_CHECK_REFCNT检查引用计数器是否为负。
CS实验室
2021/03/22
7430
Python 的垃圾回收机制
python源码阅读笔记之GC
引用计数法 增量: 各个对象的内部都有计数器。如果对象的引用数量增加,就在计数器上加1,否则减1 #define Py_INCREF(op) ( \ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ ((PyObject*)(op))->ob_refcnt++) 下面的是含有NULL检查的宏 #define Py_XINCREF(op) do { if ((op) == NULL) ; else
哒呵呵
2018/08/06
8680
Python 垃圾回收机制与原理解析
Python 作为一门解释型语言,以代码简洁易懂著称,我们可以直接对名称赋值,而不必声明类型,名称类型的确定、内存空间的分配与释放都是由 Python 解释器在运行时进行的
公众号机器学习与AI生成创作
2021/10/20
1.1K0
Python 垃圾回收机制与原理解析
《Python 源码剖析》一些理解以及勘误笔记(3)
以下是本人阅读此书时理解的一些笔记,包含一些影响文义的笔误修正,当然不一定正确,贴出来一起讨论。 注:此书剖析的源码是2.5版本,在python.org 可以找到源码。纸质书阅读,pdf 贴图。
s1mba
2017/12/28
1.2K0
《Python 源码剖析》一些理解以及勘误笔记(3)
Python垃圾回收机制
如果将应用程序比作人的身体:所有你所写的那些优雅的代码,业务逻辑,算法,应该就是大脑。垃圾 回收就是应用程序就是相当于人体的腰子,过滤血液中的杂质垃圾,没有腰子,人就会得尿毒症,垃圾 回收器为你的应该程序提供内存和对象。如果垃圾回收器停止工作或运行迟缓,像尿毒症,你的应用程序效 率也会下降,直至最终崩溃坏死。
星陨1357
2023/03/14
6700
Python垃圾回收机制
剖析 Python 面试知识点(二)- 内存管理和垃圾回收机制
Python 中一切皆对象,对象又可以分为可变对象和不可变对象。二者可以通过原地修改,如果修改后地址不变,则是可变对象,否则为不可变对象,地址信息可以通过id()进行查看。
天澄技术杂谈
2019/04/05
1.1K0
Python 是如何管理内存的?
在 GitHub 看到一篇很不错的学习资料,其中提到 Python 是如何管理内存的,我看完后很有收获,如下:
somenzz
2021/08/19
1K0
Python的垃圾回收机制(引用计数+标
我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念。在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyObject。
py3study
2020/01/17
1.2K0
python内存管理与垃圾回收
陷阱:需要注意,因为给getrefcount传递了参数a,因此也导致了引用计数+1,所以打印的结果是2,但是实际引用计数是1,故:引用计数=sys.getrefcount(xxx) - 1
zy010101
2022/05/05
5100
python进阶(7)垃圾回收机制
现在的高级语言如java,c#等,都采用了垃圾回收机制,而不再像c,c++里,需要用户自己管理内存。自己管理内存及其自由,可以任意申请内存,但这如同一把双刃剑,可能会造成内存泄漏,空指针等bug。 python中也同java一样采用了垃圾回收机制,不过不一样的是:python采用的是引用计数机制为主,标记清除和分代回收两种机制为辅的策略
全栈程序员站长
2022/09/19
7370
深入理解Python内存管理与垃圾回收,再也不怕问了(二)
如果一个对象的引用计数为0,Python解释器就会回收这个对象的内存,但引用计数的缺点是不能解决循环引用的问题,所以我们需要标记清除和分代回收。
宇宙之一粟
2020/10/26
6380
深入理解Python内存管理与垃圾回收,再也不怕问了(二)
python垃圾回收机制(引用计数)
垃圾回收(Garbage Collection)大家应该多多少少都听过,但是什么是垃圾回收呢?我们这里说的垃圾回收肯定不是把垃圾丢进垃圾桶。现在的高级语言Java,C#等,都采用了垃圾回收机制,而不再是C,C++里用户自己管理维护内存的方式,自己管理内存是很自由,但是可能出现内存泄漏,悬空指针等问题。而垃圾回收机制作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用。
全栈程序员站长
2022/09/09
7190
python垃圾回收机制(引用计数)
玩懂Python垃圾回收机制,又有时间可以摸鱼了
我们写过C语言、C++的朋友们都知道,C语言是没有垃圾回收这种说法的。手动分配以及释放内存都是需要我们的程序员自己动手完成。不管是“内存泄漏” 还是野指针都是让开发者非常头疼的问题。所以C语言开发提及讨论最多的话题就是内存管理了。but对于其他高级语言来说,例如Java、C#、Python等高级语言,已经具备了垃圾回收机制。这样可以屏蔽内存管理的复杂性,使开发者可以更好的关注核心的业务逻辑。
查理不是猹
2021/12/12
8920
垃圾收集策略与算法
程序计数器、虚拟机栈、本地方法栈随线程而生,也随线程而灭;栈帧随着方法的开始而入栈,随着方法的结束而出栈。这几个区域的内存分配和回收都具有确定性,在这几个区域内不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。
黑洞代码
2021/04/23
3560
Python 进阶:浅析「垃圾回收机制」
花下猫语:近半个月里,我连续写了两篇关于 Python 中内存的话题,所关注的点都比较微小,猎奇性质比实用性质大。作为对照,今天要分享一篇长文,是跟内存相关的垃圾回收话题,一起学习进步吧! 作者:二两
Python猫
2019/09/19
2.2K0
Python 进阶:浅析「垃圾回收机制」
Java 垃圾收集器的垃圾收集算法
在 Java 中,垃圾回收是个基础而有趣的话题,本文主要讲解 Java 垃圾收集器的垃圾收集算法,首先,需要理解几个概念:
CS实验室
2021/03/22
5230
Java 垃圾收集器的垃圾收集算法
垃圾收集算法 Krains 2020-08-06
每个对象保存一个整型的引用计数器,假设有一个对象A,如果别的对象引用了A,就让A对象的引用计数器加1,如果引用失效了,计数器减1,当计数器为0的时候,该对象就是垃圾。
Krains
2020/08/10
3000
垃圾收集算法  Krains 2020-08-06
JVM垃圾收集详解
为每个对象标记一个引用数量,当这个对象被另外一个对象引用时它的引用数据就加一,当另外一个对象释放了对它的引用它的引用数量就减一。当它的引用变为0时意味着没有对象引用,就可以回收了
Java学习录
2019/05/15
4220
垃圾收集机制与内存分配策略
Java 语言与其他编程语言有一个非常突出的特点,自动化内存管理机制。而这种机制离不开高效率的垃圾收集器(Garbage Collection)与合理的内存分配策略,这也是本篇文章将要描述的两个核心点。
Single
2018/04/04
1.1K2
垃圾收集机制与内存分配策略
推荐阅读
相关推荐
Python垃圾回收机制详解「建议收藏」
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档