zz京东电商推荐系统实践

 

挺实在算法

 

 

今天为你们分享下京东电商推荐系统实践方面的经验,主要包括:架构

  • 简介
  • 排序模块
  • 实时更新
  • 召回和首轮排序
  • 实验平台

简介

说到推荐系统,最经典的就是协同过滤,上图是一个协同过滤的例子。协同过滤主要分为俩种:user-based 基于用户的协同过滤和 item-based 基于商品的协调过滤。框架

可是,如今绝大多数推荐系统都不会直接使用协同过滤来作推荐。目前主要用的是 learningtorank 框架。分布式

这里,是推荐系统的框架,整个推荐系统能够分为两部分,在线部分和离线部分。函数

  • 在线部分主要负责当用户访问时,如何把结果拼装好,而后返回给用户。主要模块有召回、排序和对结果的调整。
  • 离线部分主要是对用户日志的数据分析,应用于线上。

整个推荐系统大概就是这样的一个框架。工具

和新闻、视频这类的内容推荐相比,电商推荐系统又有一些特殊的地方,好比:性能

优化方向(点击、销售额、时长、用户留存等)。另外,电商中推荐的内容也会有不少种,尤为像是活动类的内容,不少推荐都是算法和人工运营共同完成的。这就是电商推荐和新闻推荐等的区别之处。学习

咱们展开看下在线推荐系统:优化

除了刚才说的召回和排序以及最终的调整以外,还有实践过程当中的一些细节。3d

  • 召回:这里召回会有不少种方法,如协同过滤,热门商品、实时促销等和应用场景相关的召回,还有一些基于 KNN 的召回。
  • 过滤:召回以后,会进行过滤,主要是和应用场景相关,如已购商品过滤掉、没有库存的过滤掉,或者敏感的商品过滤掉等等这些逻辑。
  • 排序:排序目前主要用到的是 DNN 模型,某些流量比较小的地方会用到 GBDT。
  • 过滤:排序以后还会有些分页、同商品过滤等逻辑。

调整:最终调整过程当中,主要有两部分逻辑,多样性和探索逻辑。

排序模块

1. 模型结构

深度学习 ranking 模型结构咱们不做为重点讨论,这里列举了一种最经典的模型,它们都用到了不少 id 的 Embedding,而后这些 Embedding 规模都很大,这样训练和上线都比较耗时。所以,咱们作了一些优化,好比作分布式的训练,而且会有一套 Pipeline 来完成模型的上线。另外,虽然模型很复杂,而且能带来很好的效果,可是特征工程仍是必不可少的,不少指标的提高仍是依赖于特征工程,固然也包括一些模型调整的工做。

2. 实践

那么如何把这些模型落地呢?咱们看下整个模型的上线过程:

首先最重要的部分是模型训练平台和排序服务,由于不少深度模型计算量要求很高,为了能达到比较快的效果,须要部署单独的排序服务。目前比较流行的是 TensorFlowserving,能够很快速的来上线一个深度模型,并充分利用对分片、单机并行,达到很高的计算效率。

模型线上线下一致性问题对于模型效果很是重要,咱们使用特征日志来实时记录特征,保证特征的一致性。这样离线处理的时候会把实时的用户反馈,和特征日志作一个结合生成训练样本,而后更新到模型训练平台上,平台更新以后在推送到线上,这样整个排序造成了一个闭环。

3. 实时更新

咱们的特征和模型都须要作实时的更新。由于咱们常常须要很快的 catch 一些实时的信号,好比须要实时的用户画像来抓住实时的用户兴趣的变化,还好比须要抓住实时的商品画像,由于常常会有一些活动或者爆品,咱们须要快速的捕捉这些信号,并应用到推荐中。另外还有一些实时的召回和特征,好比一些交叉的特征,实时的点击率,实时订单等特征。

除了特征外,模型也须要实时更新,对于电商场景来讲这是有必定困难的,由于订单是有延时的,延时多是十几分钟到十几小时不等,这样实时模型更新上就会采起一些保守的策略,好比用点击率对模型作些微调,而后订单数据再经过离线来得到,这属于业务场景的限制。

思考

排序能够算是推荐系统中比较重要的一个环节,可是只有排序确定是不够的,事实上,有一些问题是目前的排序框架没法解决的:

  • 排序获得的结果很是类似,影响体验。
  • 有多个优化目标,须要一个平衡(点击率、订单金额、用户交互时长等)。
  • 计算能力有限,若是有无限的计算力,能够直接对所有候选集进行排序。

1. 多样性

使用模型输出的结果通常都会很是类似,若是直接给用户看体验会不好,所以在模型以后咱们须要加入多样性的逻辑。

比较通用的解决办法是多样性的 ranking,这是一个贪心算法,从第一个商品开始选,当选第二个商品的时候,会从新计算下候选集中每一个商品的 score,而后选择一个 score 最高的。咱们的方法是看 noveltyscore 候选商品的产品词分布和以前 N 个商品的产品词分布的 KL 距离。这样作的思路,就是选一个和已有商品最不像的商品,来更好的保证商品推荐结果的多样性。

因为纯基于算法的多样性可能会出现 badcase,所以还须要一个规则来进行兜底,确保在极端状况下结果也能接受。

最后,咱们思考一个问题,有没有更好的方法实现多样性的逻辑呢?固然有,好比是否能够考虑使用 listwiseranking。这里只是为你们分享一个比较容易的,而且效果比较好的方法。

2. 多目标

咱们的优化目标有不少,好比点击、转化、时长等,问题会变得比较复杂,单一的模型训练很难覆盖到全部指标。另外,常常咱们须要在各个指标之间进行权衡,所以可调试性也很是重要。

一种颇有用的方式是多模型 ranking,而后用某种方式把全部模型的结果 combine。

这也体现了一个思想,在算法的实际应用中,其实须要在算法的先进性和系统可维护性、可调试性之间作一个平衡。每每 paper 里颇有创意的算法落地的时候是有些困难的。

3. 多轮排序

下面咱们讨论一下多轮排序的问题。多轮排序是 learningtorank 实践中很重要的一个思想。使用多轮排序主要是由于计算资源的限制,没法使用复杂的模型进行大规模的候选集排序。右图描述了一个多轮排序的框架。这像是一个漏斗模型,从上往下模型的复杂度是递增的,同时候选集是逐渐减小的,就是越到后面用越复杂的模型来保证效果更好,越到前面可能只须要简单的模型来保证能拿到一些商品就能够了。

这样会存在一个问题,因为训练样本可能有偏,致使只有被用户看到的样本才有 label,可是通常不会有太大的影响。

基于索引的首轮排序

1. 索引召回

下面咱们重点介绍一下第一轮排序。倒排索引很常见,是信息检索里经常使用的工具。它经过把 doc 的内容索引到 docid 的方式,快速经过内容来查找 doc。咱们不少召回都是经过索引实现的。这里我列举了一些基于索引的召回方式,如 itemcf 的 key、产品词、热门类目、促销产品词等。

虽然索引可以很大程度上的缩小候选集的范围,可是常常状况下,第一轮排序的 doc 数量仍然可能会很大。为了保证性能,截断逻辑是必不可少的。经过状况下能够经过 qualityscore 截断,保留质量好的 doc。通过线性的 LR 或者 GBDT 模型就能够有结果了。另外截断以后须要有些多样性的逻辑,由于只有在召回的时候保持多样性,最终结果才会有多样性。

基于 qualityscore 截断是一种 naive 的算法,这里咱们讨论另外一种业界也较经常使用的算法,wand。wand 实际上是 weakand,它的重点是 wand 操做符。wand 操做符是一个布尔操做符,当 Xiwi比θ大时,它的值是 1,不然是 0。之因此叫作 weak-and,是由于当 w 都取 1,θ取 K 时,wand 操做符就变成了 and,当 w 取 1,θ取 1 时,wand 操做符就变成了 or。能够看出 wand 是介于 and 和 or 之间的操做。对 Xiwi 求和的操做其实和咱们线性模型很类似。经过 wand 操做符,咱们能够定义一些上界,由于是倒排索引,能够给每一个索引链赋予一个估计值,这样就能够拿到权重上界 UBt,这样经过和 wand 操做符对比,就能够快速的判断 UBt 是否知足条件,若是知足条件就能够快速的把一些 doc 扔掉,这样就能够快速的使用线性模型对全户作 ranking。能够看到,基于线性模型的分数作截断,比彻底基于 qualityscore 截断的策略要稍微好一点。

这里我列了 paper 中 wand 算法的伪代码。出于时间关系,咱们不会过算法逻辑的细节。我认为它的主要的思路是经过快速使用 upperbound 作截断和跳转,能够略过不少明显不符合的候选 doc,从而减小计算 score 的次数。固然这种方法对于线性模型来讲,有一个缺点,当咱们须要多样性的时候,没办法很好的实如今模型中增长多样性的。

wand 算法目前已经应用很是普遍了,在不少开源的索引如 lucene 中,也会用到这种方法快速计算文本相关分。

刚刚咱们介绍了使用倒排索引作第一轮排序,以及一个常见的排序加速算法,回过来咱们思考一下倒排索引自己,它适用于什么场景,不适用于什么场景。

首先它适用于 kv 查找这种场景,而且 kv 查找也属于实际应用不少的状况。可是对于更复杂的方式,相似 graph 的召回方式不友好,好比找用户看过的商品中类似商品的相关商品,这时实现起来会比较麻烦,这是它的一些限制。再一个,咱们须要有较好的截断策略,例如底层使用 relevencescore 截断,排序使用 GBDT。

固然,索引还会受到机器自己的内存限制,限于机器的大小,不少时候咱们须要多机分片部署索引,这样会带来必定的复杂性。虽然有些限制,可是索引是目前应用很普遍、有效的方式,包括在推荐、搜索等领域都会使用到。

2.KNN 召回

除了索引召回,KNN 也是如今较经常使用的一种召回方式。首先,咱们把全部的候选集转换成 embedding,咱们把用户兴趣也能够转换成 embedding,经过定义 embedding 之间距离计算公式,咱们能够定义 KNN 召回问题,也就是在所有候选池中,找到与用户最接近的 k 个结果。

定义好 KNN 召回的问题,下一步就是如何找到最近的 K 个候选集。因为整个候选集很是大,每次都使用用户的 embedding 去全量计算距离是不现实的,只能使用一种近似算法。咱们今天分享其中的一种近似算法。是 facebook 开源的 KNN 计算库 faiss 使用的。其原理:

首先须要对所有候选集进行分块,每一块都会有本身的质心。paper 中使用 Lloyd 算法,将整个空间划分开。分块后,就须要对每一块构建索引,进而经过索引实现快速检索的功能。

右图是索引构建和检索的方法。

上半部分是如何构建索引(这里的优化点是使用了二级索引):首先拿到 y 候选集以后,作一个 quantizer 分类获得一个一级索引,把它放到索引表中,另外还获得残差 computeresidual,能够对残差再进行一次 quantizer,获得一个二级索引,经过两级索引来加快检索的速度,同理,在真正的 quary 的时候,拿到的是用户的向量 x,先作一个 quantizer,获得 k 近邻的一级索引,而后查找 k 个一级索引,同时拿到 k 个二级索引,而后在二级索引中查找,而后这里还有不少加速的算法(这里就不展开了),经过这样一种多层的查询方式来作到加速 K 近邻的算法。

PS:关于 KNN 的一些思考,KNN 是一种有效的方式,可是不是惟一有效的方式。好比以后分享的 TDM,可以比 KNN 更加灵活。

实验平台

最后简单介绍下分层实验平台,由于你们想快速迭代特征和模型,离不开实验,常常会遇到的状况是实验流量不够用了,这时就须要对实验作分层。分层的逻辑见右图,经过在不一样的 Layer 使用不一样的哈希函数,保证每一个 Layer 之间流量是正交的,这样就能够在不一样的 Layer 上作不一样的实验。

分层实验的具体作法:召回 -> 排序 -> 后处理 -> 业务,另外还有一部分对齐流量,用来作全量的验证。

分层的优势,能够用于作实验的流量多,适合快速迭代;缺点,须要严格控制层与层之间的关系,防止相互干扰。本次分享就到这里,谢谢你们。

做者介绍:

孟崇,京东推荐架构负责人。负责京东推荐系统的 ranking 算法架构和模型训练。硕士毕业于中科院自动化所,前后在 yahoo、猎豹移动和京东从事推荐的工做,有丰富的推荐算法经验。

本文来自 DataFun 社区

原文连接:

https://mp.weixin.qq.com/s/vpANPrl86Ou2fBVHgLXtBQ

相关文章
相关标签/搜索