Learning To Rank

Learning To Rank(略してLTR)モジュールを使用すると、Solrで機械学習ランキングモデルを構成して実行できます。

このモジュールは、Solr内部での特徴量ロギングもサポートしています。Solrの外部で行う必要があるのは、独自のランキングモデルをトレーニングすることだけです。

Learning to Rankの概念

再ランキング

再ランキングを使用すると、マッチングドキュメントの単純なクエリを実行し、別の、より複雑なクエリからのスコアを使用して上位N個のドキュメントを再ランキングできます。このページでは、LTRの複雑なクエリの使用について説明します。Solrディストリビューションに含まれる他のランククエリに関する情報は、クエリ再ランキングにあります。

Learning To Rankモデル

情報検索システムでは、Learning to Rankは、トレーニング済みの機械学習モデルを使用して、取得した上位N個のドキュメントを再ランキングするために使用されます。そのような高度なモデルは、TF-IDFBM25などの標準的なランキング関数よりも、よりニュアンスのあるランキング決定を行うことができると期待されています。

ランキングモデル

ランキングモデルは、ドキュメントを再ランキングするために使用されるスコアを計算します。特定のアルゴリズムや実装に関係なく、ランキングモデルの計算では、次の3種類の入力を使用できます。

  • スコアリングアルゴリズムを表すパラメーター

  • スコアリングされるドキュメントを表す特徴

  • ドキュメントがスコアリングされているクエリを表す特徴

インターリーブ

インターリーブは、オンライン検索品質評価のアプローチであり、ユーザーに返される最終的なランク付けされたリストで結果をインターリーブすることにより、2つのモデルを比較できます。

  • 現在、Team Draft Interleavingアルゴリズムのみがサポートされています(また、その実装はすべての結果が同じシャードからのものであると想定しています)

特徴

特徴とは、スコアリングされるドキュメント、またはドキュメントがスコアリングされているクエリの量や質を表す数値である値です。たとえば、ドキュメントには「新規性」という品質があることが多く、「過去の購入数」は検索クエリの一部として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を拡張するカスタムクラス)

正規化器 クラス パラメーターの例

Identity

IdentityNormalizer

{}

MinMax

MinMaxNormalizer

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

Standard

StandardNormalizer

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

(カスタム)

(Normalizer を拡張するカスタムクラス)

フィーチャーロギング

ltr モジュールには、[features] トランスフォーマーが含まれており、特徴抽出の目的で、特に実際のランキングモデルをまだ持っていない場合に、フィーチャー値の計算と返却をサポートします。

フィーチャー選択とモデルトレーニング

フィーチャー選択とモデルトレーニングは、Solr の外部でオフラインで行われます。ltr モジュールは、カスタムモデルだけでなく、2 つの一般的な形式のモデルをサポートしています。各モデルクラスの 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

モデル

  • モデルは、1 つのフィーチャーストアのフィーチャーのみを使用します。

  • ストアが指定されていない場合は、デフォルトの _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 は、モデル定義をアップロードされたファイルから分離するのに役立ちます。

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 を指定して使用できるようになります。

ラップされたモデル (myModel) のフィーチャーが使用されるため、myWrapperModel では "features" は構成されていません。また、ラッパーモデルに構成された "store" は、ラップされたモデルのストアと一致する必要があることにも注意してください。つまり、この例では largeModelsFeatureStore という名前のフィーチャーストアが使用されています。
<lib dir="/path/to/models" regex=".*\.json" /> は、この場合は期待どおりに機能しません。<lib /> がファイルを示している場合、SolrResourceLoader は指定されたリソースを JAR と見なすためです。

上記の DefaultWrapperModel の代わりに、ZooKeeper のファイルサイズ制限を増やすことも可能です。

変更の適用

フィーチャーストアとモデルストアはどちらもマネージドリソースです。マネージドリソースに加えられた変更は、Solr コレクション(またはシングルサーバーモードの場合は Solr コア)がリロードされるまで、アクティブな Solr コンポーネントには適用されません。

LTR のクイックスタート

Solr に付属している "techproducts" の例は、ltr Solr モジュールから learning-to-rank に必要なプラグインをロードするように事前構成されていますが、デフォルトでは無効になっています。

プラグインを有効にするには、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" : {}
  }
]

フィーチャーのロギング

クエリの一部としてフィーチャーをログに記録するには、fl パラメータに [features] を追加します。例:

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 の例セクションにあります。

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 '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 パラメータを追加しても、検索の出力は変更されません。

再ランキング中に計算されたフィーチャー値を取得するには、fl パラメータに [features] を追加します。例:

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"}]
  }}

2 つのモデルをインターリーブする再ランキングクエリの実行

クエリの結果を再ランキングするには、2 つのモデル (myModelA、myModelB) をインターリーブします。検索に rq パラメータを追加し、入力に 2 つのモデルを渡します。例:

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 モデル識別子を 1 つのモデルとして、比較モデルをもう 1 つのモデルとして渡します。例:

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"}]
  }}

特定のアルゴリズムを渡してインターリーブを使用する再ランキングクエリの実行

特定のアルゴリズムを使用して 2 つのモデルをインターリーブすることにより、クエリの結果を再ランキングするには、ltr クエリパーサーに interleavingAlgorithm ローカルパラメータを追加します。例:

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
例: /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のフィーチャーをログに記録するには、flパラメータの[features]部分にefi.*パラメータを追加します。例:

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
    }
  }
}

リランククエリの実行

リランキング中に計算されたフィーチャー値を取得するには、flパラメータに[features]を追加し、rqパラメータにefi.*パラメータを追加します。例:

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.*パラメータがない(myModelefiフィーチャーを使用していないため)ことと、flパラメータの[features]部分にefi.*パラメータがある(myEfiFeatureStoreefiフィーチャーが含まれているため)ことに注意してください。

トレーニング例

トレーニングデータの例とデモのtrain_and_upload_demo_model.pyスクリプトは、Apache Solr Gitリポジトリgithub.comでミラーリングされています)のsolr/modules/ltr/exampleフォルダにあります。この例のフォルダは、Solrのバイナリリリースには同梱されていません。

高度なオプション

LTRThreadModule

フィーチャーの重みの生成を並列化するために、クエリパーサーやトランスフォーマーにスレッドモジュールを設定できます。詳細については、LTRThreadModuleのjavadocを参照してください。

フィーチャーのnull値を処理するモデル

この機能は、MultipleAdditiveTreesModelでのみ使用できます。

一部のシナリオでは、フィーチャーのnull値はゼロ値とは異なる意味を持ちます。2つを区別するようにトレーニングされたモデルがあります(例: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"
    }
  }
]

また、モデル構成には2つの追加パラメータが必要です。

  • 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の場合、フィーチャーベクターが変化します。

  • dense形式:すべてのフィーチャー値が表示されます。ゼロまたはnull値の場合もあるデフォルト値も表示されます。

  • sparse形式:デフォルト値ではない値のみが表示されます。

例:

前に定義したフィーチャーがmatchedTitle=0productReviewScore=0である場合、sparse形式はproductReviewScore:0を返します(0はmatchedTitle=0のデフォルト値であるため返されず、0はproductReviewScore=0のデフォルト値ではないため返されます)。

実装と貢献

SolrのLearning-To-Rankはどのように機能しますか?

実装の概要については、ltrjavadocを参照してください。

追加のモデルやフィーチャーを記述するにはどうすればよいですか?

さらなるモデル、フィーチャー、ノーマライザー、インタリービングアルゴリズムの貢献を歓迎します。関連リンク

LTRの例

1つのフィーチャーストア、複数のランキングモデル

  • leftModelrightModelは両方ともcommonFeatureStoreのフィーチャーを使用しており、2つのモデルの違いは各フィーチャーに付加される重みだけです。

  • 使用される規則

    • commonFeatureStore.jsonファイルには、commonFeatureStoreフィーチャーストアのフィーチャーが含まれています。

    • leftModel.jsonファイルには、leftModelという名前のモデルが含まれています。

    • rightModel.jsonファイルには、rightModelという名前のモデルが含まれています。

    • モデルのフィーチャーと重みは名前でアルファベット順にソートされているため、2つのモデルの共通点と相違点を簡単に確認できます。

    • ストアのフィーチャーは名前でアルファベット順にソートされているため、モデルで使用されるフィーチャーを簡単に検索できます。

例: /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
    }
  }
}

モデルの進化

  • linearModel201701featureStore201701のフィーチャーを使用します。

  • treesModel201702featureStore201702のフィーチャーを使用します。

  • linearModel201701treesModel201702、およびそれらのフィーチャーストアは、両方が必要な場合、共存できます。

  • linearModel201701が削除されたら、featureStore201701も削除できます。

  • 使用される規則

    • <store>.jsonファイルには、<store>フィーチャーストアのフィーチャーが含まれています。

    • <model>.jsonファイルには、<model>というモデル名が含まれています。

    • 「世代」ID(例:YYYYMM年-月)は、フィーチャーストア名とモデル名の一部です。

    • モデルのフィーチャーと重みは名前でアルファベット順にソートされているため、2つのモデルの共通点と相違点を簡単に確認できます。

    • ストアのフィーチャーは名前でアルファベット順にソートされているため、2つのフィーチャーストアの共通点と相違点を簡単に確認できます。

例: /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のフィーチャーのうち2つだけを使用する単純な線形モデルがあるとします。

例: /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)。

クエリ

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"
    }
  }
]

logAllパラメータを定義せずに、モデルストアとは異なるstoreパラメータを定義してロギング+リランキングクエリを実行すると、選択されたフィーチャーストアのすべてのフィーチャーが出力されます(デフォルト: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"
    }
  }
]

featureA=0.1,featureB=0.2,featureC=0.0のようなdense CSV値を返すには、フィーチャーロガートランスフォーマーに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"}]
  }}

featureA=0.1,featureB=0.2のようなsparse CSV値を返すには、フィーチャーロガートランスフォーマーに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"}]
  }}

LTRの追加リソース