1
/
5

【TECH BLOG】Elasticsearch LTRプラグインと特徴量キャッシュ機能の基本

はじめに

こんにちは、検索基盤部 検索研究ブロックの真鍋です。ヤフー株式会社から一部出向していて、主にZOZOTOWNの検索機能へのランキングモデルの導入に従事しています。

本記事では、Elasticsearch上でランキングモデルを扱うための有名なプラグインの仕組みと、同プラグインにZOZOが実装した機能を紹介します。

まず、本記事の背景を説明します。ZOZOTOWNでキーワード検索すると、結果の商品が並びます。結果の商品は非常に多数になることも多いので、ユーザ体験を損なわないためには、その並び順も重要です。ここで言うランキングモデルとは、この並び順の決定のために、商品のスコアを計算する式のことを指します。このような式は機械学習によって生成され、非常に複雑になることもあります。そのため、検索エンジンの標準機能では実行できず、プラグインを導入して初めて実行できることもあります。

ZOZOTOWNでは検索エンジンとしてElasticsearchを使用しています。そして、Elasticsearch上でランキングモデルを実行するために、OpenSource Connectionsが提供するLearning to Rank pluginを使用しています。以下、このプラグインを指して、単に本プラグインと呼びます。

GitHub - o19s/elasticsearch-learning-to-rank: Plugin to integrate Learning to Rank (aka machine learning for better relevance) with Elasticsearch
The Elasticsearch Learning to Rank plugin uses machine learning to improve search relevance ranking. It's powering search at places like Wikimedia Foundation and Snagajob!
https://github.com/o19s/elasticsearch-learning-to-rank


本記事の前半では、本プラグインの仕組みを説明します。まずランキングモデルを実行する仕組みを紹介し、次にランキングモデルを学習するための特徴量の値を出力する仕組みを紹介します。後半では、ZOZOが本プラグインに実装した、特徴量キャッシュの機能を紹介します。これは、ランキングモデルの実行と特徴量の値の出力を併用する際に、後者を効率化するための機能です。

具体的なコードとしては、本プラグインのバージョンv1.5.8-es7.16.2を例に説明します。

Release Release v1.5.8-es7.16.2 · o19s/elasticsearch-learning-to-rank
Version 1.5.8 Changes: - Fixes to JSON serialization in LoggingSearchExtBuilder (PR#394) - New caching option to improve performance when logging features alongside model execution (PR#397) You can't perform that action at this time. You signed in with an
https://github.com/o19s/elasticsearch-learning-to-rank/releases/tag/v1.5.8-es7.16.2


本記事では本プラグインの詳しい使い方は紹介しませんが、過去の記事で紹介しておりますので、ぜひ合わせてご覧ください。


Elasticsearch Learning to Rankプラグインの使い方とポイント - ZOZO TECH BLOG
検索基盤部の内田です。私たちは、約1年前よりヤフー株式会社と協力し、検索機能の改善に取り組んでいます。現在、ZOZOTOWNのおすすめ順検索に用いている、ランキング学習を利用した検索機能も、その取り組みの一部です。 本記事では、Elasticsearch上で、ランキング学習により構築した機械学習モデルを用いた検索を行うためのプラグイン「 Elasticsearch Learning to ...
https://techblog.zozo.com/entry/elasticsearch-learning-to-rank-plugin


ランキングモデルの実行の仕組み

まず、本プラグインでランキングモデルを実行する仕組みを紹介します。本プラグインでランキングモデルを実行するには、例えば以下のクエリをElasticsearchに送信します(本プラグインの公式ドキュメントより引用)。

{
    "query": {
        "match": {
            "_all": "rambo"
        }
    },
    "rescore": {
        "window_size": 1000,
        "query": {
            "rescore_query": {
                "sltr": {
                    "params": {
                        "keywords": "rambo"
                    },
                    "model": "my_model"
                }
            }
        }
    }
}

https://elasticsearch-learning-to-rank.readthedocs.io/en/latest/searching-with-your-model.html#rescore-top-n-with-sltr

このクエリでは、以下のことが指定されています。

  • クエリキーワードがrambo
  • 既存の検索結果の上位1,000件をランキングモデルで並べ替える
  • その際に使うランキングモデルの名前がmy_model

LtrQueryParserPluginによるクエリのパースと、RankerQueryオブジェクトの生成

例のクエリは、まず本プラグインのコードのうち LtrQueryParserPlugin に入力されます。LtrQueryParserPlugin はElasticsearch本体が提供するインタフェース SearchPlugin を実装しています。このため、LtrQueryParserPlugin はElasticsearch本体の SearchModule から見えるようになっています。

SearchModule はクエリの各要素(例のクエリで言うと matchsltr)をどのクラスにパースさせるかを管理しています。具体的には、組み込みのクラスのほか、各プラグインが SearchModule#getQueries で指定してくるクラスも考慮します。

LtrQueryParserPlugin#getQueries では、以下の通り sltr 要素を StoredLtrQueryBuilder にパースさせるという指定をしています。ただし、StoredLtrQueryBuilder.NAMEsltr であることに注意してください。この指定のため、次は本プラグイン独自の StoredLtrQueryBuilder に制御が移ります。

new QuerySpec<>(StoredLtrQueryBuilder.NAME,
        (input) -> new StoredLtrQueryBuilder(getFeatureStoreLoader(), input),
        (ctx) -> StoredLtrQueryBuilder.fromXContent(getFeatureStoreLoader(), ctx)),

https://github.com/o19s/elasticsearch-learning-to-rank/blob/37d8542c78b816c67a34fd206e6f4dc08ba7006f/src/main/java/com/o19s/es/ltr/LtrQueryParserPlugin.java#L144-L146

StoredLtrQueryBuilder

StoredLtrQueryBuilder はクエリのJSONをパースし、メモリ上の表現(後述の RankerQuery)をビルドするのに使います。ビルドのために、以下の主要なメンバーを持っています。

続きはこちら

株式会社ZOZOでは一緒に働く仲間を募集しています
同じタグの記事
今週のランキング
株式会社ZOZOからお誘い
この話題に共感したら、メンバーと話してみませんか?