百亿级样本+亿级特征ranking实现

1. 推荐系统架构

1.1 推荐页请求流程

Feeds推荐线上模块一般有几个流程:

 1. 开始线上请求。
 2. 通过召回服务进行召回,从百万级的文章视频中召回大概几千甚至上万条新闻视频,然后经过筛选,进入Ranking服务。
 3. 进行精排,再经过混排
 4. 最后推送给前端进行展示。

线下模块涉及模型训练,模型训练首先要有数据,用到Feeds的展示,点击和停留时长等相关日志进行特征提取,主要提取用户特征、内容特征和组合特征,包括模型训练出来的高维特征。通过这些特征,进行模型训练,并将模型推送给线上Ranking服务,Ranking服务通过模型进行打分。

1.2 推荐页模块详解

1.2.1 召回

负责把用户感兴趣的内容提取出来,重点是全

1. 基于内容
   比如对NBA感兴趣,通过关键词,跟内容的一些关键词匹配之后进行召回。
2. 基于协同(用户行为)
3. 向量化召回
   把用户的一些点击行为转化为高维向量,向量之间有着相似性,根据相似性召回一些内容。
4. 高热召回(非个性化)
   一些要闻。

1.2.2 排序

负责对召回的内容进行打分,(可以理解为感兴趣程度,最终的打分不一定是CTR,它和CTR不可比),重点是准。

基于模型:GBDT,FTRL

Rank 模型演进
基于规则->LR->GBDT->GBDT+FTRL->Wide&Deep

1. 基于规则之前有分层召回,各层内容点击率不一样,我们有一个召回。
2. LR是一个线性模型,它的打分公式大概类似最简单的线性划分。
3. GBDT是Boosting树,相当于拿用户特征去做一些决策。
4. GBDT+FTRL是基于GBDT训练结果,把tree的一些特征作出索引,作为FTRL的一部分训练特征。
5. W&D是YouTube提出的,如果把deep层数设为一层的话跟LR其实是类似的。

1.2.3 混排

出于产品或者业务的考虑,对排序后的内容进行重排并最终展示。

1. 对一些内容进行提权(比如视频);
2. 相似内容隔离(两篇相似性很强的文章,就要进行打散);
3. 强插(对一些要闻,新文章和视频进行强插)。

2. 数据准备

2.1 训练数据-百亿样本

日志上报方式存储空间日志条数备注
Inview(曝光)url372.9G/day9926W/day近两个月平均
click(点击)url32.2G/day7998W/day近两个月平均
exit(停留时长)Data.do59.5G/day7407W/day近两个月平均
snapshot(特征快照)server17.5T/day24亿/day近一个月平均

训练样本有曝光、点击、停留时长和一些特征快照。数据量是取最近两个月或一个月的数据进行平均。像曝光日志每天大概370G,日志将近十亿条。点击每天大概30G,约8000万条。停留时长因为涉及到Data.do的上报,有部分损失,大概每天7400万左右。特征快照量比较大,每天17.5T多,有24亿条。我们Train的样本用到将近十天的数据,总的样本量大概100亿左右,每天样本大小12-14T左右。

2.2 特征介绍

2.2.1 特征类别

1. 数值特征:文章长度,图片数
2. Onehot: 内容类型(news或video),tree 特征等(取值0或1,要么在节点上,要么不在节点上)
3. Onehot with value: 用户对单类型内容的感兴趣程度(特征名里包含了value值),
   这个值可能是一个浮点数,我们将其离散化后,特征就带上了value,特征值就变成了0和1。

2.2.2 特征离散化

做离散化的原因是,LR是一个线性模型,但是目标函数与特征之间不一定呈线性关系,所以对模型特征做离散化,方便对特征进行更好拟合。

1. 等分离散化(0-100分,每一分或十分为一档,每档的数量不固定)
2.等频离散化(按照频次划分,每档的数量都一样)

2.2.3 特征数据-亿级特征

(1)用户画像(110W+)

1. 用户属性特征:性别、地域、年龄等
2. 统计特征:用户的类别偏好cats_cs、标签偏好tags_ck等

(2)内容画像(1250W+)

1. 固有特征:文章长度、关键词、图片数、分类、话题、标签等
2. 统计特征:文章的曝光、点击数等

(3)交叉特征(9500W+)

用户与内容的交叉特征:比如用用户感兴趣的话题和当前待推荐内容的话题交叉。
我们的文章topic,有64,128,256,512,1024维这样的划分标准。然后用户在各个话题上的兴趣度。
这样交叉后数据有一定膨胀,大概有9500W+,占了我们模型特征的90%以上。

(4)树特征(6W+)

  还有一些高维特征,将树训练之后,它的叶子节点作为特征,大概6W以上。

3.离线训练过程解析

3.1 全量模型的训练过程

我们每分钟会有一个进程去检测,看全量模型是否在训练,已经在训练,结束进程。如果没有,会读取最新的GBDT模型和当前Ftrl模型是否一致,不一致,就新起一个模型训练。一致的话就结束进程。

在模型训练开始的时候,需要回溯当前N天的日志并进行特征抽取,同一条样本、不同的GBDT模型预测出来的结果是不一样的,
如果用不同的GBDT模型、同一个ftrl模型预测,会导致特征偏差,模型就会失准。
我们在特征抽取时会更新特征的一些状态,这些训练语料一旦开始抽取了,就会更新这个状态,
等抽取完之后会将这些语料,然后开始一个全量模型的训练过程。
全量模型训练完之后,它会把全量模型的状态进行分析,进行模型推送,这是全量模型的训练过程。

3.2 增量模型的训练过程

依赖于增量特征,看增量模型是否有在训练,已经在训练过程中,就停止。如果没有,看有没有新的特征产生,如果没有新的特征产生,也不需要再进行增量训练,也停止。如果新的特征已经更新了,则开始增量训练,训练过程跟全量模型是类似的,增量模型训练结束进行增量模型的推送,推送完以后,更新模型的状态,标志着它已经训练结束,不需要再进行增量更新。

3.3 增量特征抽取过程

特征抽取也是每两分钟检测一次训练样本日志,看是否有准备好日志,如果日志准备好了,开始特征抽取,抽取后会更新这部分训练样本的状态。

4. 模型管理

4.1 模型状态管理

1. 模型版本控制:状态文件记录线上模型、预上线模型
2. 型训练状态:状态锁,是否训练中
3. 定时检查:每分钟检查
    我们模型最多有两个版本,一个是online版本,一个是预上线版本,
    保证其每时每刻最多有两个模型在进行训练和特征抽取

4.2 模型语料管理

1. 训练完的语料
2. 训练中的语料
3. 抽取完的语料
4. 抽取中的语料

5. 模型训练

5.1 GBDT

1. 单机xgboost->yarn集群
2. 样本:2亿(单机xgboost时训练样本大约3500W)
3. 300颗树,8层
4. 天级更新(3:00 am开始一个新的全量模型的训练)

5.2 FTRL

1. 基于开源alphaFM的二次开发(支持浮点变量(原先不支持)、LR—>weightedLR、分布式读取训练语料)
2. GBDT模型更新后触发新的全量训练(48h内)
3. 增量训练(半小时内)

6. 模型推送

6.1 生成模型配置文件

模型名称及md5校验值

6.2 推送模型及配置文件至HDFS目录

6.3 推送配置文件路径至Zookeeper

6.4 推送策略:高峰期不推送

模型推送方面,首先要生成模型配置文件,包括模型名称和模型文件的md5值,方便通过配置文件在推送服务器上进行模型校验。在推送时,需要先推送模型及配置文件到HDFS上,然后将配置文件路径到Zookeeper上,方便线上检验模型有没有增新。而且我们增加了一个推送策略,比如流量高峰期不推送。高峰期推送,Ranking服务在更新时可能会产生GC,导致延迟。现在我们做了一些优化之后,高峰期推送也不会有什么影响。

7. 模型评估

模型上线需要做一定的评估才可以上线。主要评估指标就是离线的auc,我们在相同的训练集和测试集上,跑两个模型,一个是线上模型,一个是实验模型。跑完以后比较两者在测试集上的auc,auc有一定幅度的提升,我们再开发线上模块,将实验模型进行小流量上线。上线后我们会实时监控,对比线上rank模型和实验模型的ctr,此外去看一些离线分析的指标,包括数据统计平台分析指标,以及每天的离线邮件报表(包含模型线上的ctr、auc、uauc以及预测成功率等指标)。

8. 线上Rank服务

8.1 模型更新

1. 定时检测(分钟级)zookeeper路径下的模型是否更新
2. 更新则从HDFS拉取最新模型,通过scp推送至ranking-server(194台)
3. Ranking-server异步加载模型后,热切换。

线上Rank服务有个监测服务会定时去检测zookeeper模型是否更新,更新之后会从HDFS拉取最新模型,校验模型和配置文件,校验一致则将模型及配置文件推送到ranking-sever(我们现在ranking-sever大概有194台),然后ranking-sever会有线程去异步检测,加载模型更新之后再热切换。

8.2 模型预测

1. 特征拼接
2. 分批预测
3. 超时取消

模型的预测,线上ranking-server在接到用户请求时会同时收到用户画像,接着会去做一个实时的特征拼接,再分批预测(我们每一个batch有八条内容)。

超时取消是接收请求100ms之后rank没有预测完,则取消后续的预测,当前预测了多少条返回多少,不然可能会导致线上超时。

8.3 线上模型更新

这是我们的推送服务,模型训练完以后,把配置文件推送给ZooKeeper,把模型推到HDFS,中间有一个监控服务,去监控Zookeeper,如果有更新,则从HDFS上拉取模型和配置文件,分发给ranking-sever。

8.4 特征快照Dump

上表是我们做的ranking-sever的另外一个改动,因为之前我们召回把用户画像传给ranking-sever,做完预测后,把用户画像和内容画像直接实时dump, 写入kafka里。
在我们的推荐场景中,一次用户请求大概需要rank 500条内容左右,但是我们实际推出只有大概8条,这样gap可能比较大,有很多dump的特征是无效特征。
对此,我们进行了部分优化,先把用户画像和predictid放到一个缓存里面,rerank之后再把predictId和内容Id列表返回给ranking-sever,ranking-sever根据这样返回内容去查是否命中Cache,没有命中就丢掉,有命中,我们就将内容画像和用户画像快照写入kafka,之后我们会有离线Camus服务,去读取kafaka消费,写入HDFS进行落地。

9. 经验分享

1. 对于时间变化统计特征,用户和画像的一些统计值,最好是线上服务时请求时直接生成,
   避免特征穿越的问题。
2. 模型上线之后,发现效果不好,离线AUC提升明显,线上效果不明显,
   基本可以肯定是线上线下特征不一致导致的,可以重点进行排查。
3. 针对线上线下特征不一致,最好用同一套的特征抽取框架,用相同的配置可以保证一致性。
4. 做特征归一化操作,特征里经常会遇见一些异常值,几百万上千万,可能输入进去错误。
   这个时候,先取log,在进行特征离散化,归一化之类操作。
5. 还有要做特征的非法检查,像inf、nan,一个是最大值,一个是控制,
   这样会导致模型训练出现一些异常的参数。
6. 对于用户请求,对同一个用户来说,每次用户特征都是一样的,
   相关用户特征可以只抽取一遍,避免计算的冗余。
7. 我们训练的数据量要尽可能的大,把训练数据放在HDFS上,训练上从HDGS上读,边读取边训练。
    而不是拉到本地再进行训练。
8. 线上模型要支持自动更新,过老的模型会导致效果下降严重。
9. 特征工程决定你的效果的上限,不管我们用什么模型,都是在逼近上限。

10. 面临问题

1. 推荐页与搜索页的特性不同

1. 搜索是带着query来的,结果与之相关性越高越好,不用太关心结果的多样性。
2. 推荐页用户没有明确的目的,但是有兴趣偏好和对结果的多样性需求,推荐既要准确又要多样化。

2. CTR预估模型是一个point wise模型,没有考虑单个内容与其他内容同时出现的影响。
3. 用户对感兴趣的东西会出现审美疲劳,(且每个人的疲劳的特点是不一样的) 要及时抓住这种特点,比如一个算法工程师看完几个机器学习文章后就不想再看了,这个时候要能推荐一些其他话题的内容。(这就是我们推荐需要注意的问题)

11. 未来方向

 1. 多目标学习
 它有一个多目标学习的网络,在学习过程中不只是学习CTR,还要学时长、学用户满意度等等。
 2. 组合推荐
 以后的推荐,不只是考虑推荐结果效率,可能还要考虑feeds推荐页整个的推荐效果。最终推荐结果可能是sequence的,要保证整个序列推荐效果最大化。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值