写点什么

XGBoost 在携程搜索排序中的应用

  • 2019-12-27
  • 本文字数:3285 字

    阅读完需:约 11 分钟

XGBoost在携程搜索排序中的应用

一、前言

在互联网高速发展的今天,越来越复杂的特征被应用到搜索中,对于检索模型的排序,基本的业务规则排序或者人工调参的方式已经不能满足需求了,此时由于大数据的加持,机器学习、深度学习成为了一项可以选择的方式。


携程主站搜索作为主要的流量入口之一,是用户浏览信息的重要方式。用户搜索方式多样、对接业务多样给携程主站搜索(下文简称大搜)带来了许多挑战,如:


  • 搜索方式多样化

  • 场景多样化

  • 业务多样化

  • 意图多样化

  • 用户多样化


为了更好满足搜索的多样化,大搜团队对传统机器学习和深度学习方向进行探索。


说起机器学习和深度学习,是个很大的话题,今天我们只来一起聊聊传统机器学习中 XGBoost 在大搜中的排序实践。

二、XGBoost 探索与实践

聊起搜索排序,那肯定离不开 L2R。Learning to Rank,简称(L2R),是一个监督学习的过程,需要提前做特征选取、训练数据的获取然后再做模型训练。


L2R 可以分为:


  • PointWise

  • PairWise

  • ListWise


PointWise 方法只考虑给定查询下单个文档的绝对相关度,不考虑其他文档和给定查询的相关度。


PairWise 方法考虑给定查询下两个文档直接的相对相关度。比如给定查询 query 的一个真实文档序列,我们只需要考虑任意两个相关度不同的文档直接的相对相关度。相比 PointWise,PairWise 方法通过考虑任意两个文档直接的相关度进行排序,有一定的优势。


ListWise 直接考虑给定查询下的文档集合的整体序列,直接优化模型输出的文档序列,使得尽可能接近真实文档序列。


下面先简单介绍 XGBoost 的应用流程:



XGBoost 是一个优化的分布式梯度增强库,增强树模型,灵活便捷。但对高维度的稀疏矩阵支持不是很好,另外调参确实有点麻烦。

三、特征工程实践

在传统机器学习下,特征工程显的尤为重要,不论后续模型工程做的多好,如果前期的特征工程没有做好,那么训练的结果不会有多好。所以对特征处理的总体逻辑如下:


3.1 前期数据准备

首先,我们需要进行需求分析,就是在什么场景下排序。假设我们需要针对搜索召回的 POI 场景进行排序,那么需要确定几件事情:


  • 数据来源:搜索的数据就是各种 POI,然后需要确定我们有哪些数据可以用来排序,比如最近半年的搜索 POI 的曝光点击数据等;

  • 特征梳理:需要梳理影响 POI 排序的因子,例如查询相关特征、POI 相关特征、用户相关特征等;

  • 标注规则制定:每次搜索召回的每个 POI,会有曝光和点击数据,简单点,比如:我们可以将曝光位置作为默认标注分,当有点击,就将标注分在原来的基础上加一;

  • 数据埋点/数据抽取:这是两种方式,可以根据实际需求进行选择;

  • 数据埋点:可以在线上实时生成特征,然后进行日志埋点,离线分析的时候可以直接从日志中拉取即可,这种方式,需要提前进行埋点。

  • 数据抽取:可以通过大数据平台拉取历史数据,然后进行离线计算抽取所需特征,这种方式虽然慢点,但是可以拉取历史数据进行分析。

3.2 特征处理

前期的数据准备工作完成了,接下来可以开始看看数据质量了。


  • 查看缺失值:绝大多数情况下,我们都需要对缺失值进行处理;

  • 特征归一化处理:监督学习对特征的尺度非常敏感,因此,需要对特征归一化用来促进模型更好的收敛;

  • 噪声点处理:异常的数据会影响模型预测的正确性;

  • 特征连续值分析:分析特征的值分布范围是否均匀;

  • 特征之间的相关性分析;



通过连续值特征可以分析每个特征值的大致分布范围,有利于对相关特征进行数据补充或者重新筛选。



通过特征相关性的分析,如上我们看到几个特征之间有很高的相关性,那么可以帮助我们做特征组合或者特征筛选等等方面决策。

四、模型工程实践

4.1 评估指标制定

在搜索业务中,考虑的有以下两种情况:


  • 看重用户搜索的成功率,即有没有点击;

  • 看重页面第一屏的曝光点击率;


在文章开头提到的 L2R 的三种分类中,我们在 XGBoost 参数 objective 配置“rank:pairwise”,同时使用搜索系统常用的评估指标 NDCG (Normalized Discounted Cumulative Gain) 。


def _to_list(x):    if isinstance(x, list):        return x    return [x]
def ndcg(y_true, y_pred, k=20, rel_threshold=0): if k <= 0: return 0 y_true = _to_list(np.squeeze(y_true).tolist()) y_pred = _to_list(np.squeeze(y_pred).tolist()) c = list(zip(y_true, y_pred)) random.shuffle(c) c_g = sorted(c, key=lambda x: x[0], reverse=True) c_p = sorted(c, key=lambda x: x[1], reverse=True) idcg = 0 ndcg = 0 for i, (g, p) in enumerate(c_g): if i >= k: break if g > rel_threshold: idcg += (math.pow(2, g) - 1) / math.log(2 + i) for i, (g, p) in enumerate(c_p): if i >= k: break if g > rel_threshold: ndcg += (math.pow(2, g) - 1) / math.log(2 + i) if idcg == 0: return 0 else: return ndcg / idcg
复制代码

4.2 初始模型训练

前期通过基础的模型训练,可以初步得出一些初始参数和相关特征的重要度等相关信息。


train_dmatrix = DMatrix(x_train, y_train)valid_dmatrix = DMatrix(x_valid, y_valid)test_dmatrix = DMatrix(x_test)
train_dmatrix.set_group(group_train)valid_dmatrix.set_group(group_valid)test_dmatrix.set_group(group_test)
params = {'objective': 'rank:pairwise', 'eta': 0.5, 'gamma': 1.0, 'min_child_weight': 0.5, 'max_depth': 8,'eval_metric':'ndcg@10-','nthread':16}xgb_model = xgb.train(params, train_dmatrix, num_boost_round=1000, evals=[(valid_dmatrix, 'validation')])
复制代码



import pandas as pd print('特征名称', '特征权重值')feature_score = xgb_model.get_fscore()pd.Series(feature_score).sort_values(ascending=False)
复制代码


4.3 模型调优五部曲

通过上述基础的模型训练,我们可以得出相关的初始参数,进入到五部曲环节,XGBoost 参数调节基本为五个环节:


  • Step 1:选择一组初始参数;

  • Step 2:改变 max_depth 和 min_child_weight;

  • Step 3:调节 gamma 降低模型过拟合风险;

  • Step 4:调节 subsample 和 colsample_bytree 改变数据采样策略;

  • Step 5:调节学习率 eta;


例如我们在通过 step1,可以观察弱分类数目的大致范围,看看模型是过拟合还是欠拟合。



通过 step2 调整树的深度和节点权重,这些参数对 XGBoost 性能影响最大,我们简要概述他们:


  • max_depth:树的最大深度。增加这个值会使模型更加复杂,也容易出现过拟合,深度 3-10 是合理的;

  • min_child_weight:正则化参数。如果树分区中的实例权重小于定义的总和,则停止树构建过程。


可以通过网格搜索发现最佳结果,当然也可以通过其他方式。



我们看到,从网格搜索的结果,分数的提高主要是基于 max_depth 增加。min_child_weight 稍有影响的成绩,但是 min_child_weight = 6 会更好一些。

4.4 模型离线评估

通过调优五部曲,训练,生成最终的模型之后,就要进入离线评估阶段。离线拉取线上生产用户的请求,模拟生产,对模型预测的结果进行检验,根据在之前评估指标制定环节所提到的用户点击率和第一屏曝光点击率,比对线上用户点击产品的位置和模型预测的位置,同时对比两者之间的第一屏曝光点击率。

4.5 模型预测

通过 AB 实验,对模型进行线上预测,实时监测效果评估,方便之后的迭代和优化。

五、总结与展望

  • 对于传统的机器学习,最重要的一步是要做好需求分析,评估这种算法是否能有效解决该问题,否则得不偿失;

  • 前期的特征工程非常关键。通过多次的摸索发现,特征没有选取好,或者数据覆盖不全,标注没做好,导致后续模型不论怎么调优,都无法达到预定的效果;

  • 选定目标后,可以先尝试一些优秀的开源工具、优秀的数据分析工具。直观的图表能帮助你做更好的决策,优秀的算法库,能避免重复造轮子;

  • 单一的算法无法满足搜索排序应用场景,多模型融合以及深度学习方向需要做更深入的探索与实践;


作者介绍


曹城,携程搜索部门高级研发工程师,主要负责携程搜索的个性化推荐和搜索排序等工作。


本文转载自公众号携程技术(ID:ctriptech)。


原文链接


https://mp.weixin.qq.com/s/X4K6UFZPxL05v2uolId7Lw


2019-12-27 14:003347

评论

发布
暂无评论
发现更多内容

编写令人愉悦的API接口(二)

Geek_42915f

Java APi设计 接口规范

用 JavaScript 实现寻路算法 —— 编程训练

三钻

Java 算法 大前端 七日更 寻路算法

从中心到边缘,IoT正变为互联网之上的一张大网

华为云开发者联盟

物联网 IoT 网络

Nice!有了这份Alibaba内部 “Java面试宝典”,跳槽面试稳了

Java架构之路

Java 程序员 架构 面试 编程语言

Serverless 是一种思想状态

Serverless Devs

Java Serverless 运维 云原生 后端

你不好奇 Linux 网络发包过程吗?

小林coding

Linux 操作系统 网络

阿里P8整理出Nginx笔记:Nginx应用与运维实战核心篇

996小迁

Java nginx 架构 面试

大神带你一睹为快!阿里技术官亲自码了“2000页的Spring全家桶笔记”真牛逼!

比伯

Java 编程 程序员 架构 计算机

区块链数字货币多币种钱包开发案例

如何阅读别人的源码

熊斌

学习 Code Review 源码阅读 七日更

传统数仓如何转型大数据

数据社

大数据 数据仓库 七日更

程序员必看的Redis6.0多线程性能测试结果及分析 你看懂了嘛?

比伯

Java 编程 架构 面试

执法监督信息化建设,公安情报指挥一体化合成作战系统开发

t13823115967

智慧公安

灵魂一问:数据库连接池到底该怎么配?

Gopher指北

MySQL Go 语言

LeetCode题解:42. 接雨水,暴力法,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

高性能MySQL

田维常

MySQL

波场智能合约系统开发技术方案丨智能合约DAPP系统开发源码

滴滴内部框架手册:Spring5+SpringMVC3+MyBatis3.X

Java架构追梦

Java spring 架构 mybatis springmvc

应对游戏业务的四大“崩溃”场景有妙招,安全畅玩不是梦!

华为云开发者联盟

游戏 场景 崩溃

架构师训练营第 1 期 - 第 11 周 - 命题作业

wgl

极客大学架构师训练营

判空使用isEmpty()方法真的可行吗?

田维常

Java

用 JavaScript 实现一个 TicTacToe 游戏 —— 编程训练

三钻

Java 算法 大前端 游戏开发 七日更

APP专项测试 —— 弱网测试

行者AI

测试

都 2021 年了,Serverless 能取代微服务吗?

Serverless Devs

Serverless 微服务 运维 云原生 后端

ECS实践案例丨逻辑卷的创建和扩容操作指导

华为云开发者联盟

数据库 数据 服务

软件测试的方法

测试人生路

软件测试

架构师训练营第 1 期 第 13 周作业

李循律

极客大学架构师训练营

顶会两篇论文连发,华为云医疗AI低调中崭露头角

华为云开发者联盟

人工智能 医疗 华为云

滴滴Java后台3面题目:网络+内存溢出+各种锁+高性能+消息队列

Java架构之路

Java 程序员 架构 面试 编程语言

社区一体化综合平台搭建,智慧平安小区建设解决方案

t13823115967

智慧城市 智慧平安社区平台建设

SpacePX挖矿系统APP开发|SpacePX挖矿软件开发

系统开发

XGBoost在携程搜索排序中的应用_大数据_曹城_InfoQ精选文章