这篇论文主要就是讲了如何对id类特征进行embedding操作,Airbnb结合word2vec模型预训练了2类embedding特征用来抓捕用户的短期兴趣(listing embedding)和长期兴趣(user-type embedding和listing-type embedding)。
Listing Embedding
listing embedding是直接对用户历史行为进行分析,此时特征粒度是最细的。Airbnb将用户的租房点击信息(只有浏览超过30秒才算点击信息)分为多个session(按照用户30分钟没有点击来划分),此时我们可以将一个session看做是一条完整的句子,接下来需要做的就是对session滑动窗口截取训练样本。由于平台上租房id是很多的,所以Airbnb在训练时使用了word2vec的negtive sampling技巧来降低计算量,此时模型的优化目标是其中,
是滑动窗口中心租房id对应embedding向量,
和
分别是正样本对和负样本对。
上面我们提到session是按照用户30分钟没有点击来划分,此时我们还可以将每个session按照最后一个操作接着分类:1)booked session,最后一个操作是预定;2)exploratory session,最后一个操作还是点击。对于exploratory session,优化目标不变,而对于booked session,则将最后booked的租房id对应的embedding向量作为全局信息,每次滑动窗口时都加上最后的booked id embedding,此时优化目标变成 另外还有一个问题,当我们对租房id表进行负采样时所得到的
中大部分租房id很可能和滑动窗口中心租房id不是同一个market,这样就会导致sub-optimal。因此我们还需要在和滑动窗口中心租房id所在的market中随机选取一些负样本,此时优化目标就变成
对于那些新加入的租房id,Airbnb提出可以利用已经训练好的embedding向量为其赋赋初始值。首先需要房屋主人提供一些相关信息,如位置、价钱、类型等,然后利用这些信息找到3个最相似的房屋id(个人感觉这里可以利用KNN实现),并将其对应embedding向量求平均作为新加入房屋的embedding向量初始值。Listing embedding对应的skip-gram模型如下:

User-type & Listing-type Embedding
前面讲到的listing embedding可以很好的找到相同market中房屋之间的相似性,适合抓住user的短期兴趣。但是对于用户的长期兴趣还需要训练一些其他的特征。比如一个user过去是在洛杉矶租过房,但是现在需要在纽约租房,在这种场景下listing embedding就没法很好的为user进行推荐了。而且有些用户租房次数很少(其对应session可能只有1个)或者有些房屋被租出的次数很少,这些情况下都没法很好的训练embedding向量。换句话说就是id类特征粒度太细了,分给某个embedding向量的样本太少了,这样训练出来的embedding向量必然不是最优解。因此Airbnb提出user-type和listing-type embedding,对极其稀疏的id类特征进行装桶,将粒度变粗,保证每个embedding向量都对应足够的训练样本,此时训练集的每个session就不再是单个用户的交互行为(房屋id),而是(user-type,listing-type)对,并且session中记录的都是booking event,不包括exploratory event。相应的,每次训练时模型中需要更新的参数是user-type embedding和listing-type embedding,这2个embedding向量是处于同一个空间的。此时对于user-type()的优化目标是
对于listing-type(
)的优化目标是
其中,
是用户的最近book历史,
是随机挑选的(user-type,listing-type)对。不过我还是有个疑惑:这里session是怎么按照时间进行划分的?
2019.2.28补充:最近这篇博文,收获颇多。首先需要指明的是,对于user_type embedding和listing_type embedding的训练使用的数据是book session,而不是listing embedding训练中用到的click session。但是使用book session就会带来数据稀疏问题,airbnb的做法是利用一些规则对user_id和list_id进行聚类,将特征相似的user_id或者list_id设置为相同的user_type或者list_type。此时一个book session中就对应了一类user type的租房历史记录,也就是多个用户的book listing,那么此时session中的租房信息怎么排列呢?博主认为还是按照绝对时间排序。同时我们需要注意的是,同一个user_id的可能对应多个user_type,因为聚类的规则中包含时间规则的,所以一个用户在不同时期对应的user_type也可能不同,这就可能导致同一个用户的历史信息被分到不同的session中。我在上文中还提到了“这2种embedding向量是处于同一个空间的”,之前写这句话时并没有深入的理解,看了下博主的解释感觉有所理解了。博主认为是将user_type和list_type看作是一样的item,也就是把session中的元组(user_type, list_type)进行扁平化,再按照word2vec的方式对滑动窗口中心item对应的embedding向量进行学习,不过博主对这点还不是很确定,而评论中另外一位用户也提出不一样的数据划分方式。我暂时也不太清楚哪种方式更准确,或者说时更优,不过那个评论的用户有一点我很赞同——user_type embedding和list_type embedding处在相同空间是因为两者的优化目标中都使用了相同的网络参数。为什么要说明下这2种embedding向量是处于同一个空间呢?因为按照原始的word2vvec的思想是没法训练user_type embedding的,但是这里将两者放在同一个空间中,也就是将两者视为相同的item,所以就可以训练user_type embedding了。
此时还需要考虑房屋主人的出租反馈(确定出租还是拒绝出租)。该特征可以被用来为user-type embedding和listing-type embedding编码。所以此时对于user-type()的优化目标积就变成
而对于listing-type(
)的优化目标就变成
User-type和listing-type embedding对应的skip-gram模型如下:

训练细节:
- 根据30分钟不活动规则对用户点击序列进行划分
- 将训练集中的booked session过采样了5倍
- 按照时间滑窗不断更新训练集数据(从头训练比对原模型接着训练效果要好)
- embedding size=32,session滑动窗口大小=5(中心房屋前面选5个,后面选5个),epoch=10,利用MapReduce进行训练(300个mappers读取数据,1个reducer训练模型)
网友评论