Fork me on GitHub

详解 Airbnb 之深度学习在搜索业务的探索

文章作者:杨镒铭 滴滴出行 高级算法工程师

内容来源:记录广告、推荐等方面的模型积累@知乎专栏

今年KDD上Airbnb发表的关于embedding的论文拿到best paper,技术实力可见一斑。今天要说的这篇要更新一些,是Airbnb将深度学习应用在搜索业务中的经验汇总,链接是[1810.09591] Applying Deep Learning To Airbnb Search。文章干货满满,值得细读一番。

具体涉及的业务是根据用户预订的可能性对列表进行排序,也是Airbnb中的核心业务。在深度模型之前是应用GBDT模型,迭代长期进入瓶颈之后就需要对整个系统做一些本质上的改变。这个也是转向探索深度学习的原因。文章分模型演化、特征工程、系统工程和超参数几个部分依次展开。

一、模型演化

核心业务场景的模型探索一般都会持续迭代很久,中间也会有很多试错和惊喜。如图1所示,模型探索主要分为四个阶段,线上效果不断提升。

图1.不同模型线上收益相对效果对比

  • Simple NN

最终上线的时候结构比较简单的神经网络,隐层大小为32,使用Relu,效果和GBDT相当。神经模型的特征和训练目标和GBDT相同。这个阶段(文章称之为exercise)更多的意义是打通线上神经网络预测的pipeline。

  • LambdaRank NN

将NN和LambdaRank结合起来是第一个突破。LambdaRank是很早之前微软Burges针对排序场景提出来的一种改进,主要思想是根据item对的相对顺序来调整梯度更新时的强度。文章里损失采用pairwise损失,并将损失乘上item对调换顺序带来的指标变化  。我们17年中也曾探索过类似思路,也取得了明显的业务收益,LambdaRank的具体思想可以参考我之前的文章**FM模型在LTR类问题中的应用**。

  • Decision Tree/Factorization Machine NN

如图2所示,模型主要引入了GBDT叶子节点和FM的预测结果,属于业界比较常规的做法。

图2.Decision Tree / Factorization Machine NN

  • Deep NN

这个阶段模型使用更简单的模型,同时将训练数据增加10倍。网络结构的设置是输入层有195个特征(包括将离散特征embedding),之后两层神经网络,大小分别是127和83个结点。ps,用这两个数字有点奇怪。

图3.DNN学习曲线

文章这里提到了两个有意思的事情:一个是训练误差和测试误差随着训练样本量的变化趋势。如图3所示,当训练样本对达到17亿的时候,两者的差异基本可以消除。这点对于模型调研非常有意义,因为可以根据线下收益来估算线上可能的收益。另一个是搜索领域的深度学习模型是否已经像图像领域的深度模型超过人类的能力。这个问题很难回答,问题的关键在于搜索场景很难去定义人类的能力。图像领域拿图像分类来说,分类的标签是客观确定的,而搜索领域,用户兴趣等因素是隐式的,无法通过人工来评判。

  • 失败的模型

这部分介绍了失败的探索,并给了一些具体的反思。

文章用listing id进行embedding,这种做法在比如NLP都有成功经验,但是在文中场景却发生过拟合现象。文中给出的解释是listing特别稀疏,即使最热门的listing一年也最多被约定365次。文章也尝试多任务学习,预测book和long view,希望能将long view的学习对book的学习有一定辅助作用。由于book和long view的量级差别很大,所以对book的损失使用了更高的权重。而且对long view的标签进行了放缩,乘上log(view_duration)。但是线上效果是view增加,但是book保持不变。文中给出的解释是长时间浏览可能是listing高档或者描述太长等原因,跟book关系不大。

二、特征工程

GBDT模型依赖了繁多的特征工程工作,包括计算比值、滑动窗口平均和组合特征等。这些特征由于调研时间已经偏久,无法确定是否还能达到最初效果,以及市场环境变化是否需要更新。而神经网络的一个优点就是可以做特征表示,输入原始数据,特征工程的工作发生在隐层中。只是需要将输入给神经网络的特征保持良好的性质。

  • 特征归一化

如果直接将输入给GBDT的特征喂给神经网络,效果将很差,原因就是神经网络对输入特征很敏感,如果直接输入原始值会导致反向传播时梯度很大。为了避免这种情况,需要将特征限制到一定范围,比如限制到  。跟据特征分布不同采用不同的归一化方法。如果特征服从正太分布,则使用  转换。如果特征服从幂律分布,则使用  转换。

  • 特征分布

将特征归一化能使得特征具有一个平滑的分布。将特征保持平滑分布有下面几个好处:1、通过观察分布跟典型的分布做对比,可以注意到特征在计算时候是否存在问题。2、更容易泛化。如果特征输入给数百维度的特征,特征的组合空间将非常巨大,而训练数据只能覆盖部分组合。输入的平滑分布保证了输出对未见过的数据仍有良好的分布。文中进行了线下的测试,将价格特征分别*2、*3、*4等,然后观察到NDCG的结果稳定不变,这就说明了网络的泛化效果很好。3、检查特征完整性,这里主要是检查部分特征是否缺失或者为空。



三、系统工程

主要包括线下训练和线上预测两部分。

线下流程最初从csv格式中读取,使用feed_dict来传入数据。后来发现GPU利用率只有25%左右,很多时间用于解析csv和使用feed_dict拷贝数据。使用Protobufs和DataSet使得GPU利用率达到90%。这样使得从使用周级数据进行训练扩展到使用月级数据训练。

listing的静态特征比如位置、房间数目等不太经常发生变化,为了减少访问磁盘,只是用listing id,将对应的特征都拼接在embedding后面,但是non-trainable的。

为了满足线上的性能,打造了基于java的线上inference模块。

四、超参数

文章里提到在迭代初期对参数进行了详尽的尝试。

  • Dropout

Dropout虽然在图像等领域是标配,但是在文章并没有尝试出效果,反而在离线指标有少许降低。无独有偶,在我们的排序场景下Dropout也没有任何提升。作者给出的解释是Dropout可看做一种数据增强方法,虽然引入了随机因素,但是仍可以认为是成立的,可以作为训练数据的补充。而文中场景,使用dropout则会导致样本不再成立,从而给模型学习有误导作用。我个人觉得这个解释还是可信服的。另外,文中提出对某些特征手动添加了噪音,线下NDCG指标有1%降低,但是线上并没有明显收益。

  • Initialization

对于网络中的参数使用Xavier初始化,而embedding参数使用  的均匀分布。

  • Learning Rate

虽然优化策略非常多,但是作者发现使用Adam而且是默认参数效果最好。具体使用LazyAdam,这种在训练large embedding的时候速度更快。

  • Batch Size

使用不同的batch size对训练速度影响很大,但是对模型效果的影响不太好确定。文中提到使用LazyAdam的情况下,batch size大小200的话效果最好。

五、特征重要性

特征重要性可以帮助我们更好的认识不同特征的作用,对后期模型迭代也有意义。

  • Ablation Test

每次去除一个特征,重新训练模型,然后观察效果的diff。但是这种方法也有问题,因为删去某个特征之后,由于特征集合存在冗余,模型能能力进行弥补,即使效果降低很少也并不意味着特征不重要。

  • Permutation Test

这种方法最初是在随机森林中用来衡量特征重要性。针对某个特征,将测试集合中的取值随机打散,然后观察模型效果下降。显然,如果特征越重要,模型效果下降越明显。但是这种做法得到的结果并不能是很合理。因为特征之间往往并不独立,对特征取值进行打散可能产生的样本并不符合实际,这一个不切实际的样本空间上学习到的结果因此也并不可信。

  • TopBot Analysis

这个是作者自己提出来的一种方法。使用模型对测试集进行预测,然后计算query排在top的listing的特征分布,并和排在bottom的listing的特征分布进行对比。如图4所示,排在top的listing的价格偏低,说明模型对价格特征的敏感性。而排在top和bottom的listing的浏览分布特征基本一致,说明模型并未像预想那么利用浏览分布特征,也就是说浏览分布特征并没有区分度。

图4.测试集中排在top和bottom的listing的特征分布情况

六、回顾

从GBDT到深度学习并不是换个模型那么简单,需要重新思考整个系统的设计。在GBDT阶段可能很多工作放在特征工程上,而迁移到深度学习之后可以解放很多特征工程的工作,可以让工程师们从一个更高的层次去审视问题,比如如何设计优化目标,如何准备表示用户等。Airbnb的工程师探索深度学习两年,仍谦虚地表示才刚刚开始。希望他们后面有更优秀的工作。

ps.那是不是就说GDBT模型没啥用途了呢?其实不然,在一些中小规模项目或者短期项目上,依靠GBDT模型可以短频快地取得业务收益,毕竟工业界里快速拿到业务收益才是最重要的。

最后总结

笔者也从事过一个排序场景,针对同一个目标持续迭代达两年时间,经历从线性模型、GBDT模型、FM模型再到深度模型的调研和上线的全过程,也收获颇多。文章给我的最大感触就是作者进行了大量的尝试,但并不是浅尝辄止,针对一个work的改进为什么有效果,针对一个不work的尝试为什么没有效果,作者都进行了深入的分析和思考,并尝试给出解释。这点是非常值得算法工程师们学习和借鉴的。一方面快速迭代和大量实验,有利于验证想法和拿到实际的业务收益。另一方面基于实验结果来反思想法,有利于增强对问题的认识、个人的技术沉淀和成长。


本文地址:https://www.6aiq.com/article/1552975478018
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出