上传训练模型
虽然模型训练发生在学习排序 (Learning to Rank) 插件之外,但您可以使用该插件来记录特征分数。训练好模型后,您可以将其上传到插件,支持的序列化格式包括 RankLib 和 XGBoost。
RankLib 模型训练
特征日志记录过程会生成一个 RankLib 可用的判断文件。在以下判断文件中,ID 为 1 的查询 rambo
包含针对一组文档记录的特征 1(标题 TF*IDF
分数)和特征 2(描述 TF*IDF
分数)。
4 qid:1 1:9.8376875 2:12.318446 # 7555 rambo
3 qid:1 1:10.7808075 2:9.510193 # 1370 rambo
3 qid:1 1:10.7808075 2:6.8449354 # 1369 rambo
3 qid:1 1:10.7808075 2:0.0 # 1368 rambo
可以使用以下命令调用 RankLib 库
cmd = "java -jar RankLib-2.8.jar -ranker %s -train%rs -save %s -frate 1.0" % (whichModel, judgmentsWithFeaturesFile, modelOutput)
judgmentsWithFeatureFile
是提供给 RankLib 进行训练的输入。可以传递其他参数。有关更多信息,请参阅 RankLib 文档。
RankLib 以其自己的序列化格式输出模型。如下例所示,LambdaMART 模型是回归树的集合。
## LambdaMART
## No. of trees = 1000
## No. of leaves = 10
## No. of threshold candidates = 256
## Learning rate = 0.1
## Stop early = 100
<ensemble>
<tree id="1" weight="0.1">
<split>
<feature> 2 </feature>
...
在 RankLib 模型中,集成中的每棵树都会检查特征值,根据这些特征值做出决策,并输出相关性分数。特征按其序号位置引用,从 1 开始,对应于原始特征集中的第 0 个特征。RankLib 在模型训练期间不使用特征名称。
其他 RankLib 模型
RankLib 是一个库,除了 LambdaMART 之外,它还实现了其他几种模型类型,例如 MART、RankNet、RankBoost、AdaRank、Coordinate Ascent、ListNet 和 Random Forests。这些模型中的每一种都有自己的一组参数和训练过程。
例如,RankNet 模型是一个神经网络,它学习预测一个文档比另一个文档更相关的概率。该模型使用配对损失函数进行训练,该函数将两个文档的预测相关性与实际相关性进行比较。该模型以类似于以下示例的格式序列化:
## RankNet
## Epochs = 100
## No. of features = 5
## No. of hidden layers = 1
...
## Layer 1: 10 neurons
1 2
1
10
0 0 -0.013491530393429608 0.031183180961270988 0.06558792020112071 -0.006024092627087733 0.05729619574181734 -0.0017010373987742411 0.07684848696852313 -0.06570387602230028 0.04390491141617467 0.013371636736099578
...
所有这些模型都可以与学习排序 (Learning to Rank) 插件一起使用,前提是模型以 RankLib 格式序列化。
XGBoost 模型训练
与 RankLib 模型不同,XGBoost 模型以梯度提升决策树特有的格式序列化,如下例所示。
[ { "nodeid": 0, "depth": 0, "split": "tmdb_multi", "split_condition": 11.2009, "yes": 1, "no": 2, "missing": 1, "children": [
{ "nodeid": 1, "depth": 1, "split": "tmdb_title", "split_condition": 2.20631, "yes": 3, "no": 4, "missing": 3, "children": [
{ "nodeid": 3, "leaf": -0.03125 },
...
XGBoost 参数
可以为 XGBoost 模型指定可选参数。这些参数以对象形式指定,决策树在 splits
字段中指定。支持的参数包括 objective
,它定义了模型学习目标,如 XGBoost 文档 中所述。此参数可以转换最终的模型预测。支持的值包括 binary:logistic
、binary:logitraw
、rank:ndcg
、rank:map
、rank:pairwise
、reg:linear
和 reg:logistic
。
简单线性模型
机器学习 (ML) 模型,例如支持向量机 (SVM),会为每个特征输出线性权重。LTR 模型支持以简单格式表示这些线性权重,例如从 SVM 或线性回归模型中学习到的权重。在以下示例输出中,权重表示特征在模型预测中的相对重要性:
{
"title_query" : 0.3,
"body_query" : 0.5,
"recency" : 0.1
}
特征归一化
特征归一化用于将特征值转换到一致的范围,通常在 0 到 1 或 -1 到 1 之间。这在训练阶段完成,以便更好地理解每个特征的相对影响。某些模型,特别是像 SVMRank 这样的线性模型,依赖于归一化才能正常运行。
模型上传过程
训练完模型后,下一步是使其可用于搜索操作。这涉及将模型上传到学习排序 (Learning to Rank) 插件。上传模型时,您必须提供以下信息:
- 训练期间使用的特征集
- 模型类型,例如 RankLib 或 XGBoost
- 模型内容
以下示例请求展示了如何上传一个使用 more_movie_features
特征集训练的 RankLib 模型:
POST _ltr/_featureset/more_movie_features/_createmodel
{
"model": {
"name": "my_ranklib_model",
"model": {
"type": "model/ranklib",
"definition": "## LambdaMART\n
## No. of trees = 1000
## No. of leaves = 10
## No. of threshold candidates = 256
## Learning rate = 0.1
## Stop early = 100
<ensemble>
<tree id="1" weight="0.1">
<split>
<feature> 2 </feature>
...
"
}
}
}
以下示例请求展示了如何上传一个使用 more_movie_features
特征集训练的 XGBoost 模型:
POST _ltr/_featureset/more_movie_features/_createmodel
{
"model": {
"name": "my_xgboost_model",
"model": {
"type": "model/xgboost+json",
"definition": "[ { \"nodeid\": 0, \"depth\": 0, \"split\": \"tmdb_multi\", \"split_condition\": 11.2009, \"yes\": 1, \"no\": 2, \"missing\": 1, \"children\": [
{ \"nodeid\": 1, \"depth\": 1, \"split\": \"tmdb_title\", \"split_condition\": 2.20631, \"yes\": 3, \"no\": 4, \"missing\": 3, \"children\": [
{ \"nodeid\": 3, \"leaf\": -0.03125 },
..."
}
}
}
以下示例请求展示了如何上传一个使用 more_movie_features
特征集并带参数训练的 XGBoost 模型:
POST _ltr/_featureset/more_movie_features/_createmodel
{
"model": {
"name": "my_xgboost_model",
"model": {
"type": "model/xgboost+json",
"definition": "{
\"objective\": \"reg:logistic\",
\"splits\": [ { \"nodeid\": 0, \"depth\": 0, \"split\": \"tmdb_multi\", \"split_condition\": 11.2009, \"yes\": 1, \"no\": 2, \"missing\": 1, \"children\": [
{ \"nodeid\": 1, \"depth\": 1, \"split\": \"tmdb_title\", \"split_condition\": 2.20631, \"yes\": 3, \"no\": 4, \"missing\": 3, \"children\": [
{ \"nodeid\": 3, \"leaf\": -0.03125 },
...
]
}"
}
}
}
以下示例请求展示了如何上传一个使用 more_movie_features
特征集训练的简单线性模型:
POST _ltr/_featureset/more_movie_features/_createmodel
{
"model": {
"name": "my_linear_model",
"model": {
"type": "model/linear",
"definition": """
{
"title_query" : 0.3,
"body_query" : 0.5,
"recency" : 0.1
}
"""
}
}
}
创建带有特征归一化的模型
特征归一化是在模型评估之前可以应用的关键预处理步骤。LTR 支持两种类型的特征归一化:最小-最大归一化和标准归一化。
标准归一化
标准归一化按如下方式转换特征:
- 将平均值映射到 0
- 将高于平均值的一个标准差映射到 1
- 将低于平均值的一个标准差映射到 -1
以下示例请求展示了如何创建带有标准特征归一化的模型:
POST _ltr/_featureset/more_movie_features/_createmodel
{
"model": {
"name": "my_linear_model",
"model": {
"type": "model/linear",
"feature_normalizers": {
"release_year": {
"standard": {
"mean": 1970,
"standard_deviation": 30
}
}
},
"definition": """
{
"release_year" : 0.3,
"body_query" : 0.5,
"recency" : 0.1
}
"""
}
}
}
最小-最大归一化
最小-最大归一化将特征缩放到固定范围,通常在 0 到 1 之间。最小-最大归一化按如下方式转换特征:
- 将指定最小值映射到 0
- 将指定最大值映射到 1
- 将值在 0 到 1 之间线性缩放
以下示例请求展示了如何实现最小-最大归一化:
"feature_normalizers": {
"vote_average": {
"min_max": {
"minimum": 0,
"maximum": 10
}
}
}
模型与特征集的独立性
模型最初是参照特征集创建的。创建后,它们作为独立的顶级实体存在。
访问模型
要检索模型,请使用 GET 请求
GET _ltr/_model/my_linear_model
要删除模型,请使用 DELETE 请求
DELETE _ltr/_model/my_linear_model
模型名称在所有特征集中必须是全局唯一的。
模型持久性
创建模型时,其特征会被复制。这可以防止对原始特征的更改影响现有模型或模型生产。例如,如果用于创建模型的特征集被删除,您仍然可以访问和使用该模型。
模型响应
检索模型时,您会收到一个响应,其中包含用于创建模型的特征,如下例所示:
{
"_index": ".ltrstore",
"_type": "store",
"_id": "model-my_linear_model",
"_version": 1,
"found": true,
"_source": {
"name": "my_linear_model",
"type": "model",
"model": {
"name": "my_linear_model",
"feature_set": {
"name": "more_movie_features",
"features": [
{
"name": "body_query",
"params": [
"keywords"
],
"template": {
"match": {
"overview": ""
}
}
},
{
"name": "title_query",
"params": [
"keywords"
],
"template": {
"match": {
"title": ""
}
}
}
]}}}
后续步骤
了解如何使用 LTR 进行搜索。