导读:58同城作为分类信息网站,服务覆盖多个领域,如房屋租售、招聘求职、二手买卖等等,不同的业务有不同的特点,这使得多业务融合推荐成为一大挑战。如何准确挖掘用户的需求?如何平衡各业务之间的流量分配?如何增加多样性提升用户体验?这些问题将在本次分享中解答。
01
推荐系统整体架构
58的推荐系统架构主要分成三部分:
对外接口层:负责对外输入输出、展示功能,服务于首页、详情页等等场景;
业务逻辑层:包含推荐系统的主要模块,如兴趣服务、召回模块、排序模块等;
数据算法层:负责底层数据的存储和处理,如业务、日志数据,提供召回源、排序模型、数据缓存等一些服务。
在推荐系统中需要持续优化的环节有召回、排序和重排。召回方面,58团队采用用户兴趣召回和向量化召回相结合的方式,其中向量化召回是通过word2vec、深度兴趣模型等多种方式构建帖子的向量化表征;排序方面全量采用深度学习模型,同时也在探索多目标一体化深度学习模型。
02
场景介绍
58同城首页信息流位于app的下方,其中包含多个业务门类,如招聘、租房、二手车、二手房等,在58内部把这些信息统称为帖子。一个帖子代表某个用户发布的信息,比如一个二手车帖子,包含某个用户发布的二手车车型、车系、公里数、价格等等信息。
特点与挑战:
本文主要优化的是58同城的首页信息流,这个业务场景的特点有:
强兴趣:大部分用户都是带着自己的需求进入app;不同的兴趣周期有所差异,比如租房周期短,买房周期长。
多业务:首页的访问量较大(千万级别pv),如何把流量分配给不同的业务就很关键。
推荐感知:虽然用户的目标单一,但是如何做到推荐结果的多样性就需要对其优化。
58app首页推荐业务 ( 多品类推荐 ) 主要面临的挑战在于:
如何满足用户对于不同品类的兴趣?( 用户兴趣问题 )
推荐的业务比例如何和平台的业务比例进行匹配?( 流量分配 )
是推荐单一品类效果好,还是推荐不同品类的混排?( 混排策略 )
如何平衡CTR和多样性?( 动态刷新机制 )
03
重排优化
1. 兴趣策略
这个优化主要针对第一个挑战:强兴趣下的多业务融合。
常见的推荐系统,如新闻推荐、视频推荐、商品推荐等都是要先建立用户和商品之间的联系,然后通过适当的算法进行匹配。在58同城中,用户既有买家也有卖家,所以不仅要构建用户和商品的联系,还要构建买家和卖家之间的联系。这就需要分别为用户和商品打标签,这也是兴趣策略的重点。
以图中租房用户为例,先分别提取租客寻找房子的标签和房东在帖子中提供的标签,然后在两者之间建立联系形成匹配。
然而,如果直接利用原始的标签进行推荐,那么效果肯定是不理想的。为了改善推荐效果,还要通过一定的策略挖掘出用户当前最迫切的需求。
在对原始策略进行优化时需要考虑以下几个方向:
实时性。用户的兴趣会随时间而变化,要突出用户新的兴趣,就需要把时间较长的历史兴趣和实时兴趣分开处理,给予不同的重要性。
兴趣分层。在推荐时,不同匹配程度的兴趣往往会混合在一起推荐,这时候就需要对兴趣加以区分。
兴趣去噪。权重比较低的或者比较久远的兴趣会影响推荐结果,需要对兴趣进行去噪。
向量化兴趣。从标签的兴趣逐渐过渡到向量化的兴趣,逐渐与向量化召回相结合。
那么具体如何操作呢?下面结合优化的方向,介绍打标签的具体步骤:
第一步:数据抽取
通过埋点数据获取用户的行为,典型的方法有两种:
通过点击行为抽取对应的标签组。如上图通过租房点击抽取出地域、价格等标签;
使用转化行为。即利用点击后有的进一步的操作行为,如打电话、提交简历、实际成交等,这些行为信息量更大,会被赋予更高的权重。
第二步:数据清洗
对重复或错误的埋点、缺失或错误的字段进行修正。
第三步:兴趣分类
太久远的标签可能不符合当前用户的需求,比如以下几种经典情况:
兴趣消失:某用户几周前找保洁,现在很可能没有这个需求了;
兴趣转移:某用户两周前找工作,现在找到工作需要找房子,那么兴趣就由找工作转移到租房。
考虑到以上情况,58把用户兴趣分成历史兴趣和实时兴趣两大类。
第四步:兴趣计算
通过两个独立的流程分别处理历史兴趣和实时兴趣,这里还要考虑两种兴趣的存储系统是否分开,信息结构是否保持一致。
历史兴趣一般就是每天例行的召回形成
实时兴趣主要由实时流式服务提供
第五步:兴趣衰减
58采用的这个衰减公式简单直观,经过相同的时间衰减的程度是一致的。具体的参数可以通过abtest来检验,上面的表格是对比不做时间衰减情况下的检验结果,其中参数选择7天的效果最好。
经过时间衰减后,用户近期兴趣的权重会上升,而太久远的兴趣的权重会下降,这样可以解决以下几个问题:
同一业务内的兴趣转移:比如用户在A小区找房子后来转去B小区找房子
不同业务之间的兴趣转移:比如用户前几周找工作,现在找房子
兴趣消失:比如用户在一个月前找保洁,现在已经没有这个需求了
与此同时,还要考虑不同业务之间的差异,并根据差异设置不同的系数。比如二手房的成交周期很长,租房的成交周期就比较短,那么这两者的衰减速度就可以设置不同的值。
第六步:兴趣合并
这里分为时间和品类两个维度
时间维度:把用户不同时间的兴趣合并在一起,形成一个时间段内用户兴趣变化的序列,可以用于排序召回的分析;
品类维度:把不同品类的兴趣合并在一起,形成用户在不同领域的画像,可以用于类似兴趣转移分析、新内容试探等多样性优化的尝试。
这些兴趣汇总以后最终形成一个用户所有时间段内所有业务的基础数据
第七步:兴趣合并
有的标签之间可能会有冲突,比如在正常情况下,真正有购车需求的人不会同时关注经济实惠的平价车和昂贵奢侈的豪华车。然而在实际的数据中,会发现一个用户同时存在40万以上和5万以下这种冲突的标签,如果同时采用这些有冲突的标签计算推荐结果,那么会造成很糟糕的用户体验。
58用户在二手车价格标签上的分布,可以看到也就是说大多数用户只会关注1-2组价格区间,如果同一用户关注的价格区间超过几个,那么这种用户可能就是车商。
通过聚合策略可以避免同一类目的兴趣过于分散,这样更容易贴近用户的需求。58采用了优势组直选和长尾组淘汰两种方式:
优势组直选:直接保留权重最大的价格组,淘汰剩下的其他价格组。一般权重比较集中的情况下使用这种策略,比如上图的第一个例子中,关注5-8万价格区间的占比70%,那么仅保留该区间,淘汰剩下的其他区间。
长尾组淘汰:淘汰占比很小的价格组,保留剩下的其他价格组。一般权重比较分散的情况采用这种策略,比如上图第二个例子中,前面两个价格区间虽然占比较大但优势不明显,而最后一个价格区间权重小,那么就淘汰最后那个价格区间,保留前面两个价格区间。
第八步:兴趣去噪
这一步的目的是除去相关性低的兴趣,主要有以下几类:
由于时间久远导致兴趣降低
误点击或日志错误导致记录的兴趣有误
根据我们的数据调研,权重比较小的兴趣占比不会高于15%,淘汰这些兴趣会有一定的效果改善,比如上图中把位于6%和4%这样的兴趣删除以后效果会得到改善。
第九步:兴趣扩展
相关扩展:在用户原有的兴趣基础上进行小范围的修正或拓展
泛扩展:用户原有的兴趣非常少导致召回通道产生的候选集不够,需要更大范围地对这个用户的兴趣进行扩展。
从表格中可以看出不同类型的兴趣效果不同,扩展出来的兴趣的效果远低于原始兴趣,而泛扩展的效果会更差。所以在展示的时候,需要对它们进行分层并设定优先级,原始兴趣的优先级比较高,相关扩展和泛扩展的优先级比较低。
另外,兴趣扩展的方法可以分为品类内部标签的纵向扩展和跨品类的迁移扩展。
品类内部标签的纵向扩展:在原始标签的基础上对标签的取值范围和枚举值进行扩展,比如上图中租房的地域可以扩大其范围;价格上可以进行上下调整。具体调整的参数需要根据实验或者业务的经验来确定。
跨品类的迁移扩展:在相关品类之间进行跨品类扩展,比如从合租扩展到整租、品牌公寓;找工作的类别从物流扩展到仓库管理、供应链管理。这种兴趣的迁移和扩展也可以应用在多样性的优化上。
经过这些扩展,每个用户的标签可能就会扩展成几十个或者上百个。
第十步:兴趣排序
最后一步是把兴趣按照顺序排序,因为在召回、过滤、排序重排、分配流量上都会根据这些排序类分配优先级。
2. 业务流量分配策略
这个优化主要针对第二个挑战:多业务之间的流量均衡
实际业务需求:
由于58首页信息流是多品类混合推荐的场景,推荐的结果既要满足用户个性化需求,又要满足在整体上各业务的占比与58实际业务流量比例相符合,比如在58平台上,整租房的用户要多于合租房的用户,那么就要求推荐的帖子中整租房的比例要高于合租房的比例。
原始策略:
直接采用精排后的结果:直接采用精排以后得到的序列作为最终展示。由于精排的结果主要是以预估ctr作为评价指标,这会导致热门贴或热门品类始终占有比较大的比例,效果不理想。
采用统一的分配比例:假设58平台在招聘、租房、二手车与本地服务的流量比例为40:30:20:10,那么所有用户的推荐结果都按同样的比例分配。虽然这种策略满足总流量分配需求,但并不满足用户个性化需求。
以上两种策略均与千人千面的目标是不一致。为了解决这个问题,58调整了方案,使其既能满足个性化需求,又能保证流量分配对各业务线相对合理。
按兴趣权重分配流量:
第一步:计算用户的兴趣权重,下图为某用户在招聘、租房、黄页上的比例,分别是60%、20%和20%
第二步:经过召回、过滤、排序等环节后得到帖子的候选集,候选集中有照片、租房、黄页帖子,组成比例分别为65%、25%、10%。
注:这个比例可能跟用户兴趣比例偏差不大甚至一致,但也有可能差异很大。
第三步:优先以兴趣权重分配帖子,当帖子数量不足时再由其他品类补充。用户对黄页的兴趣占比是20%,但候选集中黄页占比只有10%,也就是说即便推出候选集中所有的黄页贴子,也不能满足黄页帖子的占比要求,这种情况就用其他品类的帖子进行补足。
满足个性化需求:每个用户的帖子分配是按照该用户的兴趣权重进行组合的,所可以满足个性化的需要
满足流量分配需求:由于用户的兴趣组成主要来源点击行为,而各品类的流量也是通过点击反映,所以按照用户兴趣进行流量分配在整体上是符合业务线之间的比例的。
这样的策略既满足了个性化需求又满足了流量分配需求,点击效果提升了1.1%,推荐业务帖的流量分配比例与58平台整体流量占比基本一致。
品类之间打散:
通过以上的步骤得到最终进行展示的帖子后,有可能还会出现一种情况——连续多个帖子都属于同一个业务,甚至出现雷同帖子。为了避免这个情况,58对最终进行展示的帖子进行业务打散,比如从排序靠后的其他品类的帖子中抽出一部分插到前面 ( 见上图 ),打散后不仅避免上述问题,还使每个业务有更公平的展示机会,且在视觉上增加了多样性。这个打散策略使点击率提升0.4%左右。
突出实时兴趣:
第一推荐位根据用户的最新实时行为直选,比如上图中用户最新的实时行为是招聘,捕捉到这个信息后在短时间内集中推荐招聘帖。该策略强调了实时兴趣,点击效果提升0.7%。
综合前面介绍的两大块内容:业务分配策略和兴趣策略,点击效果比基准效果提升1.1%。
3. 动态刷新机制
这个优化主要针对第三个挑战:推荐结果的多样性。
算法模型挖掘出来的特征会促使推荐结果越来越聚焦,这就导致用户使用越频繁,多样性就越差。如果想试探新的用户兴趣或者试探新的内容,往往又会牺牲CTR。通过协同过滤、向量化召回等多路召回的办法可以增加多样性,但在用户兴趣不变的情况下召回集合基本不变,此时需要考虑在召回集合内部的排序上进行动态调整。
降权排序:
在排序的时候把曝光次数较多的帖子进行降权和后移,比如上图中帖子2和帖子5曝光次数过多,在后续展示的时候就适当调低其排序位置。经过降权排序后,点击效果比未动态化基准累计提升4.1%。
引入时间衰减:
在降权排序的时引入时间衰减——近期曝光的帖子更快后移,远期曝光的帖子回归到正常序列,这样在点击效果和多样性之间就取得一定平衡。引入时间衰减后,点击效果比未动态化基准累计提升6.5%。
引入服务端的曝光日志:
引入服务端的曝光日志作为补充,这样可以进一步提升多样性,帖子序列的变化也会进一步加快。考虑到曝光真实性的问题,58只选取服务端头部的帖子补充补充道集合中。引入服务端的曝光日志后点击效果比未动态化基准累计提升7.0%。
经过上述三步操作,点击率比基准提高7%,且在多样性上也有明显的改善,取得双赢的结果。
04
心得体会
回顾下实践过程中的一些教训与思考:
理解业务:要做好策略上的优化并最终提升用户体验,最关键的切入点是业务。文章中提到的几个策略都来源对业务的深入理解,虽然看起来比较简单直观,但是整体效果很可观;
策略之间的平衡:不同的优化策略之间可能存在内在的矛盾冲突和效果叠加,这时候需要进行策略之间的平衡;
多目标之间的平衡:不同的场景有不同的目标,整体目标可能是提升CTR,但是某些具体场景可能是提升用户体验,也可能是增加停留时长,多个目标之间的平衡也是优化过程中需要持续解决的问题;
算法和策略之间的关系:从解决问题和取得实际效果的角度来看,策略和算法一样重要,没必要厚此薄彼。从工程实践角度看,两者结合时更要做到高内聚低耦合,减少依赖,加快各自的迭代速度。
05
问题解答
1. 冷启动优化问题
对全新的用户 ( 用户的基础数据完全缺失 ),简单的方案是推全局热门或者地域热门,复杂一点的方案是进行兴趣试探:尝试给用户打一些标签并通过标签推出内容,或者新内容试探:尝试把新的内容推给全新的用户。
对于有一定的数据积累但是不足以提供好的推荐结果的用户,可以对用户进行兴趣迁移或对标签进行扩展,在召回上也可以采用多路召回来解决这类问题。
2. 负反馈的优化问题
这讨论显性负反馈。当用户反馈对帖子不感兴趣的理由后,相当于提供了一个显性的负反馈。典型的方案有这几个:
直接屏蔽:屏蔽帖子——对这个用户不再展示该帖子,屏蔽标签——不再展示类似标签的帖子,比如用户多次提供租房帖子的负反馈,那么就对该用户屏蔽所有有租房类标签的帖子。由于这种方案比较生硬,所以往往达不到好的效果;
建立策略:挖掘用户对哪一类标签不感兴趣,在推荐时对这一类标签的权重进行修正,不会直接屏蔽此类帖子;
建立算法模型:通过算法把负反馈的结果映射成独立的特征,在排序时使用这些特征便会影响最终的结果,从而减少这类物品的推荐。
3. 多样性的优化问题
多样性的目标是减少马太效应,有以下集中方法:
多个通道召回的结果增强用户看到的多样性,包括协同过滤、向量化召回、地域召回等等
全局热门内容的降权
兴趣试探、新内容试探