学习排序(Learning To Rank,简称 LTR)特性目前还处于技术预览阶段,可能会在未来的版本中发生改变或被移除。Elastic将致力于修复所有的问题,但此特性不属于正式GA特性的支持SLA。
学习排序(LTR)使用一个经过训练的机器学习(ML)模型为你的搜索引擎构建一个排名函数。通常,该模型被用作第二阶段的重新排序器,用于改进由简单的第一阶段检索算法返回的搜索结果的相关性。LTR函数接收一份文档列表和一个搜索上下文,并输出重排名后的文档:
图7. 学习排序概述
除了需要排序的文档列表,LTR函数还需要一个搜索上下文。通常,这个搜索上下文至少包含用户提供的搜索词(上述示例中的text_query
)。搜索上下文还可以提供用于排名模式的额外信息。这可能是关于执行搜索的用户的信息(如人口统计数据、地理位置或年龄);关于查询的信息(如查询长度);或查询上下文中的文档信息(如标题字段的得分)。
LTR模型通常是在一个判断列表上进行训练的,这是一组带有相关性等级的查询和文档。判断列表可以由人或机器生成:它们通常由行为分析数据填充,通常带有人工审核。判断列表决定了给定搜索查询的结果的理想排序。LTR的目标是尽可能地将模型拟合到新的查询和文档的判断列表排名。
判断列表是用来训练模型的主要输入。它由包含查询和文档对,以及它们对应的相关性标签的数据集组成。相关性判断通常是二元的(相关/不相关)或更细粒度的标签,比如从0(完全不相关)到4(高度相关)的等级。下面的例子使用了一个分级的相关性判断。
图8. 判断列表示例
虽然判断列表可以由人工手动创建,但是也有技术可用来利用用户参与度数据,如点击或转化,来自动构建判断列表。
你的判断列表的数量和质量将极大地影响LTR模型的整体性能。在构建你的判断列表时,以下几个方面应当非常谨慎考虑:
仅依赖于查询和文档对并不能提供足够的信息来训练用于LTR的ML模型。判断列表中的相关性得分依赖于多个属性或 特征 。需要提取这些特征以确定各个组件如何组合以确定文档的相关性。判断列表加上提取的特征构成了LTR模型的训练数据集。
这些特征可以分为三个主要类别:
title
字段的BM25得分。为了准备训练数据集,特征被添加到判断列表中:
图9. 带有特征的判断列表
在Elasticsearch中,使用模板查询在构建训练数据集和查询时进行特征提取。以下是一个模板查询的例子:
[
{
"query_extractor": {
"feature_name": "title_bm25",
"query": { "match": { "title": "{{query}}" } }
}
}
]
当然,LTR的核心是ML模型。模型是使用上述描述的训练数据和目标进行训练的。在LTR的情况下,目标是根据如 nDCG 或 MAP 等排名指标,以最优的方式对结果文档进行排名,给出判断列表。模型完全依赖于来自训练数据的特征和相关性标签。
LTR领域正在快速发展,许多方法和模型类型正在被尝试。在实践中,Elasticsearch特别依赖于梯度提升决策树(GBDT)模型进行LTR推理。
注意,Elasticsearch支持模型推理,但训练过程本身必须在Elasticsearch之外进行,使用GBDT模型。在目前最流行的LTR模型中,LambdaMART提供了强大的排名性能和低推理延迟。它依赖于GBDT模型,因此非常适合在Elasticsearch中的LTR。
XGBoost是一个知名的库,提供了LambdaMART的实现,使其成为LTR的热门选择。我们在eland中提供了帮助器,以方便将训练好的XBGRanker模型作为你在Elasticsearch中的LTR模型。
要了解更多关于训练的信息,请查看训练和部署LTR模型,或者查看我们在elasticsearch-labs
仓库中可用的交互式LTR笔记。
通常,XGBoost模型训练过程使用标准的Python数据科学工具,如Pandas和scikit-learn。
我们在elasticsearch-labs
仓库中开发了一个示例笔记。这个交互式Python笔记详细描述了一个端到端的模型训练和部署工作流。
我们强烈推荐在你的工作流中使用eland,因为它提供了用于在Elasticsearch中处理LTR的重要功能。使用eland可以:
特征提取器是使用模板查询定义的。Eland提供了eland.ml.ltr.QueryFeatureExtractor
来直接在Python中定义这些特征提取器:
from eland.ml.ltr import QueryFeatureExtractor
feature_extractors=[
# 我们希望使用匹配查询的标题字段的得分作为一个特征:
QueryFeatureExtractor(
feature_name="title_bm25",
query={"match": {"title": "{{query}}"}}
),
# 我们可以使用script_score查询直接获取字段值作为一个特征:
QueryFeatureExtractor(
feature_name="popularity",
query={
"script_score": {
"query": {"exists": {"field": "popularity"}},
"script": {"source": "return doc['popularity'].value;"},
}
},
),
# 我们可以在查询的值上执行一个脚本并使用返回值作为一个特征:
QueryFeatureExtractor(
feature_name="query_length",
query={
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "return params['query'].splitOnToken(' ').length;",
"params": {
"query": "{{query}}",
}
},
}
},
),
]
一旦特征提取器被定义,它们就被包装在一个eland.ml.ltr.LTRModelConfig
对象中,用于后续的训练步骤:
from eland.ml.ltr import LTRModelConfig
ltr_config = LTRModelConfig(feature_extractors)
构建你的数据集是训练过程中的一个关键步骤。这涉及到提取相关的特征并将它们添加到你的判断列表中。我们建议使用Eland的eland.ml.ltr.FeatureLogger
助手类进行这个过程。
from eland.ml.ltr import FeatureLogger
# 创建一个特征记录器,它将被用于查询Elasticsearch以检索特征:
feature_logger = FeatureLogger(es_client, MOVIE_INDEX, ltr_config)
FeatureLogger提供了一个extract_features
方法,它使你能够为判断列表中的特定文档提取特征。同时,你可以传递查询参数给前面定义的特征提取器:
feature_logger.extract_features(
query_params={"query": "foo"},
doc_ids=["doc-1", "doc-2"]
)
我们的示例笔记解释了如何使用FeatureLogger
构建一个训练数据集,通过将特征添加到判断列表中。
一旦你的模型训练完成,你将能够将它部署到你的Elasticsearch集群。你可以使用Eland的MLModel.import_ltr_model method
方法:
from eland.ml import MLModel
LEARNING_TO_RANK_MODEL_ID="ltr-model-xgboost"
MLModel.import_ltr_model(
es_client=es_client,
model=ranker,
model_id=LEARNING_TO_RANK_MODEL_ID,
ltr_model_config=ltr_config,
es_if_exists="replace",
)
此方法将以Elasticsearch可以理解的格式序列化训练好的模型和学习排序配置(包括特征提取),然后使用创建训练模型API将模型部署到Elasticsearch。
目前支持以下类型的模型用于与Elasticsearch的LTR:
未来将支持更多类型的模型。
一旦你的模型在Elasticsearch中部署,你就可以使用训练模型API进行管理。现在,你已经准备好在搜索时间使用你的LTR模型作为重新评分器。
一旦你的LTR模型在Elasticsearch中训练和部署,它就可以在搜索API中作为一个重新评分器使用:
GET my-index/_search
{
"query": {
"multi_match": {
"fields": ["title", "content"],
"query": "the quick brown fox"
}
},
"rescore": {
"learning_to_rank": {
"model_id": "ltr-model",
"params": {
"query_text": "the quick brown fox"
}
},
"window_size": 100
}
}
第一轮查询提供需要重新评分的文档。 | |
---|---|
上传到Elasticsearch的训练模型的唯一标识符。 | |
命名参数,传递给用于特征提取的查询模板。 | |
应由重新评分器在每个分片上检查的文档数量。 |
LTR模型返回的得分通常不可与第一轮查询发出的得分进行比较,可能会低于未重新评分的得分。这可能导致未重新评分的结果文档排名高于重新评分的文档。为了防止这种情况,LTR重新评分器的window_size
参数是必需的,应大于或等于from + size
。
当向用户提供分页时,window_size
应保持恒定,因为每一页都是通过传递不同的from
值来进行的。改变window_size
可以改变顶部的命中,导致用户在翻页时结果混乱地移动。
根据你的模型如何训练,模型可能会为文档返回负分。虽然第一阶段的检索和排名不允许使用负分,但是在LTR重新评分器中是可以使用负分的。
LTR重新评分器与collapse feature不兼容。
我们目前不支持术语统计作为特征,但未来的版本将引入这个能力。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。