Real-time Personalization using Embeddings for Search Ranking at Airbnb
前言
这篇论文是KDD2018的best paper,来自Airbnb在搜索排序中利用Embedding进行实时个性化推荐的实践应用,和之前的Embedding一样均是以word2vec为基础技术(w2v大法好),但是这次Airbnb在实践中根据自己的业务场景对于序列的定义、word2vec的计算进行了优化从而更加适合自身的场景特点。
闲话不多聊了,来看论文吧。
Abstract
上来先交代整体的背景,作者提到在搜索排序和推荐领域没有一个通用可以解决所有问题的算法,每个场景都应该根据自己的场景进行优化,而在Airbnb这样一个短时租赁的平台与许多平台面临的问题也不一样,因为Airbnb其实有两类用户,一类是host,即房主,另一类是guest也就是我们普通用户。一方面,搜索排序以及推荐需要满足用户自身的兴趣需求,另一方面也要满足房主的需求(房主可能拒绝出租,原因包括入住人太多,用户评分过低等)。
Airbnb根据他们的业务场景,设计了一套专门适合于他们业务场景的Embedding model,通过不同的Embedding来capture用户的长短时偏好以及满足双方需求。
Airbnb基于这样的Embedding模型驱动了整体99%的转化,可以说已经全量地上到了业务场景之中,并且其相比于之前的提升幅度也较大,在经过离线预测、线上AB后逐渐全量为业务服务,相比于之前的模型CTR提升在20%。
Airbnb的主要场景是两个,搜索排序即将搜索检索匹配的结果进行排序后返回,另外一个是猜你喜欢,即推荐与当前click过的list中更为近似的房源(近似通过余弦距离来度量),如下两个图:
- 这里额外提一句,Airbnb这个界面做的真的非常让人感觉很舒服啊!
引言
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190619232715555.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMTk0MzE=,size_16,color_FFFFFF,t_70)
第一段再次提到了Airbnb的场景下不仅要满足guest也要满足host的需求
Airbnb在搜索下的场景思考是这样的
- 用户在一次search session过程中可能会点击多个房源,与多个host联系后才有可能产生booking,那么在这样的一个search session中就可以形成一个用户行为序列,点击的房源id、联系的房东id等,在这样的背景下可以为用户推荐与这些房源相似的房源。
- 用户的负向行为如跳过那些高点击的房源,那么下次就会为用户降低与这些房源相似的房源的排序位置。
为了完成上述功能,核心的内容就是如何评估房源之间的相似度?Embedding是一个很好的方案,Embedding将房源ID嵌入到低纬的向量空间,利用向量空间内的余弦距离作为房源之间相似度的度量。
- Airbnb利用用户的search session中的数据形成用户行为序列来学习房源的Embedding表示从而加入到Searching Ranking Model以及列表推荐,再次强调了这两个场景驱动了Airbnb 99%的转化量,剩余1%的转化可能来自于用户过去预定过或者好友推荐的房源直接进行了预定。
- 对于实时的个性化推荐,Airbnb采用的是用户实时的click信息作为用户的短时偏好,这种做法在国内许多公司也早就已经应用上了,拿我最爱的Bilibili来说每一刷都会更新出与最近点击相关的视频列表,上下文很重要啊,一刷停不下来。
- 另外Airbnb还设计了一套用于capture用户长时偏好的Embedding,该Embedding基于用户历史booking信息来训练,但是booking信息与许多推荐场景一样,大量长尾用户的booking list只有一两个,而且booking时间间隔非常久,并且booking行为非常稀疏,也就是Airbnb面临的问题是时间间隔久、行为稀疏、行为序列短的问题,后面会介绍Airbnb针对这种场景的解决方案。
contributions
论文简单列举了一下本文相比于传统的文章的贡献点,如下:
- Real-time Personalization
- Adapting Training for Congregated Search
Airbnb中的搜索特点是集中搜索若干地区,而word2vec 中negative sampling是从语料库中进行采样,Airbnb针对negative sampling进行了优化从而更加适应场景。
- Leveraging Conversions as Global Context
关注最终成功转化的session,并将booking作为global context加入到word2vec的训练之中
- User Type Embeddings
传统的用户Embedding都是为每个用户id进行表达,而这种做法在数据稀疏、数据量不足时效果很差,并且针对每个用户id进行Embedding学习在线上使用时需要占用大量的内存(redis空间),因此采用规则将用户映射到更粗粒度的子空间对子空间进行Embedding
- Rejections as Explicit Negatives
为了减少推荐的列表被host拒绝的可能,在进行用户type以及listing(房源)type Embedding时将Rejections加入到负样本之中
小结
- 对于用户的短时偏好,Airbnb使用了800 million个click sessions来生成高质量的listing embedding,并且通过离线和在线进行了测试并落地,将Embedding加入到模型中后效果提升明显。
- 对于用户的长时偏好,Airbnb使用50 million用户的booking历史列表在同一个向量空间内训练user type以及listing type的Embedding,由于在同一空间进行训练,user type和listing type便可以计算余弦距离并将其作为特征加入到模型之间,同样也经过了离线以及在线的测试并落地。
METHODOLOGY
接下来到了本文的重点了,即Airbnb是如何生成两类Embedding的。
listing embedding
首先来看Airbnb对listing是如何进行embedding的
- 由于基于word2vec进行训练,那么最重要的第一步就是如何构建训练的序列,Airbnb的做法是这样的,用户每次使用Airbnb都会产生一个session来标识会话,在session有效期间内用户会产生多次的点击记录,那么将这些点击过的listing按时间构建为一个序列,这里有个处理的方式,就是人为设定当前后点击的listing时间间隔超过半小时则认为是一个新的序列。
接下来论文温习了一下skip-gram,虽然上一篇有介绍,这里还是看一下吧,下图是loss function
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620004431534.png)
其中m为窗口大小,S为序列集合,li代表当前中心词,其中 P ( l i + j ∣ l i ) P(l_{i+j}|l_i) P(li+j∣li)通过sigmoid计算获得(论文中在不用Negative Sampling写的使用softamx,在使用NS后换用了sigmoid,因为listing数量太大了,计算softmax开销过大)。
接下来,通过负采样来对word2vec进行训练,公式中 D p D_p Dp代表正样本, D n D_n Dn代表负样本,公式如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620005533898.png)
其中l代表中心词,c代表窗口,负采样是随机从全体样本中进行抽取的,注意到第二项中sigmoid是正号,这是因为负样本的发生概率为 1 − δ ( i ) 1-\delta(i) 1−δ(i), v l v_l vl是中心词的词向量, v ′ c v^{'}c v′c代表窗口词c对应的辅助向量。
- 这里有一个疑问,因为word2vec中是生成一个 θ i \theta^i θi来作为第i的word的辅助向量从而辅助训练的,该向量和word的Embedding不构成直接关系,但是Airbnb这篇文章中强调待训练的参数 θ \theta θ是 v c v_c vc和 v l v_l vl,并且提到了where v l v_l vl and v′l are the input and output vector representations of listing l,这段不知道该如何理解,难道是直接将Vc窗口词的Embedding作为sigmoid的参数与中心词Vl进行乘积估计结果,这样SGD过程中也就可以同时对中心词与窗口词同时进行更新了,有懂的欢迎留言交流。
通常情况下,我们会直接针对上面的objective进行训练了,但是Airbnb对objective做了一定修改。
Booked Listing as Global Context
Airbnb对objective进行的修改就是将click session list划分为两类,一种是最终产生了booking即成功转化的,称之为booked sessions,另一类就是没有产生转化的,叫做exploratory sessions。
Airbnb认为booked session中,booking的listing应该在训练过程中始终提供预测并提供损失,也就是说在包含booking listing的click行为序列中,booking的listing始终应该在窗口词中参与训练,即无论中心词如何滑动,窗口大小如何选择,booked listing始终在窗口内。如下图:
对应的objective修改为:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019062001074090.png)
主要的变动是将booked listing加入到了每次的损失函数计算中,对应着上图中的最后一项,也就说在计算objective时时刻都关注着booked的listing,说明bookedlisting是一个非常正的正样本。
- 这里,文章再次提到了, v l b v_{lb} vlb is the embedding of the booked listing l b l_b lb,这是不是印证了前面说的Airbnb实现自己的word2vec没有使用辅助向量而是直接使用Embedding,这种做法的好处是节省了计算开销,但是会不会影响效果呢?
这里还是再提一句,论文中提到了At each step the embedding of the central listing vl is being updated such that it predicts the embeddings of the context listings vc from Dp and the booked listing vlb,即在Airbnb的word2vec中使用的完全是当前词预测前后词,这种做法之前会导致一条样本SGD只更新输入向量,但是Airbnb进行了修改后将Embedding作为辅助向量的替换后,一次SGD可以同时更新中心词以及窗口词,计算的效率会获得不小的提高,但是还是那个问题,效果有没有影响呢?还是说当前已经很多地采用这种方式了呢?
Adapting Training for Congregated Search
回到之前提到的,Airbnb的搜索场景和web搜索不同,在Airbnb下的搜索结果大量以地区进行集聚,因为大家短租都是瞄准某一片区域,但是word2vec的negative sampling是对所有的vocabulary进行采样,这会导致负采样的样本集中的中心词与context大概率不来自同一个market,文中说法是Dn contains mostly listings that are not from the same markets as listings in Dp,这种不平衡问题会导致其学习market similarity时效果不佳,那么如何解决这个问题呢?
- Airbnb的做法继续是从objective下手,人为地针对中心listing所处的market进行负采样,采样集为 D m n D_{m_n} Dmn,修改后的objective如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620013806113.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMTk0MzE=,size_16,color_FFFFFF,t_70)
新的objective中加入了针对market负采样的信息,从而平衡从整个vocabulary中负采样引发的不平衡问题。
Cold start listing embeddings
冷启动是影响推荐系统性能的一大杀手,那么Airbnb是如何解决listing的冷启动的呢?
- Airbnb要求host上传新的listing时必须要填充足够的信息,例如是合住、单间、价位等信息,Airbnb选择的是listing type以及price bucket以及地理位置信息,即给定新listing,在已有Embedding的listing中选择物理位置最近的若干个具有相同listing type和price bucket的listing的平均embedding作为当前新listing的embedding,Airbnb选择的是三个。
Examining Listing Embeddings.
Airbnb将listing嵌入到32维的空间表示,在800million条cilck session上利用上面的objective进行优化计算。
- 在Embedding完成后,首先利用kmeans对Embedding进行聚类并可视化来观察Embedding能否将包含位置信息,选择了加州的100个簇,可视化结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620014558542.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMTk0MzE=,size_16,color_FFFFFF,t_70)
如上图所示,Embedding信息很好地表征了地理位置的相近性。
2. 第二步,Airbnb比较了不同listing type的listing之间相似度以及不同price bucket之间的相似度信息,如下图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620014830301.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMTk0MzE=,size_16,color_FFFFFF,t_70)
可以发现,相同类别的相似度更高,对于价格因素,差距越大相似度也越低,说明Embedding也很好地表征了价格以及type信息。
- 论文中提到了价格因素、type等其实不需要表征,这些有结构化的数据,但是对于一些非结构化的特征例如房间装修风格等,通过传统的方式无法有效地进行表征,但是Embedding也具备了表征这种信息的能力(这些信息来源于用户喜好的类型比较统一,形成的click session较好),下面来看一下通过余弦相似度计算出的相似listing:
如上图,可以发现通过余弦距离进行相似度度量完美地表达了相似性。
为了更加便利地查看Embedding计算出的相似列表,Airbnb甚至还做了个工具来快速地可视化,如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190620015519623.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMTk0MzE=,size_16,color_FFFFFF,t_70)
通过该工具可以看到,输入listing的id就可以输出与其最近邻的listing列表,还能输出这500个最近邻listing的score分布信息等,非常方便用于比较Embedding的结果。
小结
这次上篇先介绍Airbnb基于click session对listing进行Embedding并加入到搜索排序以及实时个性化排序的部分内容,Airbnb结合自己id业务场景以及case分析一步步地优化objective从而提升Embedding的能力令人赞叹,通过理解业务、分析bad case并想办法解决问题也是在工业落地过程中非常重要的能力。墙裂建议大家都去看一下这篇文章,作者写的通俗易懂,看起来非常顺畅,并且有许多工程处理经验都很值得学习,值得细细品味的好文。