笔者简介:Pro是program(编程的意思),Lights是光线,fx和fxjh是名字缩写。喜欢写技术分享文章(推荐系统、游戏开发、acm算法)。
一、 文章背景
特征是什么?特征是推荐系统/搜索系统等AI应用系统的输入,是千人千面的基础。
特征平台服务于算法,提供丰富的特征用于模型的在线预测和再训练。
这里举个与西瓜书(《机器学习 周志华》)里类似例子来形象描述什么是特征以及怎么根据特征进行推荐服务。
比如西瓜有属性色泽、根蒂、敲声这三个属性。
有的西瓜:色泽=青绿;根蒂=蜷缩;敲声=浊响,
有的西瓜:色泽=乌黑;根蒂=稍蜷;敲声=沉闷,
还有的西瓜:色泽=浅白;根蒂=稍蜷;敲声=清脆。
这里色泽、根蒂、敲声,我们都称之为西瓜的特征,而青绿、乌黑、浅白都是是西瓜色泽特征的可能的一种取值。
比如一个“色泽=浅白;根蒂=稍蜷;敲声=清脆”的西瓜,用户尝了之后“八分甜”,这里的”八分甜“就是一个label。最终“色泽=浅白;根蒂=稍蜷;敲声=清脆|八分甜”就构成了一条训练样本。
再比如已经上线了一个冷启动的模型(这里指训练完成后导出模型文件用于线上serving,而不是算法模型结构)。当来了一个特别喜欢吃“七分甜的西瓜”的用户来了之后,系统会挑出一部分西瓜,加上“七分甜”,去模型里给这些西瓜打分,然后把分数最高(最可能符合用户七分甜预期)的一匹西瓜推荐给用户。然后用户给出的行为反馈有个西瓜是“五分甜”,那么我们又收获了一条样本“那个渣渣西瓜|五分甜”,进行再训练。
所以最开始推荐的可能不准,但等样本量足够大,用户的行为足够多,推荐系统可以推的越来越准。(关于推荐系统,详见笔者的另一篇文章《浅谈NB推荐系统架构》https://www.prolightsfxjh.com/article/the-architecture-of-nb-recommendation-system/)
二、 背景与目标
1、 NB特征平台的背景
不断会有新产品立项和上线,故特征平台需要着重考虑新业务和新事件的接入的成本。并且新团队的推荐和搜索很可能是一个不大的团队,大部分是算法同学,工程支撑同学可能会很少。从需求出发,算法同学需要一个可以高效便捷上新特征新模型的平台。
2、 NB特征平台的目标
这就需要工程支持同学提供尽可能灵活快捷可配置化的生产和加工特征的平台,以支撑推荐和搜索的业务场景。
三、 NB特征平台的整体架构
1. 浅蓝色是指业务系统。
2. 深蓝色是特征平台内部。
3. 灰色是第三依赖。
从上到下,分别是业务层(各个具体的业务场景),应用层(推荐系统、搜索系统、业务画像平台),特征在线系统,特征流式系统,特征离线系统,特征数据存储。
其中特征查询服务、在线特征工程服务、特征标准化服务、模型打分代理服务使用c++写的,其余服务是用go写。
用户触发推荐页或者搜索的时候,feed服务(精排或者重排)或recall服务(粗排)会把用户id和一堆待打分的物品id,传给模型打分代理,然后特征系统内部会去查特征、做在线特征工程、特征标准化、然后去掉serving服务进行打分并返回给上层推荐系统或者搜索系统。
四、 特征平台的整体流程
如上图
先在特征管理平台网页进行特征注册以及接入的消息队列和schema、一些模型id等配置。
然后是从原始数据到原始特征,再到工程化特征,最后到标准化特征,再到样本的整体流程。
1. 原始数据:NB特征平台的原始数据的源头主要是各个业务DB的binlog的Kafka、线上事件埋点Kafka、第三方画像平台的数据(Hive表导出到Kafka或在线查询接口的方式都有)。其中用户行为和业务DB是流式数据,第三方平台数据是离线数据(入库的时候依然转成流式)。
2. 原始特征:原始数据从数据源触发消息队列,然后根据走一个流式的特征抽取服务,写入特征KV存储或者时间序列数据库。此时的特征笔者称之为原始特征,因为它人类行为或者人类信息触发,并且人类可读。
3. 工程化特征:在线使用的时候,会先查出原始特征,然后进行特征转化(也可以叫特征工程),得到的特征笔者称之为工程化特征,这是有请求触发的,延迟计算的特征。
4. 标准化特征:工程化特征经过一定的标准化变成机器可读,人类无法直接识别的特征,笔者称之为标准化特征。
5. 原始样本:由用户特征+一个物品的全部需要的特征+全局环境特征经过一些列加工后得到的标准化数据称之为原始样本。原始样本之后join拼接上label之后,可得到训练样本。
/*下面这段文字没有注意放哪,先放到这了*/
关于特征的分类,按照使用方式划分是
1. 非模型类的,例如召回trigger,过滤,重排等
6. 模型使用,需要特征转换+标准化。
其它具体的NB特征分类标准之后会出单独的文章来分享(《NB特征分类标准》https://www.prolightsfxjh.com/article/nb-feature-classification-standard/)。
后文会通过特征抽取、特征查询、特征转化、特征管理平台这4个小节来介绍(特征标准化由于脱敏的原因这里没法说)。
五、 特征抽取
1、 初始版特征抽取流程
原始特征又被笔者根据计算方式分成3类
基础特征:从业务DB产生的Binlog直接简单抽取,然后入库生成基础特征。
实时特征:Flink实时计算,然后存入KV存储。
窗口类特征:Flink窗口计算,中间数据存储在HDFS,最终特征存储在KV存储。
2、基于时间序列数据库的特征抽取
如何灵活可配置化的批量进行特征的抽取?
笔者的方案是搭建基于时间序列数据库来进行特征抽取流程。
时序特征之后会出专门的文章来介绍,这里只举几个列子,
Ø1、近n个时间单位的用户action属性序列
Ø2、近n次的用户action属性序列
Ø3、近n个时间单位的用户action属性的聚合
Ø4、满足具体条件的近naction特征
主要解决的问题是:
1.长序列的存储。
序列特征存储在KV存储的话长度上限很小。时间序列数据库没有上限限制。(比如近300天用户点击位置类别的序列)
2.具有更好的实时性。
目前的近n xx序列特征是小时或者天级更新的,使用时间序列数据库的可以实现秒级更新延时。
3.灵活的生产序列特征。如果没有tsdb新增一种近x填的特征,就需要一定的开发量。而时序特征是推荐的主要特征
基于tsdb可以有算法同学做特征设计的时候直接配置下,即可生成一系列的特征。
比如1、该用户近n天的点击文章类型序列 2、该用户近n次点击的文章标题序列 3、该用户近n小时点击的商品的最小价格 4、该用户最近半小时停留时长>2s的类目id序列等。
3、优化版时序特征的生成-优化版
每次调用的时候在线生成时序特征,耗时非常的高(约上百ms),怎么降低在线获取时序特征的延时以提高用户体验?
笔者的解决方案:在流式(近线)环境下产生事件的时候就提取生产好时序特征并写入KV存储,线上使用直接查KV存储即可。(优化后约毫秒级)
不过这样做有个缺点,就是对时间序列数据库的压力比较大,比较费资源。
六、 特征查询
1. 特征查询耗时依然偏高如何优化?
解决方案:使用基于一致性哈希的负载均衡的分布式缓存。
思考过程:
优化前:每个服务实例都使用上百GB内存来缓存尽可能多的数据,缓存命中率90%。
一是缓存的数据占数据总量的比例还是太小,导致频繁的容量淘汰,缓存命中率并不高,
希望达到95%以上,并且再压一压延时。
二是每个服务实例都缓存几乎一样的数据,导致浪费了大量的内存,希望有效降低内存消耗。
所以想做分布式缓存,希望所有的服务实例加起来是一份全量数据,每个实例只存一个
分片,优化掉老方案的大量冗余内存,并且由于全部的数据都缓存住了,
得以提高缓存命中率,降低查询延时。
2. 一致性哈希的应用:
对用户id或者物品id进行哈希,然后根据哈希值去哈希环上找到对应的服务实例地址,然后去该用户id或者物品id的特征数据。
这样相同的用户id或者物品id的请求会一直打到同一批服务实例上,这批id在这批服务实例上访问频率很高,一直是热点,这样相对普通加权负载均衡,可以使得目标特征在这批服务实例上一直不被淘汰,使得缓存命中率大幅度提高。
3.分布式缓存的容灾逻辑:
1、如何扩容?
该服务存的是一个数据分片的缓存,下层有全量数据的落地,故扩容之后继续累积缓存即可,不会导致数据丢失。会有短暂的数据不一致,但推荐模型的机制使得只需要特征达到最终一致就不会影响个性化推荐带来的业务效果。
2、如何迁移?
可自动迁移,原理同上。
3、如何重启或发布?
重启或者发布之后,之前的内存热点缓存也都清空了。(这个等同于缩容之后再扩容)。
4、如何容灾?
默认是至少2个服务器实例作为一个哈希环上的区间分隔点,它们相互备份,
备份的份数可以通过配置控制。
注:避免大规模的扩容或者重启或者发布,
需要少量节点并且持续时间很长的分批操作。
4.优化结果:
优化后:优化了大量机器内存成本,主调延时被调延时减低,热点缓存命中率非常高。
七、 特征转换与算子DAG
业务多,特征种类多,相同的特征在不同模型可能需要不同的加工方式,不同的特征也可能需要相同的加工方式,如何减少重复开发?
1. 解决方法:
参与共建共用特征工程框架,共同累积算子库。配置好算子,在线特征工程根据DAG图的拓扑序执行算子,最终把特征工程处理之后的特征输入给模型。
2. 算子示例:
map_get算子:输入用户特征是对各个类目物品的点击数量和物品的类目id,求得用户对该类目物品的点击数量。
map_get算子:输入用户特征是对各个类目物品的曝光数量和物品的类目id,求得用户对该类目物品的曝光数量。
除法算子:输入用户对该物品类目的点击和曝光次数,求得该用户对该物品类目的曝光点击率;
等距分桶算子:输入上述的曝光点击率,(区局最大值,分桶个数是配置的常量),求得属于哪个分桶。
3. 配置示例:
a’ =f1(A,B)
c’ =f2(C,B)
ac =f3(a’,c’)
ac’ =f4(ac)
E =f5(ac’)
D =f6(a’)
F =f7(c’)
4. 算子执行DAG示意图
圆形框是各自特征工程算子。
5. 收益:
算子库多业务共建,减少开发成本。
抽象成算子,可复用性强。
屏蔽工程细节,算法同学仅需要配置DAG即可。
八、 管理平台
怎样进行方便灵活的特征配置与管理?
比如特征设计(生命周期、特征血脉等)、模型绑定特征、特征发布、特征监控、特征校验、权限控制。
解决方法:搞一个特征管理平台网站,封装上线细节、自动化支持各种约束条件(用系统来约束操作,而非人为约定操作),减少人工操作出错可能性。
。
特征管理平台网页截图
九、 NB特征平台最终效果
最终耗时一年多,从零搭建了可通过在特征管理网页上添加一些配置,就可以接入新业务新事件,来生产出一批量新的特征的特征平台。
本博所有文章均为博主原创,未经许可不得转载。
https://www.prolightsfxjh.com/article/nb-feature-platform/
Thank you!
------from ProLightsfx
如果对笔者的文章感兴趣的话,欢迎关注公众号。
本博所有文章均为博主原创,未经许可不得转载
如经许可后转载,请注明出处:http://43.154.125.150/article/nb-feature-platform/
ProLightsfx
感悟:做过的很多东西,如果不趁早反思总结一下,整理后写成文章沉淀下来,时间长了也就忘了。
上周末整理了下两三年前做的特征平台!之前一直没有整理,现在总算是整理好了