在Airbnb中用户通过搜索界面点击了一个房源之后,有两种方式继续浏览其他房源:
论文的写作思路就是从下面三个方面进行推进的
这篇博客也是按照这个思路来记录。
首先回答第一个问题,需要构造哪些embedding。论文首先针对了房源详情页下面的“相似房源”这个应用场景提出了listing embedding,进一步为了更好的实现搜索页上的排序算法,又提出了user type & listing type embedding。所以可以概括为本文提出了两种embedding:
listing embedding + user-type & listing-type embedding
step1. 使用skip-gram构造最初的目标函数
l i l_i li表示一个listing
step2. 采用negative sampling构造采样之后的目标函数
v l v_l vl表示位于当前作用center的这个listing的embedding向量
v c v_c vc表示center后面的这个输入listing的embedding向量
( l , c ) (l,c) (l,c)表示当前的输入向量
( l , c ) ∈ D p (l,c)\in D_p (l,c)∈Dp表示当前的输入向量属于正样本
( l , c ) ∈ D n (l,c)\in D_n (l,c)∈Dn表示当前的输入向量属于负样本
由于前面两个基础目标函数,属于日常比较常用的,而且后面开始才是作者针对airbnb的实际场景提出的比较有意义的地方,所以前面两个公式这里就直接略过了,不做解释。
step3. 根据预定行为构造有导向于“booking”的目标函数
作者指出,用户一直浏览的最终的目的是为了产生“booking”这样下订单的行为,因此应当将“booking”了的listing当作这一段时间(我理解的就是上一个有booking行为到这个booking行为之内的所有session)的最后一个item。也就是将这个booking listing当作一个全局“global”的值。在这样的基础上,构造了下面的目标函数
v l b v_{l_b} vlb表示booking listing的embedding向量
注意蓝色框的地方就是添加进来的booking listing。
由于这个booking listing是作为“正例”样本,所以纳入到目标函数中的分母的指数是取“负”。
同时,这个booking listing纳入目标函数的前面并没有加 ∑ \sum ∑这个求和符号,就是体现了“global”的效果,也就是在这个session里面,都需要考虑到这个booking listing作为正例。
这附图应该更容易理解到这个“global”的形式:
step4.根据房源地区进一步优化得到最终的目标函数
由于listing embedding是基于当前已经点击了一个房源,因此,此时用户是已经有一个地区倾向了;同时,listing embedding更多的就是为了解决airbnb的“相似房源”这个场景下的候选listing的排序,因此作者提出了在目标函数中在加入基于地区的采样。
v m n v_{m_n} vmn表示当前地区的listing的embedding向量
( l , m n ) ∈ D m n (l,m_n)\in D_{m_n} (l,mn)∈Dmn表示当前的输入向量属于目标地区中负样本
这里将与点击listing处于同一个地区的其他listing当作负样本,纳入目标函数中。所以纳入到目标函数中的分母的指数是取“正”。
由于新的房源没有历史被点击的信息,所以这里会通过找到三个地理位置最接近、房源类别和价格区间相同的“老”房源,通过计算这些“老”房源的embedding的平均值来当作“新”房源的embedding值
作者用了三种方式来验证这样的embedding方式代表一个listing是有效的:
作者根据已有的用户点击数据计算了California的所有listing的listing embedding向量。
然后将这些listing embedding直接进行聚类。
最后根据聚类结果,绘制得到了这幅图。
从图中可以看到,地理位置接近的listing会被聚集在一起。
结论:说明这样计算得到的embedding能够提取地理位置上的信息
2. 分类计算平均余弦相似度
同样的,先根据已有的用户点击数据计算计算所有listing的listing embedding向量;
然后,根据listing本身的房源类型或价格区间进行分类;
最后计算分类之后的,所有listing embedding向量之间的平均余弦相似度,得到下面两个表。
从表中可以看到,每种类型都是对自己这个类型的房源embedding向量有最大的相似性
结论:说明listing embedding里面能够encode到房源的类型和价格区间这两种features
3.k-nearest
作者还计算了每个listing embedding的k近邻,并对比这个listing和k近邻;
为了展示这个结果,作者还做了一个可视化的工具来展示,这里给了一个截图。
可以从图中看到,输入一个listing embedding得到的k-nearst的房子风格都非常相似。
结论:说明embedding能够提取房源的建筑风格
横坐标:处于book行为发生前点击的次数
纵坐标:book的listing在该模型下处所处的位置(值越低说明排序位置越高)
作者将listing ID embedding到32维的向量上进行的离线测评。
整个测评思路:比较不同的“模型”,对booking的房源所排的位置的结果比较。
基于整个点击序列往booking行为之前回溯,取一定次数之内的所有数据。这里作者就是取了booking前的17次点击行为内的listing。在原有的search ranking排序模型上,进行re-ranking,看处于“当前”的这个点击listing下,模型计算出来最后booking的房源的位置。(这里作者并没有仔细说如何进行的re-ranking,我自己猜测的是将search ranking的结果计算listing embedding的余弦相似度,然后根据整个余弦相似度进行排序,完成推荐)
最后从图中可以看到,re-ranking之后,booking listing的位置都往前排了。同时,也能看出来,采用“d32 booking global + market negative”这个方法构建目标函数得到的embedding,最后的位置也是最好的。
listing embedding不能够解决的问题:
解决方案:
BUT
step1. 从user和listing到user_type和listing_type
分别完成user和listing到user_type和listing_type上的映射
具体的映射方式,如下:
For example, for a user from San Francisco with MacBook laptop, English language settings, full profile with user photo, 83.4% average Guest 5 star rating from hosts, who has made 3 bookings in the past, where the average statistics of booked listings were $52.52 Price Per Night, $31.85 Price Per Night Per Guest, 2.33 Capacity, 8.24 Reviews and 76.1% Listing 5 star rating, the resulting user_type is S F _ l g 1 _ d t 1 _ f p 1 _ p p 1 _ n b 1 _ p p n 2 _ p p g 3 _ c 2 _ n r 3 _ l 5 s 3 _ g 5 s 3 SF\_ lg_{1}\_dt_{1}\_fp_{1}\_pp_1\_nb_1\_ppn_2\_ppg3\_c2\_nr3\_l5s_3\_g5s_3 SF_lg1_dt1_fp1_pp1_nb1_ppn2_ppg3_c2_nr3_l5s3_g5s3
这样就实现了将所有的用户和房源都进行了聚合。
作者还强调,用type来表示原有的user和listing,可以解决两个问题:
step2. 获取booking session
只提取预定行为,按时间构造booking session
step3. 构造输入数据
按时间构造形如(user-type, listing-type)的二元组所构成的有序序列,表示该user_type预定了该listing_type。
作者指出,按照这样形式构造输入序列的原因是为了将user-type和listing-type都映射到同一个特征空间中。
step1. 使用negative sampling构造最初的目标函数
同样的,在type embedding的构造过程中,用negative sampling作为最基础的目标函数。
作者计算了用户当前所处的user_type与候选的listing的listing-type embedding之间的余弦相似度
这里给出了一个计算结果,对某一个属于 S F _ l g 1 _ d t 1 _ f p 1 _ p p 1 _ n b 3 _ p p n 5 _ p p g 5 _ c 4 _ n r 3 _ l 5 s 3 _ g 5 s 3 SF\_lg_1\_dt_1\_fp_1\_pp_1\_nb_3\_ppn_5\_ppg_5\_c_4\_nr_3\_l_{5}s_3\_g_{5}s_3 SF_lg1_dt1_fp1_pp1_nb3_ppn5_ppg5_c4_nr3_l5s3_g5s3这类的用户,得到余弦相似度比较高的几个listing type embedding,然后浏览了该用户历史上的订单情况,发现embedding能够概括用户的预定偏好=>该用户预定的房源基本都偏向于空间大,数量多,评论高的房源。
作者将embedding运用在在原有的排序算法上,衍生出embedding features实现了更好的排序效果
原有的排序模型:
现在的排序模型:
前七行特征需要先根据用户行为计算得到一些基础的指标 H c H_c Hc、 H s H_s Hs、 H l c H_lc Hlc、 H w H_w Hw、 H i H_i Hi、 H b H_b Hb
H c H_c Hc:clicked listing_ids 用户过去两周内点击过的listings id
H l c H_lc Hlc:long-clicked listing_ids 过去两周内用户点击过,同时在详情页面上停留时长超过60s的listing id
H s H_s Hs:skipped listing_ids 过去两周内用户直接忽略进而点击了陈列在它后面的listing
H w H_w Hw:wishlisted listing_ids 过去两周内用户加入心愿单的listing
H i H_i Hi:inquired listing_ids 过去两周内用户联系过房东但是没有成为book订单的listing
H b H_b Hb:booked listing_ids 过去两周内用户预定过的listing
从这些基础指标 H ∗ H_* H∗的定义以及计算方式上可以看到,这些指标是会根据用户的行为不断发生改变的,所以作者也强调,embedding features的引入能够实现现有的排序算法实时更新。
关于为什么要提取基础指标 H ∗ H_* H∗,并计算地区embedding,我的理解:因为需要了解到用户近期的一个行为偏好,因此需要提取近期的用户行为。同时,也需要用某种规则将近期的这些行为模式提取出来;又因为listing embedding里面其实是蕴含了地区之间的差异信息的,因此用地区来进行分组,使得组内方差变小,平均之后的embedding更具有代表性,所以才采用了计算每个地区的listing embedding值来代表用户对地区的偏好。
只存在离线测评,作者说在线测评的结果:several months later
原有features+embedding features共有104个,对数据进行拟合之后可以看到这些新生成的embedding features的重要度在104个特征中,重要性排名挺高的。这说明了embedding features对排序算法影响蛮大的。
另一方面,直接计算了新的排序模型在DCU等指标上的值,发现加入了embedding features之后的排序模型,在所有的指标上都有提升。
5.1 booking session的长度
原文中有这样的一段话:
Specifically, we form a set S b S_b Sb consisting of N b N_b Nb booking sessions from N users, where each session s b = ( u t y p e 1 l t y p e 1 , . . . . . . , u t y p e M l t y p e M ) ∈ S b s_b=(u_{type_{1}}l_{type_{1}},......,u_{type_{M}}l_{type_{M}}) \in S_b sb=(utype1ltype1,......,utypeMltypeM)∈Sb is defined as a sequence of booking events, i.e. (user_type, listing_type) tuples ordered in time. Note that each session consists of bookings by same user_id, however for a single user_id their user_types can change over time, similarly to how listing_types for the same listing can change over time as they receive more bookings.
我理解的就是一个session就是一个用户的所有booking行为。当用户不断发生预定行为,他所对应user_type也在不断变化,同时listing也是因为用户们的预定行为一直在改变其listing_type。
对于一个有很多次预定行为的用户,他的session长度肯定大于1,但是对于历史上就只预定过一次的用户,预定长度还是1呀。
5.2 如何进行的训练
作者提出的将user_type和listing_type映射到同一个特征空间中,这个embedding是怎么实现的?
就从作者给出的加入了房东reject的session示意图中看,user_type和listing_type是平行放入了模型中,但是这样存在一个问题就是窗口在进行滑动的过程中,中心item有时候会是user_type有时候又会是listing_type,同时,中心item的前后就会变成不同时期的另一个type,比如说,当前的中心item是 u s e t _ t y p e i uset\_type_{i} uset_typei但是它前面一个item就会变成 l i s t i n g _ t y p e i − 1 listing\_type_{i-1} listing_typei−1后面一个item就是 l i s t i n g _ t y p e i + 1 listing\_type_{i+1} listing_typei+1,我感觉用这样的序列进行训练不是很合理呀。