我们是如何为一个全新的双边市场来迭代的构建机器学习的搜索平台的,我们是如何帮助其成长的。
作者:Mihajlo Grbovic
编译:ronghuaiyang
首发:AI公园公众号
导读
Airbnb体验是由专业房东精心设计和引导的活动,提供不一样的当地场景和文化品味。每一次体验都要经过编辑团队的质量审查,然后才会发布到平台上。
我们在2016年11月推出了Airbnb体验,在全球12个城市提供了500个体验。2017年,我们将业务扩展到60个城市,5000个体验。2018年,我们继续保持快速增长,成功将体验带到1000多个目的地,包括复活节岛、塔斯马尼亚和冰岛等独特的地方。我们以超过20,000次的活跃体验强势结束了这一年。
随着用户体验的增长,搜索和发现以及个性化已经成为市场增长和成功的重要因素。
在这篇博文中,我们描述了我们在市场的不同增长阶段(从小型到中型和大型)使用机器学习进行排序的经验。
我们的搜索排序机器学习模型的前三个阶段
主要的结论是,基于机器学习的搜索排序在每个阶段都有效,因为我们选择的模型和基础设施的复杂度水平与可用的数据量和需要排序的库存大小相匹配。当使用少量数据进行训练时,非常复杂的模型将不能很好地工作,而当大量训练数据可用时,简单的基线并不是最优的。
第一步:构建强大的基线
当Airbnb体验发布时,需要在搜索中进行排名的体验数量很少,我们只是开始收集用户体验交互的数据(展示、点击和预订)。在那个时候,最好的选择是每天随机地对体验重新排序,直到收集一个小数据集来开发阶段1的机器学习模型。
收集训练数据:为了训练我们的第一个排序的机器学习模型,我们收集了用户的搜索日志(即点击),这些用户最终进行了预订。
训练数据收集:最终进行预订的用户的搜索会话点击行为。
标注训练数据:在标注训练数据时,我们主要对两个标签感兴趣:已预订的体验(我们将其视为正标签)和已点击但未预订的体验(我们将其视为负标签)。通过这种方式,我们收集了一个50000个样本的训练数据集。
基于我们将要排序的内容构建信号:在我们的机器学习模型的第一阶段,我们决定只基于体验的特征进行排名。我们总共构建了25个特征,其中包括:
- 体验的持续时间 (比如1小时,2小时,3小时等等)
- 价格以及每小时的价格
- 类别 (比如烹饪,音乐,冲浪等等)
- 浏览 (评分,浏览量)
- 预定数量 (过去7天,过去30天)
- 过去和未来被占用的比例 (比如60%)
- 最大座位数量 (比如,最多可以5个人参加)
- 点击率
训练排序模型:给定训练数据、标签和特征,我们使用GBDT模型。这里,我们把问题当成是二分类使用对数损失函数。
在使用GBDT时,不需要太担心特征的尺度或缺失。然而,需要考虑的一个重要因素是,与线性模型不同,在基于树的模型中使用原始计数作为特征来进行树的遍历决策可能是有问题的,因为这些计数在快速增长的市场中很容易发生快速变化。在这种情况下,最好使用分数比。例如,与其使用最近7天的预订数(例如10个预订),不如使用不同比例的预订,例如相对于浏览的数量(例如每1000个浏览有12个预订)。
排序模型的测试:为了进行离线超参数调优,我们和在生产中的随机重排序进行了比较,我们使用了训练中没有使用的留出的数据。我们选择的指标是AUC和NDCG,这是标准的排序的指标。具体地说,我们根据模型得分(预订的概率)对体验重新进行了排序,并测试了预订的体验在所有用户点击的体验中的排名(越高越好)。
此外,为了了解一个训练过的模型学到了什么,我们为几个最重要的体验特征绘制了部分依赖关系图。这些图显示了如果我们固定了除一个特征(我们正在检查的那个)以外的所有特征的值,那么特定的体验排名分数会发生什么变化。从下面的图中可以看出,模型是通过以下方式来学习利用特征的:
每1k浏览者预订量越多的体验排名越高
经验与较高的平均审查评级将排名更高
体验与较低的价格将排名更高
- 每1k浏览者预订量越多的体验排名越高
- 具有较高的平均浏览评分的体验排名较高
- 价格较低的体验排名较高
由于离线测试通常有太多的假设,例如,在我们的例子中,它被限制为对用户点击的内容重新排列,而不是整个库存,我们进行了一个在线实验,即A/B测试,作为我们的下一步。我们将阶段1的机器学习模型与基于规则的随机预订数量排序进行了比较。结果是非常令人鼓舞的,因为使用了第一阶段的ML排名模型。我们能够提高预订量+13%。
实现细节:在这个阶段,我们的机器学习模型被限制为只使用了体验的特征,因此,体验的排名对所有用户都是一样的。此外,所有的查询参数(客人数量、日期、位置等)仅作为检索的过滤器(例如,为2位客人获取下周可用的巴黎的体验),而体验的排名并不根据这些输入而改变。
给定了这样一个简单的设置,整个排名的pipeline,包括训练和评分,都是离线实现的,每天在Airflow中运行。输出只是对所有体验的完整排序,也就是说有一个排序表,该列表被上传到生产机器上,每次进行搜索时都使用它来对满足搜索条件的体验子集进行排序。
第二步:个性化
搜索排名开发的下一步是向机器学习排序模型添加“个性化”功能。从一开始,我们就知道个性化将在体验排序中扮演重要角色,因为库存和客户兴趣的多样性。
不像我们的家庭生意,在同一个城市两个价格相近的私人房间是非常相似的,两个随机选择的体验可能是非常不同的,例如烹饪课和冲浪课。与此同时,客人可能对他们想要在旅途中做什么有不同的兴趣和想法,我们的目标是快速捕捉这种兴趣,并在搜索结果中提供更高准确率内容。
我们介绍了两种不同类型的个性化,主要是通过对收集到的用户数据进行特征工程。
1. 基于预定的Airbnb房子的个性化
大部分的体验预订来自已经在Airbnb上预订了房子的客人。因此,我们有相当多的信息可以用来建立个性化的特征:
- 预定的房子的位置
- 行程日期
- 行程长度
- 客人的数量
- 行程的价格 (低于市场/高于市场)
- 行程的类型:家庭,商务
- 首次旅行或者回程
- 国内/国际旅行
- 停留天数
为了举例说明可以用来指导排序的特征,我们展示了两个重要的特征:
- 预订的房子和体验之间的距离。了解预定的房子的位置(经纬度)和体验的地点,我们可以计算他们的距离(以英里为单位)。数据显示,用户喜欢便捷,也就是说,Airbnb的预订体验中,有很大一部分是在Airbnb的房子附近预订的。
- 预订行程可提供的体验。考虑到入住和退房的日期,我们知道客人希望预订哪一天的体验,并可以在这些日期中将体验标记为“可用”或“不可用”。
在训练新的机器学习排名模型时,使用了这两个特征(以及其他特征)。下面我们将展示它们的部分依赖关系图。
上面的图证实了这两个特征的行为匹配了我们对模型的学习的直观预期,即体验更接近预定的房排名会更高(有更高的分数),以及体验在旅行日期内可用排名会更高(这是非常方便的,因为即使搜索的时候没有指定日期,我们也可以利用旅行的日期)。
2. 基于用户点击的个性化
考虑到用户的短期搜索历史,我们可以推断出有用的信息,可以帮助我们个性化未来的搜索:
- 推断用户对某些类别的兴趣:例如,如果用户主要点击的是音乐类的体验,我们可以推断用户对音乐感兴趣
- 推断用户的可用时间:例如,如果用户主要点击晚间的体验,我们可以推断用户在一天的那个时间是可用的
当它们被发布到平台上时,每个体验都被手动标记为一个类别(如远足、滑雪、骑马等)。这种结构化的数据使我们能够区分不同类型的体验。它还使我们能够通过用户在不同类别上的点击来聚类用户,并创建每个类别的用户兴趣属性。
为此,我们计算了来自用户点击的用户点击的类别两个特征:
类别强度:对用户对于特定类别的体验的点击进行加权求和:
这里是对过去15天(d\_0到d\_now)进行求和, _A_是某一类别在d天的操作数(在本例中为单击)。
类别距离现在的天数值:自用户上次单击该类别中的某个体验以来的天数。请注意,用户可能单击了许多具有不同强度和距离现在的天数的不同类别,但是当为需要排序的特定体验计算特征时,我们使用该体验类别的强度和距离现在的天数。
为了说明我们的模型从这两个特征中学到了什么,我们在下面展示了部分依赖关系图。正如在左侧所观察到的,在用户拥有高强度的类别中的体验将排名更高。同时,拥有最近的特征(在右侧)可以让模型随着时间的流逝而忘记历史,用户上次点击很久以前的类别中的体验的排名偏低。
我们为几个不同的用户操作构建了相同类型的特征(强度和最近时间),包括愿望列表和预订某个类别。
一天内的时间个性化:不同的体验在一天的不同时间举行(如清晨、傍晚等)。与跟踪不同类别的点击类似,我们还可以跟踪一天中不同时间的点击,并计算用户的每日时间和体验的每日时间之间的时间符合百分比,描述如下:
正如所观察到的那样,该模型学会了以一种方式来使用这个特征,即将用户在一天中所拥有的体验按照用户的喜好进行排序。
训练排序模型:为了训练具有个性化特征的模型,我们首先生成包含这些特征的训练数据,这些训练数据是基于搜索日志重构过去的。到那时,我们已经有了一个更大的库存(4000个体验),能够收集更多的训练数据(250K标记的样本),接近50个排序特征。
在创建个性化特征时,不能“标签泄露”是“非常重要的”,即公开用于创建标签的事件之后发生的一些信息。因此,我们只使用预订之前发生的用户单击。此外,为了进一步减少泄漏,在创建训练数据时,我们只在用户与多个体验和类别交互时计算个性化特征(以避免用户仅单击了一个体验/类别,如冲浪,并最终预订该类别)。
另一个需要考虑的重要方面是,我们的搜索流量包含登录用户和未登录用户的搜索。考虑到这一点,我们发现训练两个模型更合适,一个为已登录用户提供个性化特征,另一个不提供个性化特征,将服务于未登录流量。主要原因是使用个性化特性训练的“登录”模型过于依赖这些特征的存在,因此不适合在未登录流量上使用。
测试排序模型:我们进行了A/B测试,将新设置的两个具有个性化特征的模型与第一阶段的模型进行比较。结果显示,个性化很重要,因为与第一阶段的模式相比,我们能够提高7.9%的预订量。
实现细节:为了在生产中实现阶段2模型的服务,我们选择了一个简单的解决方案,它只需要最少的时间来实现。我们创建了一个以用户id为键值的查找表,其中包含该用户所有体验的个性化排序,并使用键0对注销的用户进行排序。
这需要每天在Airflow中离线计算所有这些排序,以生成列表。由于预先计算所有用户的个性化排序的成本很高(_O_(_NM_),其中_N_是用户数量,_M_是体验数量),我们将_N_限制为100万最活跃的用户。此时的个性化特征仅按天计算,这意味着我们最多会有一天的延迟(这也是一个因素,如果在基础设施方面进行更多的投资,可以极大地改进)。
阶段2的实现是一个临时的解决方案,用于验证个性化的收益,然后我们在阶段3中投入更多的资源来构建一个在线打分基础设施,这是需要的,因为_N_和_M_预计将增长更多。
第3步:进行在线打分
之后我们展示了机器学习排序模型迭代之后的显著的收益,随着体验数量和训练数据大量的增长,训练一个更加复杂的模型成为可能。我们准备投入更多工程资源构建一个在线评分基础设施,目标是得到更多的预订收益。
使用在线评分也解锁了一套全新的特征,“查询特征”可以使用了。
这意味着我们可以使用输入的位置、客人数量和日期来设计更多的特征。
例如,我们可以使用输入的“位置”,例如城市、社区或景点,来计算体验和输入位置之间的距离。这个特征帮助我们将那些接近输入位置的体验排名提高。
此外,我们可以使用输入的客人数量(单身、夫妻、大型团体)来计算它与需要排名的平均预订体验的客人数量之间的关系。这一特征帮助我们将更适合的体验排在更高的位置。
在在线设置中,我们还可以利用用户的“浏览器语言设置”动态地进行语言个性化。一些体验被翻译成多种语言提供出来。如果浏览器设置语言翻译可用,则显示该语言翻译。使用在线的排序,我们可以更进一步,通过设计一个特征来决定是否在浏览器语言中提供体验,从而对语言匹配的体验进行更高的排名。在下面的图片中,我们展示了一个阶段3的机器学习模型的例子,当浏览器语言是俄语时,用俄语提供的体验排名更高。
最后,在在线设置中,我们还知道用户搜索的国家。我们可以根据来自这些国家的用户喜欢的类别,使用国家信息来个性化体验排名。例如,历史数据告诉我们,当访问巴黎时,日本游客更喜欢课程和工作室(如香水制作),美国游客更喜欢食物和饮料体验,而法国游客更喜欢历史和志愿者。我们使用这些信息在源-目的层次上设计了几个个性化特征。
训练排序模型:为了训练具有查询特征的模型,我们首先将它们添加到我们的历史训练数据中。当时的库存是16000个体验,我们有超过200万个带标签的例子用于训练,总共有90个排序特征。如前所述,我们训练了两个GBDT模型:
- 登录用户模型,使用体验特征,查询特征,和用户(个性化)特征
- 针对非登录流量的模型,使用体验和查询特征,使用登录用户的数据(点击和预订)进行训练,但不考虑个性化特征
拥有在线评分基础设施的好处是,我们可以使用登录模型实现比以前多得多的用法,因为不需要像我们在阶段2中所做的那样预先计算个性化排名。只要某个用户id有个性化信号可用,我们就使用登录模型,否则我们就回到使用未登录模型。
测试排序模型:我们进行了A/B测试来比较阶段3的模型和阶段2的模型。我们的预订量又一次增长了5.1%。
实现细节:为了实时的对成千上万的列表在线评分,我们在我们的搜索服务环境中建立了自己的机器学习推理服务。基础设施主要有三个部分:1)实时获取来自不同地方的模型输入,2)模型部署到生产环境,3)模型评分。
该模型需要三种类型的信号来进行评分:体验特征、查询特征、和用户特征。不同的信号根据其大小、更新频率等进行不同的存储。具体来说,由于它们的量非常大(数以亿计的用户),用户特征存储在在线的key-value存储中,搜索服务器可以在用户进行搜索时查找它们。另一方面,“体验特征”并不大(几万个体验),因此可以存储在搜索服务器的内存中,并直接从那里读取。最后,根本不需要存储查询特征,它们只是在从前端进入时被读取。
体验和用户特征均在Airflow特征生成作业完成后每日更新。我们正致力于将一些特征转换到在线,方法是使用一个key-value存储,该存储具有读写功能,允许我们在更多数据到来时立即更新特征(例如,新体验的审查、新用户的点击等)。
在模型部署过程中,我们将GBDT模型文件(最初是JSON格式)转换为内部的Java GBDT结构,并在搜索服务应用程序启动时将其加载。
在评分阶段,我们首先从它们各自的位置获取所有的特征(用户、体验和查询特征),并将它们拼接到一个向量中,作为模型的输入。接下来,根据用户特征是否为空,区别是登录模型还是未登录模型。最后,我们返回所有体验的模型分数,并按分数的降序排列它们。
第4步:处理业务规则
到目前为止,我们排序模型的目标是增加预订量。然而,像Airbnb这样的市场可能还有其他一些次要目标,我们称之为“业务规则”,我们可以通过机器学习来帮助实现这些目标。
其中一个重要的业务规则是提高质量。从一开始,我们就相信,如果客人有一个非常好的体验,他们会回来,并在不久的将来再次预订体验。基于这个原因,我们开始收集用户的反馈,1)星级评分,从1到5,2)关于体验是否“独特、比预期更好、吸引人等”的额外结构化的多重反馈。
随着越来越多的数据支持我们的重新预订假设,趋势变得更加明显。因为它可以观察到在下图左边,客人有一个很好的体验(留下一个五星级评级),要比不太好的体验,在未来的90天内,重新预定量高了1.5倍。
这促使我们试验我们的目标函数,我们改变了二分类(+1=预订,-1=点击&未预订),在不同质量等级的训练数据中引入权重(例如,对于非常高质量的预订权重最高,对于非常低质量的预订权重最低)。质量等级由我们的质量团队通过数据分析定义。例如:
- 非常高质量的体验需要>50评论,>4.95评论评级和>55%的客人说,体验是“独特的”,“比预期的更好”
- 非常低质量的体验需要>10评论,<4.7评论评级。
在测试以这种方式训练的模型时,A/B测试结果(上图右侧)表明,我们可以利用机器学习排序来获得更多的高质量的预订,而获得更少的低质量的预订,同时保持总体预订不变。
以同样的方式,我们成功地解决了其他几个次要目标:
- 尽早发现和提升潜在的新点击 利用冷启动信号并在排序中提升它们,这样有了+14%的新点击的预定提升,并且总体预定保持不变。
- 在前8个结果中增强多样性,这样我们可以展示不同的类别,这对低意图流量尤其重要(这导致**+2.3%的总体预订收益**)。
- 优化没有位置信息的搜索的可点击性 对于预定意图低的用户登录我们的网页的时候,在搜索的时候没有指定特定的位置,我们认为应该使用不同的目标。我们的第一次尝试是根据我们的排序模型得分从所有地点中选择前18名,然后根据点击率重新排列,这样相比没有根据CTR重新排序有**+2.2%的总体预订收益**。
监控和解释排序
对于任何双边市场来说,能够解释某些商品的排名是非常重要的。在我们的这种情况下,它是有价值的,因为我们可以:
- 就什么因素导致排名上升,什么因素导致排名下降,向房子的主人提供具体反馈。
- 跟踪排序算法执行的总体趋势,以确保它是我们在市场上想要的行为。
为了实现这个功能,我们使用了Apache Superset和Airflow来创建两个仪表板:
- 一个仪表板用来跟踪在市场中随着时间的推移,具体的体验的排名的变化,以及机器学习模型中变量的变化。
- 一个仪表板显示不同体验群组的整体排名趋势(例如,市场中5星体验的排名)。
为了说明为什么这些仪表板是有用的,我们在下面的图中给出了几个例子。
在下面的图中,我们展示了一个体验的例子,该体验的排名(左面板)从第30名提高到第1名。为了解释原因,我们可以查看跟踪该体验的各种统计数据的图(右面板),这些图要么直接用作机器学习模型中的特征,要么用于派生特征。
举例说明为什么特定体验的排名会随着时间的推移而提高
可以清楚地看到,排名的提高是因为评论的数量从0增加到了60,同时保持了5.0的评论等级,>60%的用户表示体验比预期的要好。此外,主人降低了价格,这也可能导致排名的提高。
在下一幅图中,我们展示了一个体验的例子,该体验的排名从第4名下降到第94名。再一次,排序模型使用的输入信号可以说明问题。
这个例子解释了为什么特定体验的排名会随着时间的推移而下降
体验开始收到差评(平均评级从4.87降至4.82),主人吧价格提高了20美元,整体预订数量下降。此外,在那个市场上,人们在(清晨)进行体验的时间越来越少(轻微的季节性影响)。所有这些因素综合起来导致排名下降。
对于经常与主人接触的市场经理来说,仪表板尤其有用。此外,为了能够跟踪我们正在执行的排序行为,研究特定群组的体验在其市场中的排序是很有用的。在下面的图中,我们显示了仪表板的快照,我们可以跟踪不同维度的平均排名(越低越好)。
例如,左图显示使用>50评论的体验要比使用10-30评论的体验好得多。看看另外两个图表,我们可以看到,平均来说,>4.9的用户体验排名最好(比那些平均评分较低的用户体验要好得多),而>55%的用户表示他们的体验是独特的体验,这比非独特体验要好得多。
这种类型的仪表板对于做出业务决策和修改排名算法以强制执行更好的行为非常有用。例如,根据显示不同价格区间组的排名趋势的图(如下图所示),我们注意到非常低的价格体验在排名上有太大的优势。我们决定通过取消价格作为排名模型使用的信号之一来减少这种优势。
取消价格并对模型进行再训练的结果是,排名上的差异减小了(7月1日之后),而没有影响总体预订。这说明了报告的有用性,以及如何使用机器学习来操纵排名,以实现期望的排序行为。
正在做的事情和未来的工作
在我们正在进行的和未来的工作中,我们将反复进行
- 训练数据的构造(记录评分时的特征值,而不是根据当天的最佳猜测重建它们)
- 损失函数(例如,通过使用pairwise损失,我们将预订的体验与排名更高但未预订的体验进行比较,这样的设置更适合进行排序)
- 训练标签(例如,使用具体的值代替二进制标签,即为不同的用户行为分配不同的值,如:0代表曝光,0.1代表点击,0.2代表点击选定的日期和时间,1.0代表预订,1.2代表高质量预订)
- 增加更多的实时信号(例如能够根据实时用户行为进行个性化设置,例如10分钟前而不是1天前的点击)
- 明确询问用户他们希望在旅途中进行的活动类型(这样我们可以根据声明的兴趣和推断的兴趣进行个性化设置)
- 处理我们在训练中使用的数据中存在的位置偏差。
- 优化额外的次要目标,比如帮助那些比别人更少接待客人的主人(比如1-2个月),以及那些出去度假又回来的主人。
- 测试不同的模型 不限于GBDT
- 通过排序模型的泄露预测找到在特定市场中表现更好的供应。
- 探索/利用框架
- 测试human-in-the-loop的方法(例如员工选择)
到目前为止的业务影响总结
最后,我们总结一下我们的团队迄今为止通过博客文章中讨论的实验所产生的对预订的影响。
最重要的是:“不要等到你有了大数据,你可以用小数据做很多事情来帮助你的业务增长。”
—END—
推荐阅读
关注图像处理,自然语言处理,机器学习等人工智能领域,请点击关注AI公园专栏。
欢迎关注微信公众号