学习排序
使用学习排序(简称 LTR)模块,您可以在 Solr 中配置和运行机器学习排序模型。
该模块还支持在 Solr 内部进行特征日志记录。您在 Solr 外部唯一需要做的就是训练您自己的排序模型。
学习排序概念
重排名
重排名允许您运行一个简单的查询来匹配文档,然后使用来自另一个更复杂的查询的分数对前 N 个文档进行重排名。此页面描述了 LTR 复杂查询的使用,有关 Solr 发行版中包含的其他排名查询的信息,请参见查询重排名。
训练模型
特征工程
LTR 模块包括几个特征类,并支持自定义特征。每个特征类的 javadoc 都包含一个示例来说明该类的使用。 特征工程本身的过程完全取决于您的领域专业知识和创造力。
特征 | 类 | 示例参数 | 外部特征信息 |
---|---|---|---|
字段长度 |
|
(尚未)支持 |
|
字段值 |
|
(尚未)支持 |
|
原始分数 |
|
不适用 |
|
Solr 查询 |
|
支持 |
|
Solr 过滤器查询 |
|
支持 |
|
Solr 查询 + 过滤器查询 |
|
支持 |
|
值 |
|
支持 |
|
(自定义) |
(扩展 Feature 的自定义类) |
归一化器 | 类 | 示例参数 |
---|---|---|
恒等 |
|
|
最小-最大 |
|
|
标准 |
|
|
(自定义) |
(扩展 Normalizer 的自定义类) |
特征日志记录
ltr 模块包括一个 [features]
转换器,以支持计算和返回 特征提取 的特征值,特别是在您还没有实际的重排序模型时。
特征选择和模型训练
特征选择和模型训练在线下和 Solr 外部进行。 ltr 模块支持两种通用形式的模型以及自定义模型。 每个模型类的 javadoc 都包含一个示例来说明该类的配置。 以 JSON 文件的形式,您训练的模型或模型(例如,不同客户地理位置的不同模型)可以使用提供的 REST API 直接上传到 Solr。
通用形式 | 类 | 具体示例 |
---|---|---|
线性 |
RankSVM、Pranking |
|
多重加性树 |
LambdaMART、梯度提升回归树 (GBRT) |
|
神经网络 |
RankNet |
|
(包装器) |
(不适用) |
|
(自定义) |
(扩展 AdapterModel 的自定义类) |
(不适用) |
(自定义) |
(扩展 LTRScoringModel 的自定义类) |
(不适用) |
模块
这是通过 ltr
Solr 模块提供的,该模块需要在使用前启用。
LTR 配置
Learning-To-Rank 是一个模块,因此其插件必须在 solrconfig.xml
中配置。
最低要求
-
包含所需的模块 JAR。 请注意,默认情况下,路径是相对于 Solr 核心的,因此可能需要对您的配置进行调整,或者显式指定
$solr.install.dir
。<lib dir="${solr.install.dir:../../../..}/modules/ltr/lib/" regex=".*\.jar" />
-
声明
ltr
查询解析器。<queryParser name="ltr" class="org.apache.solr.ltr.search.LTRQParserPlugin"/>
-
配置特征值缓存。
<cache name="QUERY_DOC_FV" class="solr.search.CaffeineCache" size="4096" initialSize="2048" autowarmCount="4096" regenerator="solr.search.NoOpRegenerator" />
-
声明
[features]
转换器。<transformer name="features" class="org.apache.solr.ltr.response.transform.LTRFeatureLoggerTransformerFactory"> <str name="fvCacheName">QUERY_DOC_FV</str> </transformer>
-
声明
[interleaving]
转换器。<transformer name="interleaving" class="org.apache.solr.ltr.response.transform.LTRInterleavingTransformerFactory"/>
LTR 生命周期
特征存储
建议您将所有特征组织到类似于命名空间的存储中
-
存储中的特征必须唯一命名。
-
跨存储的相同或相似的特征可以共享相同的名称。
-
如果未指定存储名称,则将使用默认的
_DEFAULT_
特征存储。
要发现所有特征存储的名称
https://127.0.0.1:8983/solr/techproducts/schema/feature-store
要检查 commonFeatureStore
特征存储的内容
https://127.0.0.1:8983/solr/techproducts/schema/feature-store/commonFeatureStore
模型
-
一个模型只使用一个特征存储中的特征。
-
如果未指定存储,则将使用默认的
_DEFAULT_
特征存储。 -
一个模型不需要使用特征存储中定义的所有特征。
-
多个模型可以使用同一个特征存储。
要记录 currentFeatureStore
的特征的特征
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,score,[features store=currentFeatureStore]
在使用基于 currentFeatureStore
的 currentModel
进行重排序时,记录 nextFeatureStore
特征的特征
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=currentModel reRankDocs=100}&fl=id,score,[features store=nextFeatureStore]
查看所有模型
https://127.0.0.1:8983/solr/techproducts/schema/model-store
删除 currentModel
模型
curl -XDELETE 'https://127.0.0.1:8983/solr/techproducts/schema/model-store/currentModel'
只有当没有模型使用某个特征存储时,才能删除该特征存储。 |
删除 currentFeatureStore
特征存储
curl -XDELETE 'https://127.0.0.1:8983/solr/techproducts/schema/feature-store/currentFeatureStore'
使用大型模型
对于 SolrCloud,由于 ZooKeeper 缓冲区的限制,大型模型可能无法上传。在这种情况下,DefaultWrapperModel
可以帮助您将模型定义与上传的文件分开。
假设您考虑使用位于 /path/to/models/myModel.json
的大型模型,通过 DefaultWrapperModel
。
{
"store" : "largeModelsFeatureStore",
"name" : "myModel",
"class" : "...",
"features" : [
"..."
],
"params" : {
"...": "..."
}
}
首先,使用 <lib/>
指令将该目录添加到 Solr 的资源路径中
<lib dir="/path/to" regex="models" />
然后,配置 DefaultWrapperModel
以包装 myModel.json
{
"store" : "largeModelsFeatureStore",
"name" : "myWrapperModel",
"class" : "org.apache.solr.ltr.model.DefaultWrapperModel",
"params" : {
"resource" : "myModel.json"
}
}
myModel.json
将在初始化期间加载,并且可以通过指定 model=myWrapperModel
来使用。
myWrapperModel 中没有配置 "features" ,因为将使用包装的模型 (myModel ) 的特征;另请注意,为包装器模型配置的 "store" 必须与包装的模型的 "store" 匹配,即在本例中,使用名为 largeModelsFeatureStore 的特征存储。 |
<lib dir="/path/to/models" regex=".*\.json" /> 在这种情况下无法按预期工作,因为如果 <lib /> 指示文件,则 SolrResourceLoader 会将给定资源视为 JAR。 |
作为上述 DefaultWrapperModel
的替代方案,可以提高 ZooKeeper 的文件大小限制。
应用更改
特征存储和模型存储都是托管资源。 对托管资源所做的更改不会应用于活动的 Solr 组件,直到重新加载 Solr 集合(或单服务器模式下的 Solr 核心)。
快速入门 LTR
Solr 附带的 "techproducts"
示例已预配置为从 ltr
Solr 模块加载学习排名的所需插件,但默认情况下它们是禁用的。
要启用插件,请在运行 techproducts
示例时指定 solr.ltr.enabled
JVM 系统属性
bin/solr start -e techproducts -Dsolr.ltr.enabled=true
上传特征
要在 /path/myFeatures.json
文件中上传特征,请运行
curl -XPUT 'https://127.0.0.1:8983/solr/techproducts/schema/feature-store' --data-binary "@/path/myFeatures.json" -H 'Content-type:application/json'
要查看您刚刚上传的特征,请在浏览器中打开以下 URL
https://127.0.0.1:8983/solr/techproducts/schema/feature-store/_DEFAULT_
[
{
"name" : "documentRecency",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"q" : "{!func}recip( ms(NOW,last_modified), 3.16e-11, 1, 1)"
}
},
{
"name" : "isBook",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"fq": ["{!terms f=cat}book"]
}
},
{
"name" : "originalScore",
"class" : "org.apache.solr.ltr.feature.OriginalScoreFeature",
"params" : {}
}
]
记录特征
要记录作为查询一部分的特征,请将 [features]
添加到 fl
参数中,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,score,[features]
输出将包含特征值作为逗号分隔的列表,类似于此处显示的输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features]"}},
"response":{"numFound":2,"start":0,"maxScore":1.959392,"docs":[
{
"id":"GB18030TEST",
"score":1.959392,
"[features]":"documentRecency=0.020893794,isBook=0.0,originalScore=1.959392"},
{
"id":"UTF8TEST",
"score":1.5513437,
"[features]":"documentRecency=0.020893794,isBook=0.0,originalScore=1.5513437"}]
}}
特征日志记录参数
特征记录器转换器接受下面描述的参数。 有关如何使用它们的示例,请参见下面的 LTR 示例部分。
存储
-
无重排序
可选
默认值:
_DEFAULT_
重排序
可选
默认值:模型特征存储
此参数指定用于记录特征的特征存储。
在重排序查询中,使用的默认特征存储是模型特征存储(例如,
[features]
)。 logAll
-
无重排序
默认值:
true
重排序
记录器和模型具有相同的特征存储
默认值:
false
重排序
记录器和模型具有不同的特征存储
默认值:
true
此参数指定要记录的特征。
如果设置为
true
,则将打印特征存储中的所有特征。
如果设置为 false
,则仅打印模型使用的特征。
当没有传递重排序查询时,仅支持 logAll = 'true'。 传递 false 将导致 Solr 异常。 |
在传递重排序查询的日志记录场景中,如果记录器 store 与模型 store 不同,则仅支持 logAll = 'true'。 传递 false 将导致 Solr 异常。 |
格式
-
可选
默认值:
dense
此参数指定用于记录特征的格式。 支持的值为:
dense
和sparse
。您可以将默认行为更改为 sparse,在
solrconfig.xml
中的 特征记录器转换器声明中放置<str name="defaultFormat">sparse</str>
,如下所示
<transformer name="features" class="org.apache.solr.ltr.response.transform.LTRFeatureLoggerTransformerFactory">
<str name="fvCacheName">QUERY_DOC_FV</str>
<str name="defaultFormat">sparse</str>
<str name="csvKeyValueDelimiter">:</str>
<str name="csvFeatureSeparator"> </str>
</transformer>
上传模型
要在 /path/myModel.json
文件中上传模型,请运行
curl -XPUT 'https://127.0.0.1:8983/solr/techproducts/schema/model-store' --data-binary "@/path/myModel.json" -H 'Content-type:application/json'
要查看您刚刚上传的模型,请在浏览器中打开以下 URL
https://127.0.0.1:8983/solr/techproducts/schema/model-store
{
"class" : "org.apache.solr.ltr.model.LinearModel",
"name" : "myModel",
"features" : [
{ "name" : "documentRecency" },
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"weights" : {
"documentRecency" : 1.0,
"isBook" : 0.1,
"originalScore" : 0.5
}
}
}
运行重排序查询
要对查询结果进行重排序,请将 rq
参数添加到您的搜索中,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModel reRankDocs=100}&fl=id,score
添加 rq
参数不会更改搜索的输出。
要获取在重排序期间计算的特征值,请将 [features]
添加到 fl
参数,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModel reRankDocs=100}&fl=id,score,[features]
输出将包含特征值作为逗号分隔的列表,类似于此处显示的输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features]",
"rq":"{!ltr model=myModel reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"documentRecency=0.020893792,isBook=0.0,originalScore=1.959392"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"documentRecency=0.020893792,isBook=0.0,originalScore=1.5513437"}]
}}
运行重排序查询和查询限制
如果在重排序时超出查询限制,则会中止并完全还原重新评分。
返回原始排名列表,并在响应头中标记 'partialResults'。有关超出限制的详细信息,将在响应头 'partialResultsDetails' 中返回。
请参阅 部分结果参数,了解如何处理部分结果的更多详细信息。
运行交叉两个模型的重新排名查询
要重新排名查询结果,交叉两个模型(myModelA、myModelB),请在搜索中添加 rq
参数,并传入两个模型作为输入,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModelA model=myModelB reRankDocs=100}&fl=id,score
要获取在重新排名期间计算的、交叉选择的搜索结果模型,请将 [interleaving]
添加到 fl
参数,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModelA model=myModelB reRankDocs=100}&fl=id,score,[interleaving]
输出将包括为每个搜索结果选择的模型,类似于此处显示的输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[interleaving]",
"rq":"{!ltr model=myModelA model=myModelB reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[interleaving]":"myModelB"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[interleaving]":"myModelA"}]
}}
运行交叉模型与原始排名的重新排名查询
在使用交叉进行搜索质量评估时,将模型与原始排名进行比较可能很有用。要重新排名查询结果,交叉模型与原始排名,请在搜索中添加 rq
参数,并传入特殊的内置 OriginalRanking
模型标识符作为一个模型,以及你的比较模型作为另一个模型,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=_OriginalRanking_ model=myModel reRankDocs=100}&fl=id,score
添加 rq
参数不会更改搜索的输出。
要获取在重新排名期间计算的、交叉选择的搜索结果模型,请将 [interleaving]
添加到 fl
参数,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=_OriginalRanking_ model=myModel reRankDocs=100}&fl=id,score,[interleaving]
输出将包括为每个搜索结果选择的模型,类似于此处显示的输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features]",
"rq":"{!ltr model=_OriginalRanking_ model=myModel reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[interleaving]":"_OriginalRanking_"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[interleaving]":"myModel"}]
}}
运行交叉传递特定算法的重新排名查询
要重新排名查询结果,使用特定算法交叉两个模型,请将 interleavingAlgorithm
本地参数添加到 ltr 查询解析器,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModelA model=myModelB reRankDocs=100 interleavingAlgorithm=TeamDraft}&fl=id,score
目前,唯一支持的(也是默认的)算法是 'TeamDraft'。
外部特征信息
ValueFeature 和 SolrFeature 类支持使用外部特征信息,简称 efi
。
上传特征
要在 /path/myEfiFeatures.json
文件中上传特征,请运行
curl -XPUT 'https://127.0.0.1:8983/solr/techproducts/schema/feature-store' --data-binary "@/path/myEfiFeatures.json" -H 'Content-type:application/json'
要查看您刚刚上传的特征,请在浏览器中打开以下 URL
https://127.0.0.1:8983/solr/techproducts/schema/feature-store/myEfiFeatureStore
[
{
"store" : "myEfiFeatureStore",
"name" : "isPreferredManufacturer",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : { "fq" : [ "{!field f=manu}${preferredManufacturer}" ] }
},
{
"store" : "myEfiFeatureStore",
"name" : "userAnswerValue",
"class" : "org.apache.solr.ltr.feature.ValueFeature",
"params" : { "value" : "${answer:42}" }
},
{
"store" : "myEfiFeatureStore",
"name" : "userFromMobileValue",
"class" : "org.apache.solr.ltr.feature.ValueFeature",
"params" : { "value" : "${fromMobile}", "required" : true }
},
{
"store" : "myEfiFeatureStore",
"name" : "userTextCat",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : { "q" : "{!field f=cat}${text}" }
}
]
日志特征
要将 myEfiFeatureStore
特征作为查询的一部分记录,请将 efi.*
参数添加到 fl
参数的 [features]
部分,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,cat,manu,score,[features store=myEfiFeatureStore efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=1]
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,cat,manu,score,[features store=myEfiFeatureStore efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=0 efi.answer=13]
上传模型
要在 /path/myEfiModel.json
文件中上传模型,请运行
curl -XPUT 'https://127.0.0.1:8983/solr/techproducts/schema/model-store' --data-binary "@/path/myEfiModel.json" -H 'Content-type:application/json'
要查看您刚刚上传的模型,请在浏览器中打开以下 URL
https://127.0.0.1:8983/solr/techproducts/schema/model-store
{
"store" : "myEfiFeatureStore",
"name" : "myEfiModel",
"class" : "org.apache.solr.ltr.model.LinearModel",
"features" : [
{ "name" : "isPreferredManufacturer" },
{ "name" : "userAnswerValue" },
{ "name" : "userFromMobileValue" },
{ "name" : "userTextCat" }
],
"params" : {
"weights" : {
"isPreferredManufacturer" : 0.2,
"userAnswerValue" : 1.0,
"userFromMobileValue" : 1.0,
"userTextCat" : 0.1
}
}
}
运行重新排名查询
要获取在重新排名期间计算的特征值,请将 [features]
添加到 fl
参数,并将 efi.*
参数添加到 rq
参数,例如
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myEfiModel efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=1}&fl=id,cat,manu,score,[features]
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myEfiModel efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=0 efi.answer=13}&fl=id,cat,manu,score,[features]
请注意,fl
参数的 [features]
部分中没有 efi.*
参数。
重新排名时记录特征
要在使用 myModel
重新排名时仍然记录 myEfiFeatureStore
特征的特征
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=myModel}&fl=id,cat,manu,score,[features store=myEfiFeatureStore efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=1]
请注意,rq
参数中没有 efi.*
参数(因为 myModel
不使用 efi
特征),而 fl
参数的 [features]
部分中存在 efi.*
参数(因为 myEfiFeatureStore
包含 efi
特征)。
训练示例
示例训练数据和一个演示 train_and_upload_demo_model.py
脚本可以在 Apache Solr Git 存储库(镜像在 github.com 上)的 solr/modules/ltr/example
文件夹中找到。此示例文件夹未在 Solr 二进制版本中提供。
高级选项
LTRThreadModule
可以为查询解析器和/或转换器配置线程模块,以并行化特征权重的创建。有关详细信息,请参阅 LTRThreadModule 的 javadoc。
模型处理特征的空值
此功能仅适用于 MultipleAdditiveTreesModel。
在某些情况下,特征的空值与零值具有不同的含义。有些模型经过训练可以区分两者(例如,https://xgboost.readthedocs.io/en/stable/faq.html#how-to-deal-with-missing-values),在 Solr 中引入了额外的 missing
分支参数来支持此功能。
这定义了当相应的特征值为 null 时要遵循的分支。使用默认配置时,空值和零值具有相同的含义。
要处理空值,需要修改 myFeatures.json
文件。需要将具有 NaN
值的 defaultValue
参数添加到每个可以采用空值的特征。
[
{
"name": "matchedTitle",
"class": "org.apache.solr.ltr.feature.SolrFeature",
"params": {
"q": "{!terms f=title}${user_query}"
}
},
{
"name": "productReviewScore",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "product_review_score",
"defaultValue": "NaN"
}
}
]
此外,模型配置需要两个额外的参数
-
isNullSameAsZero
需要在模型params
中定义,并设置为false
; -
需要将
missing
参数添加到每个支持空值的相应特征的分支。这可以采用left
和right
之间的值之一。
{
"class":"org.apache.solr.ltr.model.MultipleAdditiveTreesModel",
"name":"multipleadditivetreesmodel",
"features":[
{ "name": "matchedTitle"},
{ "name": "productReviewScore"}
],
"params":{
"isNullSameAsZero": "false",
"trees": [
{
"weight" : "1f",
"root": {
"feature": "matchedTitle",
"threshold": "0.5f",
"left" : {
"value" : "-100"
},
"right": {
"feature" : "productReviewScore",
"threshold": "0f",
"missing": "left",
"left" : {
"value" : "50"
},
"right" : {
"value" : "65"
}
}
}
}
]
}
}
当模型的 isNullSameAsZero
为 false
时,特征向量会发生变化。
-
密集格式:显示所有特征值,也显示可以是零值或空值的默认值。
-
稀疏格式:仅显示非默认值。
例如
给定之前定义的特征;如果它们的值是 matchedTitle=0
和 productReviewScore=0
,则稀疏格式将返回 productReviewScore:0
(0 是 matchedTitle=0
的默认值,因此不返回,0 不是 productReviewScore=0
的默认值,因此返回)。
实现和贡献
- Solr 学习排序是如何在底层工作的?
-
有关实现的概述,请参阅
ltr
javadocs。 - 我如何编写其他模型和/或特征?
-
欢迎贡献更多模型、特征、归一化器和交叉算法。相关链接
LTR 示例
一个特征存储,多个排名模型
-
leftModel
和rightModel
都使用commonFeatureStore
中的特征,这两个模型之间唯一的区别是附加到每个特征的权重。 -
使用的约定
-
commonFeatureStore.json
文件包含commonFeatureStore
特征存储的特征 -
leftModel.json
文件包含名为leftModel
的模型 -
rightModel.json
文件包含名为rightModel
的模型 -
模型的特征和权重按名称字母顺序排序,这使得很容易看到两个模型之间的共同点和差异。
-
存储的特征按名称字母顺序排序,这使得很容易查找模型中使用的特征
-
[
{
"store" : "commonFeatureStore",
"name" : "documentRecency",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"q" : "{!func}recip( ms(NOW,last_modified), 3.16e-11, 1, 1)"
}
},
{
"store" : "commonFeatureStore",
"name" : "isBook",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"fq": [ "{!terms f=category}book" ]
}
},
{
"store" : "commonFeatureStore",
"name" : "originalScore",
"class" : "org.apache.solr.ltr.feature.OriginalScoreFeature",
"params" : {}
}
]
{
"store" : "commonFeatureStore",
"name" : "leftModel",
"class" : "org.apache.solr.ltr.model.LinearModel",
"features" : [
{ "name" : "documentRecency" },
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"weights" : {
"documentRecency" : 0.1,
"isBook" : 1.0,
"originalScore" : 0.5
}
}
}
{
"store" : "commonFeatureStore",
"name" : "rightModel",
"class" : "org.apache.solr.ltr.model.LinearModel",
"features" : [
{ "name" : "documentRecency" },
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"weights" : {
"documentRecency" : 1.0,
"isBook" : 0.1,
"originalScore" : 0.5
}
}
}
模型演变
-
linearModel201701
使用featureStore201701
中的特征 -
treesModel201702
使用featureStore201702
中的特征 -
linearModel201701
和treesModel201702
及其特征存储可以在两者都需要时共存。 -
当
linearModel201701
被删除后,也可以删除featureStore201701
。 -
使用的约定
-
<store>.json
文件包含<store>
特征存储的特征 -
<model>.json
文件包含模型名称<model>
-
“生成” ID(例如,
YYYYMM
年月)是特征存储和模型名称的一部分 -
模型的特征和权重按名称字母顺序排序,这使得很容易看到两个模型之间的共同点和差异。
-
存储的特征按名称字母顺序排序,这使得很容易看到两个特征存储之间的共同点和差异。
-
[
{
"store" : "featureStore201701",
"name" : "documentRecency",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"q" : "{!func}recip( ms(NOW,last_modified), 3.16e-11, 1, 1)"
}
},
{
"store" : "featureStore201701",
"name" : "isBook",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"fq": [ "{!terms f=category}book" ]
}
},
{
"store" : "featureStore201701",
"name" : "originalScore",
"class" : "org.apache.solr.ltr.feature.OriginalScoreFeature",
"params" : {}
}
]
{
"store" : "featureStore201701",
"name" : "linearModel201701",
"class" : "org.apache.solr.ltr.model.LinearModel",
"features" : [
{ "name" : "documentRecency" },
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"weights" : {
"documentRecency" : 0.1,
"isBook" : 1.0,
"originalScore" : 0.5
}
}
}
[
{
"store" : "featureStore201702",
"name" : "isBook",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"fq": [ "{!terms f=category}book" ]
}
},
{
"store" : "featureStore201702",
"name" : "originalScore",
"class" : "org.apache.solr.ltr.feature.OriginalScoreFeature",
"params" : {}
}
]
{
"store" : "featureStore201702",
"name" : "treesModel201702",
"class" : "org.apache.solr.ltr.model.MultipleAdditiveTreesModel",
"features" : [
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"trees" : [
{
"weight" : "1",
"root" : {
"feature" : "isBook",
"threshold" : "0.5",
"left" : { "value" : "-100" },
"right" : {
"feature" : "originalScore",
"threshold" : "10.0",
"left" : { "value" : "50" },
"right" : { "value" : "75" }
}
}
},
{
"weight" : "2",
"root" : {
"value" : "-10"
}
}
]
}
}
特征日志
logAll 参数
假设有一个完整的特征存储,如下所示
[
{
"store" : "completeFeaturesStore",
"name" : "documentRecency",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"q" : "{!func}recip( ms(NOW,last_modified), 3.16e-11, 1, 1)"
}
},
{
"store" : "completeFeaturesStore",
"name" : "isBook",
"class" : "org.apache.solr.ltr.feature.SolrFeature",
"params" : {
"fq": ["{!terms f=cat}book"]
}
},
{
"store" : "completeFeaturesStore",
"name" : "originalScore",
"class" : "org.apache.solr.ltr.feature.OriginalScoreFeature",
"params" : {}
}
]
假设有一个简单的线性模型,只使用 completeFeaturesStore
的两个特征
{
"store" : "completeFeaturesStore",
"name" : "linearModel",
"class" : "org.apache.solr.ltr.model.LinearModel",
"features" : [
{ "name" : "isBook" },
{ "name" : "originalScore" }
],
"params" : {
"weights" : {
"isBook" : 1.0,
"originalScore" : 0.5
}
}
}
进行日志记录 + 重新排名查询而不定义 store
和 logAll
参数将仅打印模型特征(默认:store=模型存储
和 logAll=false
)。
查询
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=linearModel reRankDocs=100}&fl=id,score,[features]
输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features]",
"rq":"{!ltr model=linearModel reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"isBook=0.0,originalScore=1.959392"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"isBook=0.0,originalScore=1.5513437"}]
}}
进行日志记录 + 重新排名查询而不定义 store
参数并将 logAll = true
将打印模型存储中的所有特征。
查询
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=linearModel reRankDocs=100}&fl=id,score,[features logAll=true]
输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features logAll=true]",
"rq":"{!ltr model=linearModel reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"documentRecency=0.020893792,isBook=0.0,originalScore=1.959392"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"documentRecency=0.020893792,isBook=0.0,originalScore=1.5513437"}]
}}
假设有一个不同的特征存储,如下所示
[
{
"store": "differentFeaturesStore",
"name": "valueFeature1",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "field1"
}
},
{
"store": "differentFeaturesStore",
"name": "valueFeature2",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "field2"
}
}
]
进行日志记录 + 重新排名查询,定义一个与模型存储不同的 store
参数而不定义 logAll
参数,将打印所选特征存储中的所有特征(默认:logAll=true
)。
查询
https://127.0.0.1:8983/solr/techproducts/query?q=test&rq={!ltr model=linearModel reRankDocs=100}&fl=id,score,[features store=differentFeaturesStore]
输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features store=differentFeaturesStore]",
"rq":"{!ltr model=linearModel reRankDocs=100}"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"valueFeature1=0.1,valueFeature2=2.0"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"valueFeature1=1.3,valueFeature2=4.0"}]
}}
format 参数
假设有一个特征存储,如下所示
[
{
"store": "myFeaturesStore",
"name": "featureA",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "field1"
}
},
{
"store": "myFeaturesStore",
"name": "featureB",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "field2"
}
},
{
"store": "myFeaturesStore",
"name": "featureC",
"class": "org.apache.solr.ltr.feature.FieldValueFeature",
"params": {
"field": "field3"
}
}
]
要返回密集的 CSV 值,例如:featureA=0.1,featureB=0.2,featureC=0.0
,请将 format=dense
参数传递给特征记录器转换器
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,score,[features store=myFeaturesStore format=dense]
输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features store=myFeaturesStore format=dense]"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"featureA=0.1,featureB=0.2,featureC=0.0"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"featureA=1.3,featureB=0.0,featureC=2.1"}]
}}
要返回稀疏的 CSV 值,例如:featureA=0.1,featureB=0.2
,请将 format=sparse
参数传递给特征记录器转换器
https://127.0.0.1:8983/solr/techproducts/query?q=test&fl=id,score,[features store=myFeaturesStore format=sparse]
输出
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"test",
"fl":"id,score,[features store=myFeaturesStore format=sparse]"}},
"response":{"numFound":2,"start":0,"maxScore":1.0005897,"docs":[
{
"id":"GB18030TEST",
"score":1.0005897,
"[features]":"featureA=0.1,featureB=0.2"},
{
"id":"UTF8TEST",
"score":0.79656565,
"[features]":"featureA=1.3,featureC=2.1"}]
}}