闲聊推荐系统中的曝光过滤机制
某天某时某刻在摸鱼,闲刷某乎,看到了一篇实用性很强的文章:【闲聊推荐架构】推荐系统的曝光去重该怎么设计?(点击阅读原文查看),仔细阅读了一番,发现写的是真不错,推荐大家去读,但是这篇文章可能是一个「工程大佬」写的,对于曝光过滤的设计实现层面写的很赞,但是对于偏向于算法层面的同学来讲,可能不是那么友好,因此提笔在该篇文章和一些话题讨论基础上,结合笔者自己的工作经验进行补充和介绍,如果大家有什么好的想法和提议欢迎在评论区留言!
1.曝光过滤问题的定义
相信做推荐系统的朋友对「曝光过滤」这个话题肯定不陌生,试想在某个电商平台中总是给你推你已经看过的东西,那么它的用户流失率肯定不低,在失去用户体验的同时,也并不能对商品做到有效的分发,因此就引出了「曝光过滤」这个话题。
曝光过滤,顾名思义,就是将历史曝光给用户的item不再重复的进行曝光,进而引申的是将已经曝光过的商品的高相似商品也进行过滤,当然这里也有另一个命题是:推荐结果中高相似度商品的去重问题。所以这里探讨的是三个问题:
历史曝光过的商品进行过滤 历史曝光过的商品的高相似度商品进行过滤 候选池中高相似度商品去重
历史曝光过滤中最重要的是用户的历史曝光序列怎么定义,比如跨场景、跨天等,高相似度过滤中如何定义item的相似度、跨场景、跨session的高相似度去重都是值得细细探究和深挖的点,这些内容会在第四部分进行分享。
2.在哪个阶段进行过滤
传统的推荐系统的流程包括:召回、粗排、精排、重排。在这些不同的阶段中,何时进行曝光过滤比较合适的?首先粗排和精排是不需要进行曝光过滤的,因为其天生的职责是排序,粗排是为了缓解精排的压力,选取比候选池小但比最终推荐结果大的一个池子给精排,精排则是优中选优,选出用户最可能喜欢的若干个spu曝光给用户。
其实常见的曝光过滤是在召回阶段完成的,但其实在重排侧也可以进行曝光过滤,我们依次来进行分析。
此处和文章作者表达的观点不同,文章作者认为历史曝光过滤在召回过程中做,高相似度曝光过滤在召回后做。小编则认为历史曝光过滤和历史曝光过的商品的高相似度商品在召回阶段做,至于是召回过程中还是召回后,取决于我们存储数据的引擎和推荐框架,候选池中高相似度的去重可以在重排阶段做,因为在召回后做的话目的是去重,减少粗排和精排的计算压力,但是目前在排序算法不那么复杂的情况下,计算资源没有什么压力,因此可以在重排阶段根据精排吐出来的结果进行去重。
2.1 召回阶段的曝光过滤
在召回阶段做曝光过滤,包括两种:
召回过程中做曝光过滤 召回后做曝光过滤
这两种做法至于怎么选,其实都可以,取决于底层的数据存储结构。如果我们底层存储数据使用的是es这样的检索框架,则可以在召回过程中进行处理,把用户的曝光序列和历史曝光的高相似度商品序列当作是一个not query的参数,进行查询即可。当然在es框架的基础下,也可以放到召回后去做,不过是多此一举罢了。
如果底层存储数据使用的是类redis这样的数据引擎,则可以在召回后做,因为kv存储结构并不支持查询时过滤。
2.2 重排阶段的曝光过滤
针对高相似度的商品去重其实也可以放在召回之后做,只不过可能对最终的结果是有损的。比如现在有一组高相似度的商品集合出现在了召回池中<A, B, C, D>,在召回后我们可以根据单一的排序指标,比如质量分等进行排序,取质量分最高的一个或者两个,但是针对用户来讲,并不一定是质量分高的就是一定会点的。
所以在计算资源允许的情况下,可以将高相似度商品去重放在重排阶段,即针对精排吐出来的top M结果中,对高相似度的商品进行去重,保留top1或者top2,这样可以保证用户看到的排序指标值最高的那个。
3.曝光过滤的实现
关于曝光过滤的工程问题,大概就是基于布隆过滤器 或者 布谷鸟过滤器,这里就不展开叙述来实现,因为也不是小编的专长,大家可以参考:https://zhuanlan.zhihu.com/p/392462871
这里主要讲一下其流程和思路问题。
3.1 历史曝光过滤
历史曝光过滤即用户在当时请求之前的曝光。在推荐中其实会对每个用户维护一个定长和元素定时失效的队列,比如说长度是300,时效是3天,那么用户的曝光列表就会按时间先后存放在该列表中。
如果元素个数达到了300,则会将最早放进去的进行淘汰,另一种情况是如果元素列表没有达到300,但是时间达到了3天,则会将达到3天有效期的元素依次清楚。
3.2 历史曝光过滤的高相似过滤
历史曝光过滤的高相似度过滤,这个就比较复杂了,首先我们要维护一份数据:商品对应的高相似度商品,这个是需要算法进行离线挖掘和评估的。
这个的一般做法是:结合商品主图和标题的相似度进行衡量,但是这个要求比较高,卡的阈值也比较高,可以多离线进行评估。
首先拿到用户的历史曝光序列,然后获取提前存储在redis中的商品对应的高相似度商品数据,行成一个列表,在召回时过滤或者召回后过滤。
3.3 候选池中高相似度商品去重
这个其实也依赖于我们提前挖掘好的商品对应的高相似度商品数据,一般会是在重排侧进行过滤。
假设这里精排侧吐出来的商品是50个,重排的目标就是对这50个进行重新排序,保证用户体验,比如高相似度去重、相似商品进行排列等。一般的逻辑是,对这50个商品进行遍历,如果其高相似度商品存在于50个中,则进行移除,保证最终展示给用户的一次请求结果中没有两个相似度很高的商品,在一定程度上保证用户的体验。
4.曝光过滤的延伸
曝光过滤其实只是推荐系统中最基本的一种保用户体验的机制,与之相关的还有:复购过滤、商品去重机制等,在过滤这个概念中,又涉及到了时间、地点等因素,就使得顾虑的策略变得比较复杂和多变。
4.1 历史曝光过滤中的时间问题
时间问题指的是保存用户的历史曝光序列使用过去多久的数据?1、3、7等?定多少天合适呢?也是要根据自己的业务场景的流量和用户的曝光次数探查进行决定的。
不过这里一般设计的思路:根据数据探查的结果设置一个可以动态调节的阈值(比如:300),再结合时间因素(比如3天)进行过滤。即曝光过滤的列表长度最大为300或者3天,进行综合控制。具体其实现可以参考上边「3」部分的内容。
这里需要注意的是这个阈值需要做成可配置的,这样便于动态的调节,否则每次修改都依赖于上线就很糟糕了!
4.2 历史曝光过滤中的场景问题
像京东、淘宝、美团这样的大的电商平台中,不同的场景模块是由不同的团队进行负责的,但是大家共享的是同一份底层的商品数据,那么就会出现用户在这个场景看到的东西,可能在别的场景中重复推荐。
比如在京东app中首页的「精选」和我的页面的「精选推荐」,两个场景下如果给用户重复曝光了同一个商品,或者高相似的商品是会引起很大的用户体验问题。因此在做推荐的过程中,就需要考虑这种跨场景的曝光是否需要对用户进行过滤,因为一些小的业务场景中是没有必要这么做的,因为还要考虑人力、算力、ROI等。
4.3 高相似度过滤中的跨session问题
在做推荐系统相关工作的过程中,经常被反馈的一个badcase是,这个东西我在上一页或者之前好像看过。这个其实反应的就是高相似度的商品进行了重复的推荐。
这里除了高相似度的问题以外,就是跨PV或者跨Session的问题,所以一般在处理时,如果这种case特别明显,需要加强处理,即对用户前几次请求中推荐过的商品进行高相似度的曝光过滤。
5.写在最后
曝光过滤问题是会伴随着推荐系统一直存在的,而且是一个持续优化的问题,不可能有一种完美的方法能够满足所有人的需求,因此要辩证的看待这些问题。
其次优化是伴随着badcase存在的,在做某一个具体的业务过程中,深入的分析case,然后进行总结和反思自己的算法模型、机制策略等,持续性的优化才是推荐系统更优的可行之道!