学习排序

使用学习排序(简称 LTR)模块,您可以在 Solr 中配置和运行机器学习排序模型。

该模块还支持在 Solr 内部进行特征日志记录。您在 Solr 外部唯一需要做的就是训练您自己的排序模型。

学习排序概念

重排名

重排名允许您运行一个简单的查询来匹配文档,然后使用来自另一个更复杂的查询的分数对前 N 个文档进行重排名。此页面描述了 LTR 复杂查询的使用,有关 Solr 发行版中包含的其他排名查询的信息,请参见查询重排名

学习排序模型

在信息检索系统中,学习排序用于使用训练过的机器学习模型对检索到的前 N 个文档进行重排名。我们希望这种复杂的模型可以做出比诸如 TF-IDFBM25 等标准排名函数更细致的排名决策。

排名模型

排名模型计算用于对文档进行重排名的分数。无论任何特定的算法或实现如何,排名模型的计算可以使用三种类型的输入

  • 表示评分算法的参数

  • 表示正在评分的文档的特征

  • 表示正在为文档评分的查询的特征

交错

交错是一种在线搜索质量评估方法,允许比较两个模型,将它们的结果交错在返回给用户的最终排名列表中。

  • 目前仅支持团队草案交错算法(并且其实现假设所有结果都来自同一分片)

特征

特征是一个值或数字,它表示正在评分的文档或正在评分的查询的某种数量或质量。例如,文档通常具有“新近度”质量,而“过去购买次数”可能是一个作为搜索查询的一部分传递给 Solr 的数量。

归一化器

一些排名模型期望特征在特定的尺度上。可以使用归一化器将任意特征值转换为归一化值,例如,在 0..1 或 0..100 的尺度上。

训练模型

特征工程

LTR 模块包括几个特征类,并支持自定义特征。每个特征类的 javadoc 都包含一个示例来说明该类的使用。 特征工程本身的过程完全取决于您的领域专业知识和创造力。

特征 示例参数 外部特征信息

字段长度

FieldLengthFeature

{"field":"title"}

(尚未)支持

字段值

FieldValueFeature

{"field":"hits"}

(尚未)支持

原始分数

OriginalScoreFeature

{}

不适用

Solr 查询

SolrFeature

{"q":"{!func} recip(ms(NOW,last_modified) ,3.16e-11,1,1)"}

支持

Solr 过滤器查询

SolrFeature

{"fq":["{!terms f=category}book"]}

支持

Solr 查询 + 过滤器查询

SolrFeature

{"q":"{!func} recip(ms(NOW,last_modified), 3.16e-11,1,1)", "fq":["{!terms f=category}book"]}

支持

ValueFeature

{"value":"${userFromMobile}","required":true}

支持

(自定义)

(扩展 Feature 的自定义类)

归一化器 示例参数

恒等

IdentityNormalizer

{}

最小-最大

MinMaxNormalizer

{"min":"0", "max":"50" }

标准

StandardNormalizer

{"avg":"42","std":"6"}

(自定义)

(扩展 Normalizer 的自定义类)

特征日志记录

ltr 模块包括一个 [features] 转换器,以支持计算和返回 特征提取 的特征值,特别是在您还没有实际的重排序模型时。

特征选择和模型训练

特征选择和模型训练在线下和 Solr 外部进行。 ltr 模块支持两种通用形式的模型以及自定义模型。 每个模型类的 javadoc 都包含一个示例来说明该类的配置。 以 JSON 文件的形式,您训练的模型或模型(例如,不同客户地理位置的不同模型)可以使用提供的 REST API 直接上传到 Solr。

通用形式 具体示例

线性

LinearModel

RankSVM、Pranking

多重加性树

MultipleAdditiveTreesModel

LambdaMART、梯度提升回归树 (GBRT)

神经网络

NeuralNetworkModel

RankNet

(包装器)

DefaultWrapperModel

(不适用)

(自定义)

(扩展 AdapterModel 的自定义类)

(不适用)

(自定义)

(扩展 LTRScoringModel 的自定义类)

(不适用)

模块

这是通过 ltr Solr 模块提供的,该模块需要在使用前启用。

安装 LTR

ltr 模块需要 modules/ltr/lib/solr-ltr-*.jar JAR。

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]

在使用基于 currentFeatureStorecurrentModel 进行重排序时,记录 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_
示例:/path/myFeatures.json
[
  {
    "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

此参数指定用于记录特征的格式。 支持的值为:densesparse

您可以将默认行为更改为 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
示例:/path/myModel.json
{
  "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"}]
  }}

运行重排序查询和查询限制

Apache Solr 允许定义查询限制以中断特别昂贵的查询(允许的时间允许的 CPU)。

如果在重排序时超出查询限制,则会中止并完全还原重新评分。

返回原始排名列表,并在响应头中标记 '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'。

外部特征信息

ValueFeatureSolrFeature 类支持使用外部特征信息,简称 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
示例:/path/myEfiFeatures.json
[
  {
    "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
示例:/path/myEfiModel.json
{
  "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 参数添加到每个可以采用空值的特征。

示例:/path/myFeatures.json
[
  {
    "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 参数添加到每个支持空值的相应特征的分支。这可以采用 leftright 之间的值之一。

示例:/path/myModel.json
{
  "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"
            }
          }
        }
      }
    ]
  }
}

当模型的 isNullSameAsZerofalse 时,特征向量会发生变化。

  • 密集格式:显示所有特征值,也显示可以是零值或空值的默认值。

  • 稀疏格式:仅显示非默认值。

例如

给定之前定义的特征;如果它们的值是 matchedTitle=0productReviewScore=0,则稀疏格式将返回 productReviewScore:0 (0 是 matchedTitle=0 的默认值,因此不返回,0 不是 productReviewScore=0 的默认值,因此返回)。

实现和贡献

Solr 学习排序是如何在底层工作的?

有关实现的概述,请参阅 ltr javadocs

我如何编写其他模型和/或特征?

欢迎贡献更多模型、特征、归一化器和交叉算法。相关链接

LTR 示例

一个特征存储,多个排名模型

  • leftModelrightModel 都使用 commonFeatureStore 中的特征,这两个模型之间唯一的区别是附加到每个特征的权重。

  • 使用的约定

    • commonFeatureStore.json 文件包含 commonFeatureStore 特征存储的特征

    • leftModel.json 文件包含名为 leftModel 的模型

    • rightModel.json 文件包含名为 rightModel 的模型

    • 模型的特征和权重按名称字母顺序排序,这使得很容易看到两个模型之间的共同点和差异。

    • 存储的特征按名称字母顺序排序,这使得很容易查找模型中使用的特征

示例:/path/commonFeatureStore.json
[
  {
    "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" : {}
  }
]
示例:/path/leftModel.json
{
  "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
    }
  }
}
示例:/path/rightModel.json
{
  "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 中的特征

  • linearModel201701treesModel201702 及其特征存储可以在两者都需要时共存。

  • linearModel201701 被删除后,也可以删除 featureStore201701

  • 使用的约定

    • <store>.json 文件包含 <store> 特征存储的特征

    • <model>.json 文件包含模型名称 <model>

    • “生成” ID(例如,YYYYMM 年月)是特征存储和模型名称的一部分

    • 模型的特征和权重按名称字母顺序排序,这使得很容易看到两个模型之间的共同点和差异。

    • 存储的特征按名称字母顺序排序,这使得很容易看到两个特征存储之间的共同点和差异。

示例:/path/featureStore201701.json
[
  {
    "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" : {}
  }
]
示例:/path/linearModel201701.json
{
  "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
    }
  }
}
示例:/path/featureStore201702.json
[
  {
    "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" : {}
  }
]
示例:/path/treesModel201702.json
{
  "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 参数

假设有一个完整的特征存储,如下所示

示例:/path/completeFeaturesStore.json
[
  {
    "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 的两个特征

示例:/path/linearModel.json
{
  "store" : "completeFeaturesStore",
  "name" : "linearModel",
  "class" : "org.apache.solr.ltr.model.LinearModel",
  "features" : [
    { "name" : "isBook" },
    { "name" : "originalScore" }
  ],
  "params" : {
    "weights" : {
      "isBook" : 1.0,
      "originalScore" : 0.5
    }
  }
}

进行日志记录 + 重新排名查询而不定义 storelogAll 参数将仅打印模型特征(默认: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"}]
  }}

假设有一个不同的特征存储,如下所示

示例:/path/differentFeaturesStore.json
[
  {
    "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 参数

假设有一个特征存储,如下所示

示例:/path/myFeaturesStore.json
[
  {
    "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"}]
  }}