学习排序

使用学习排名(或简称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 配置

学习到排名是一个模块,因此其插件必须在 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_ 特征存储。

发现所有特征存储的名称

http://localhost:8983/solr/techproducts/schema/feature-store

检查 commonFeatureStore 特征存储的内容

http://localhost:8983/solr/techproducts/schema/feature-store/commonFeatureStore

模型

  • 模型使用来自一个特征存储的特征。

  • 如果没有指定存储,则将使用默认 _DEFAULT_ 特征存储。

  • 模型不必使用特征存储中定义的所有特征。

  • 多个模型可以使用相同的特征存储。

记录 currentFeatureStore 的特征

http://localhost:8983/solr/techproducts/query?q=test&fl=id,score,[features store=currentFeatureStore]

在使用 currentModel 根据 currentFeatureStore 重新排序时,记录 nextFeatureStore 特征

http://localhost:8983/solr/techproducts/query?q=test&rq={!ltr model=currentModel reRankDocs=100}&fl=id,score,[features store=nextFeatureStore]

查看所有模型

http://localhost:8983/solr/techproducts/schema/model-store

删除 currentModel 模型

curl -XDELETE 'http://localhost:8983/solr/techproducts/schema/model-store/currentModel'
只有在没有模型使用特征存储时才能删除特征存储。

删除 currentFeatureStore 特征存储

curl -XDELETE 'http://localhost:8983/solr/techproducts/schema/feature-store/currentFeatureStore'

使用大模型

对于 SolrCloud,由于 ZooKeeper 缓冲区的限制,大模型可能无法上传。在这种情况下,DefaultWrapperModel 可以帮助你将模型定义与上传的文件分离开来。

假设你考虑通过 DefaultWrapperModel 使用位于 /path/to/models/myModel.json 的大模型。

{
  "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 'http://localhost:8983/solr/techproducts/schema/feature-store' --data-binary "@/path/myFeatures.json" -H 'Content-type:application/json'

要查看刚上传的特征,请在浏览器中打开以下 URL

http://localhost: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 参数,例如

http://localhost: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 示例 部分中找到有关如何使用它们的示例。

store

不重新排序

可选

默认值:_DEFAULT_

重新排序

可选

默认值:模型特征存储

此参数指定用于记录特征的特征存储。

在重新排序查询中,使用的默认特征存储是模型特征存储(例如 [features])。

logAll

不重新排序

默认值:true

重新排序

记录器和模型具有相同的特征存储

默认值:false

重新排序

记录器和模型具有不同的特征存储

默认值:true

此参数指定要记录的特征。

如果设置为 true,则会打印特征存储中的所有特征。

如果设置为 false,则只会打印模型使用的特征。

如果没有传递重新排序查询,则只支持 logAll = 'true'。传递 false 将导致 Solr 异常。
在传递重新排序查询的记录场景中,如果记录器 store 与模型 store 不同,则只支持 logAll = 'true'。传递 false 将导致 Solr 异常。
format

可选

默认值:dense

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

您可以将默认行为更改为稀疏,在 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 'http://localhost:8983/solr/techproducts/schema/model-store' --data-binary "@/path/myModel.json" -H 'Content-type:application/json'

要查看您刚刚上传的模型,请在浏览器中打开以下 URL

http://localhost: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 参数添加到您的搜索中,例如

http://localhost:8983/solr/techproducts/query?q=test&rq={!ltr model=myModel reRankDocs=100}&fl=id,score

添加 rq 参数不会更改搜索的输出。

要获取重新排序期间计算的特征值,请将 [features] 添加到 fl 参数,例如

http://localhost: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"}]
  }}

运行重新排序查询,交错两个模型

要重新排序查询的结果,交错两个模型 (myModelA, myModelB),请将 rq 参数添加到您的搜索中,在输入中传递两个模型,例如

http://localhost:8983/solr/techproducts/query?q=test&rq={!ltr model=myModelA model=myModelB reRankDocs=100}&fl=id,score

要获取交错在重新排序期间为搜索结果挑选的模型,请将 [interleaving] 添加到 fl 参数,例如

http://localhost: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 模型标识符作为一种模型传递,并将比较模型作为另一种模型传递,例如

http://localhost:8983/solr/techproducts/query?q=test&rq={!ltr model=_OriginalRanking_ model=myModel reRankDocs=100}&fl=id,score

添加 rq 参数不会更改搜索的输出。

要获取交错在重新排序期间为搜索结果挑选的模型,请将 [interleaving] 添加到 fl 参数,例如

http://localhost: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 查询解析器,例如

http://localhost: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 'http://localhost:8983/solr/techproducts/schema/feature-store' --data-binary "@/path/myEfiFeatures.json" -H 'Content-type:application/json'

要查看刚上传的特征,请在浏览器中打开以下 URL

http://localhost: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] 部分,例如

http://localhost:8983/solr/techproducts/query?q=test&fl=id,cat,manu,score,[features store=myEfiFeatureStore efi.text=test efi.preferredManufacturer=Apache efi.fromMobile=1]
http://localhost: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 'http://localhost:8983/solr/techproducts/schema/model-store' --data-binary "@/path/myEfiModel.json" -H 'Content-type:application/json'

要查看您刚刚上传的模型,请在浏览器中打开以下 URL

http://localhost: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 参数,例如

http://localhost: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]
http://localhost: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 特征

http://localhost: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 时,这定义要遵循的分支。使用默认配置,null 值和零值具有相同的含义。

要处理空值,需要修改 myFeatures.json 文件。需要向每个可能采用空值的特征添加一个 defaultValue 参数,其值设为 NaN

示例:/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 Learning-To-Rank 在底层如何工作?

有关实现概述,请参阅 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
    }
  }
}

在未定义 `store` 和 `logAll` 参数的情况下进行日志记录 + 重新排序查询将仅打印模型特征(默认值:`store=model store` 和 `logAll=false`)。

查询

http://localhost: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` 的情况下进行日志记录 + 重新排序查询将打印模型存储中的所有特征。

查询

http://localhost: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"
    }
  }
]

在未定义 `logAll` 参数的情况下,定义一个不同于模型存储的 `store` 参数并进行日志记录 + 重新排序查询将打印所选特征存储中的所有特征(默认值:`logAll=true`)。

查询

http://localhost: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` 参数传递给特征记录器转换器

http://localhost: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` 参数传递给特征记录器转换器

http://localhost: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"}]
  }}