在互联网高速发展的今天,越来越复杂的特征被应用到搜索中,对于检索模型的排序,基本的业务规则排序或者人工调参的方式已经不能满足需求了,此时由于大数据的加持,机器学习、深度学习成为了一项可以选择的方式。
携程主站搜索作为主要的流量入口之一,是用户浏览信息的重要方式。用户搜索方式多样、对接业务多样给携程主站搜索(下文简称大搜)带来了许多挑战,如:
为了更好满足搜索的多样化,大搜团队对传统机器学习和深度学习方向进行探索。
说起机器学习和深度学习,是个很大的话题,今天我们只来一起聊聊传统机器学习中XGBoost在大搜中的排序实践。
聊起搜索排序,那肯定离不开L2R。Learning to Rank,简称(L2R),是一个监督学习的过程,需要提前做特征选取、训练数据的获取然后再做模型训练。
L2R可以分为:
PointWise方法只考虑给定查询下单个文档的绝对相关度,不考虑其他文档和给定查询的相关度。
PairWise方法考虑给定查询下两个文档直接的相对相关度。比如给定查询query的一个真实文档序列,我们只需要考虑任意两个相关度不同的文档直接的相对相关度。相比PointWise,PairWise方法通过考虑任意两个文档直接的相关度进行排序,有一定的优势。
ListWise直接考虑给定查询下的文档集合的整体序列,直接优化模型输出的文档序列,使得尽可能接近真实文档序列。
下面先简单介绍XGBoost的应用流程:
XGBoost是一个优化的分布式梯度增强库,增强树模型,灵活便捷。但对高维度的稀疏矩阵支持不是很好,另外调参确实有点麻烦。
在传统机器学习下,特征工程显的尤为重要,不论后续模型工程做的多好,如果前期的特征工程没有做好,那么训练的结果不会有多好。所以对特征处理的总体逻辑如下:
首先,我们需要进行需求分析,就是在什么场景下排序。假设我们需要针对搜索召回的POI场景进行排序,那么需要确定几件事情:
前期的数据准备工作完成了,接下来可以开始看看数据质量了。
通过连续值特征可以分析每个特征值的大致分布范围,有利于对相关特征进行数据补充或者重新筛选。
通过特征相关性的分析,如上我们看到几个特征之间有很高的相关性,那么可以帮助我们做特征组合或者特征筛选等等方面决策。
在搜索业务中,考虑的有以下两种情况:
在文章开头提到的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
前期通过基础的模型训练,可以初步得出一些初始参数和相关特征的重要度等相关信息。
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)
通过上述基础的模型训练,我们可以得出相关的初始参数,进入到五部曲环节,XGBoost参数调节基本为五个环节:
例如我们在通过step1,可以观察弱分类数目的大致范围,看看模型是过拟合还是欠拟合。
通过step2调整树的深度和节点权重,这些参数对XGBoost性能影响最大,我们简要概述他们:
可以通过网格搜索发现最佳结果,当然也可以通过其他方式。
我们看到,从网格搜索的结果,分数的提高主要是基于max_depth增加。min_child_weight稍有影响的成绩,但是min_child_weight = 6会更好一些。
通过调优五部曲,训练,生成最终的模型之后,就要进入离线评估阶段。离线拉取线上生产用户的请求,模拟生产,对模型预测的结果进行检验,根据在之前评估指标制定环节所提到的用户点击率和第一屏曝光点击率,比对线上用户点击产品的位置和模型预测的位置,同时对比两者之间的第一屏曝光点击率。
通过AB实验,对模型进行线上预测,实时监测效果评估,方便之后的迭代和优化。
作者介绍:
曹城,携程搜索部门高级研发工程师,主要负责携程搜索的个性化推荐和搜索排序等工作。
本文转载自公众号携程技术(ID:ctriptech)。
原文链接:
领取专属 10元无门槛券
私享最新 技术干货