學習排序

使用 學習排序 (簡稱 LTR) 模組,您可以在 Solr 中設定並執行機器學習排序模型。

此模組也支援在 Solr 內記錄功能。您唯一需要在 Solr 外部執行的操作是訓練您自己的排序模型。

學習排序概念

重新排序

重新排序允許您執行簡單的查詢以比對文件,然後使用來自另一個更複雜的查詢的分數來重新排序前 N 個文件。此頁面說明 LTR 複雜查詢的使用方式,關於 Solr 發行版本中包含的其他排序查詢的資訊,請參閱查詢重新排序

學習排序模型

在資訊檢索系統中,學習排序用於使用經過訓練的機器學習模型來重新排序前 N 個檢索到的文件。希望此類複雜的模型可以做出比標準排序函式 (如 TF-IDFBM25) 更細微的排序決策。

排序模型

排序模型會計算用於重新排序文件的分數。無論任何特定的演算法或實作,排序模型的計算可以使用三種輸入類型

  • 代表評分演算法的參數

  • 代表正在評分文件的功能

  • 代表正在評分文件之查詢的功能

交錯

交錯是一種線上搜尋品質評估方法,可讓您比較兩個模型,將其結果交錯於返回給使用者的最終排序清單中。

  • 目前僅支援團隊選拔交錯演算法 (且其實作假設所有結果都來自同一個分片)

特徵

特徵是一個數值,代表正在評分的文檔或正在為其評分文檔的查詢的某些數量或品質。例如,文檔通常具有「新近度」品質,而「過去購買次數」可能是一個作為搜尋查詢的一部分傳遞給 Solr 的數量。

正規化器

某些排名模型期望特徵位於特定的尺度上。正規化器可用於將任意特徵值轉換為正規化值,例如,在 0..1 或 0..100 的尺度上。

訓練模型

特徵工程

LTR 模組包含多個特徵類別,以及對自訂特徵的支援。每個特徵類別的 javadocs 都包含一個範例來說明該類別的使用。那麼,特徵工程本身的過程完全取決於您的領域專業知識和創造力。

特徵 類別 範例參數 外部特徵資訊

欄位長度

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 模組支援兩種通用形式的模型以及自訂模型。每個模型類別的 javadocs 都包含一個範例來說明該類別的配置。以 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 可以協助您將模型定義與上傳的檔案分開。

假設您考慮使用透過 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" 必須與包裝模型的特徵儲存相符,也就是說,在此範例中使用名為 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

您可以將預設行為變更為稀疏,將 <str name="defaultFormat">sparse</str> 放入 solrconfig.xml 中的 特徵記錄器轉換器宣告中,如下所示

<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)。

如果在重新排名時超過查詢限制,則會中止重新評分並完全還原。

原始的排名列表會被返回,且回應會標記 responseHeader 'partialResults'。超出限制的詳細資訊會在 responseHeader 'partialResultsDetails' 中返回。

請參閱 Partial Results Parameter 以取得更多關於如何處理部分結果的詳細資訊。

執行交錯兩個模型的重新排名查詢

若要重新排名查詢結果,並交錯兩個模型(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

若要取得重新排名時,交錯選擇用於搜尋結果的模型,請在 fl 參數中加入 [interleaving],例如:

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 參數不會變更搜尋的輸出。

若要取得重新排名時,交錯選擇用於搜尋結果的模型,請在 fl 參數中加入 [interleaving],例如:

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.* 參數。

在重新排名時記錄特徵

若要記錄 myEfiFeatureStore 的特徵,同時仍使用 myModel 重新排名:

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 javadocs。

模型處理特徵的空值

此功能僅適用於 MultipleAdditiveTreesModel

在某些情況下,特徵的空值與零值具有不同的含義。有些模型經過訓練以區分這兩者(例如,https://xgboost.readthedocs.io/en/stable/faq.html#how-to-deal-with-missing-values),在 Solr 中引入了一個額外的 missing 分支參數來支援此功能。

這定義了當相應的特徵值為 null 時要遵循的分支。在預設配置中,null 值和零值具有相同的含義。

若要處理 null 值,需要修改 myFeatures.json 檔案。需要為每個可以假設為 null 值的特徵添加具有 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 參數需要添加到每個分支,其中相應的特徵支援 null 值。它可以假設 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 時,特徵向量會發生變化。

  • 密集格式:顯示所有特徵值,也包括可以是零值或 null 值的預設值。

  • 稀疏格式:僅顯示非預設值。

例如:

假設之前定義的特徵;如果它們的值為 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
    }
  }
}

在未定義 storelogAll 參數的情況下進行記錄 + 重新排名查詢,將只會印出模型特徵(預設:store=model storelogAll=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"}]
  }}