3

推荐系统:从千人千面到千域千面

 3 years ago
source link: https://www.biaodianfu.com/amap-suggestion-optimization-practice.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

谈到推荐系统,很多人的印象中是“个人性推荐”和“千人千面”。关于“千域千面”应该很少人提及,主要能用到的场景不多,先前有想过在酒店场景上应用,但是由于各种原因最终没有尝试。以下是高德地图在“千域千面”的一些经验,记录下来供后续学习。

Learning to Rank(LTR)在高德的尝试

搜索建议(suggest服务),用户在输入框输入query的过程中,为用户自动补全query或POI,罗列出补全后的所有候选项,并进行智能排序。

Learning to Rank(LTR)是用机器学习的方法来解决检索系统中的排序问题。业界比较常用的模型是GBrank,Loss方案用的最多的是Pair Wise,这里也保持一致。一般应用LTR解决实际问题,最重要的问题之一就是如何获得样本。

  • 高德地图每天的访问量巨大,这背后隐藏的候选POI更是一个天文数字,想要使用人工标注的方法去获得样本明显不现实。
  • 如果想要使用一些样本自动构造的方法,比如基于用户对POI的点击情况构建样本pair <click, no-click>,也会遇到如下的问题:
    • 容易出现点击过拟合,以前点击什么,以后都给什么结果。
    • 有时,用户点击行为也无法衡量真实满意度。
    • Suggest前端只展示排序Top 10结果,更多的结果没有机会展现给用户,自然没有点击。

部分用户习惯自己输入完整Query进行搜索,而不使用搜索建议的补全结果,统计不到这部分用户的需求。对于这几个问题总结起来就是:无点击数据时,建模很迷茫。但就算有某个POI的点击,却也无法代表用户实际是满意的。最后,在模型学习中,也面临了特征稀疏性的挑战。统计学习的目标是全局误差的一个最小化。稀疏特征由于影响的样本较少,在全局上影响不大,常常被模型忽略。但是实际中一些中长尾case的解决却往往要依靠这些特征。因此,如何在模型学习过程中进行调优是很重要。

第一步,融合服务端多张日志表,包括搜索建议、搜索、导航等。接着,进行session的切分和清洗。最后,通过把输入session中,末尾query的点击计算到session中所有query上,以此满足实现用户输入session最短的优化目标。

最终,抽取线上点击日志超过百万条的随机query,每条query召回前N条候选POI。利用上述样本构造方案,最终生成千万级别的有效样本作为GBrank的训练样本。

  • 特征方面,主要考虑了4种建模需求,每种需求都有对应的特征设计方案:
  • 有多个召回链路,包括:不同城市、拼音召回。因此,需要一种特征设计,解决不同召回链路间的可比性。
  • 随着用户的不断输入,目标POI不是静态的,而是动态变化的。需要一种特征能够表示不同query下的动态需求。
  • 低频长尾query,无点击等后验特征,需要补充先验特征。
  • LBS服务,有很强的区域个性化需求。不同区域用户的需求有很大不同。为实现区域个性化,做到千域千面,首先利用geohash算法对地理空间进行分片,每个分片都得到一串唯一的标识符。从而可以在这个标识符(分片)上分别统计特征。

详细的特征设计,如下表所示:

初版模型,下掉所有规则,在测试集上MRR 有5个点左右的提升,但模型学习也存在一些问题,gbrank特征学习的非常不均匀。树节点分裂时只选择了少数特征,其他特征没有发挥作用。建模的第二个难题:模型学习的调优问题。具体来就是如何解决gbrank特征选择不均匀的问题。

经过分析,造成特征学习不均衡的原因主要有:

  • 交叉特征query-click的缺失程度较高,60%的样本该特征值为0。该特征的树节点分裂收益较小,特征无法被选择。然而,事实上,在点击充分的情况下,query-click的点击比city-click更接近用户的真实意图。
  • 对于文本相似特征,虽然不会缺失,但是它的正逆序比较低,因此节点分裂收益也比city-click低,同样无法被选择。

综上,由于各种原因,导致树模型学习过程中,特征选择时,不停选择同一个特征(city-click)作为树节点,使得其他特征未起到应有的作用。解决这个问题方案有两种:

  • 对稀疏特征的样本、低频query的样本进行过采样,从而增大分裂收益。优点是实现简单,但缺点也很明显:改变了样本的真实分布,并且过采样对所有特征生效,无法灵活的实现调整目标。
  • 调loss function。按两个样本的特征差值,修改负梯度(残差),从而修改该特征的下一轮分裂收益。例如,对于query-click特征非缺失的样本,学习错误时会产生loss,调loss就是给这个loss增加惩罚项loss_diff。随着loss的增加,下一棵树的分裂收益随之增加,这时query-click特征被选作分裂节点的概率就增加了。具体的计算公式如下式:

-\text{gradient}=y_{ij}-\frac{1}{1+\exp(-(h(x_i)-h(x_j))+\text{loss}_{diff})}

以上公式是交叉熵损失函数的负梯度,loss_{diff} 相当于对sigmod函数的一个平移。

差值越大,loss_{diff}越大,惩罚力度越大,相应的下一轮迭代该特征的分裂收益也就越大。调loss后,重新训练模型,测试集MRR在初版模型的基础又提升了2个点。同时历史排序case的解决比例从40%提升到70%,效果明显。

Learning to Rank技术在高德搜索建议应用后,使系统摆脱了策略耦合、依靠补丁的规则排序方式,取得了明显的效果收益。gbrank模型上线后,效果基本覆盖了各频次query的排序需求。目前,已经完成了人群个性化、个体个性化的建模上线,并且正在积极推进深度学习、向量索引、用户行为序列预测在高德搜索建议上的应用。

参考链接:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK