概要
こんにちは、shin0higuchiです😊
この記事はElastic stack (Elasticsearch) Advent Calendar 2018 - Qiitaの17日目です。
ElasticsearchのRanking Evaluation APIについて整理してみました 。
バージョン情報など
Elasticsearch : 6.5.1
Kibana : 6.5.1
Ranking Evaluation APIとは
Ranking Evaluation APIは、検索クエリに対する検索結果の妥当性を評価するためのAPIです。
Elasticsearchのバージョン6.2以降で利用することができます。
突然ですが、「良い検索」とはどういったものでしょうか?
一般的に、指定した検索条件に対して、より関連度の高いドキュメントが検索結果の上位に来るほど、良い検索システムであると言えます。
このAPIでは、「関連度の高いドキュメント」を事前にテストデータセットとして定義することで、実際の検索結果を評価します。
使いどころとしては、「index時に利用しているanalyzerの設定が適切か?」「アプリケーションがElasticsearchに対して発行するクエリは適切か?」などを定量的に評価したい場合に利用するのが良いと思います。
使い方
データ登録
今回は、日本語のWikipediaデータをElasticsearchに登録しておきます。
https://dumps.wikimedia.org/jawiki/20181201/jawiki-20181201-pages-articles6.xml-p2534193p3873913.bz2
からデータをダウンロードし、Logstashを使って取り込みました。
Kibanaから確認してみたところ、wikiというindexが作成されています。
約60万件の記事が登録されていることがわかります。
また、タイトル一覧を取得してみると、非常に多岐にわたる記事が登録されていますね。
リクエストの形式
Ranking Evaluation APIを利用する際のリクエスト形式は次のようになります。
GET /wiki/_rank_eval { "requests": [ ... ], "metric": { ... } }
詳細については後述しますが、リクエストボディは大まかに2つの要素からなります。
- requests : 検索クエリおよび、そのクエリで検索結果の上位に来て欲しいドキュメントのリスト
- metrics : 検索結果の評価方法の定義
では、それぞれの定義内容について説明します。
requests
requestsの形式は次の通り。
{ "id": " ... ", "request": { "query": { ... } }, "ratings": [ { "_index": "wiki", "_id": "doc1", "rating": 0 }. { "_index": "wiki", "_id": "doc2", "rating": 1 }, { "_index": "wiki", "_id": "doc3", "rating": 2 } ] }
request内にクエリを記述し、そのクエリで検索結果の上位に来て欲しいドキュメントのリストはratingsの中に記述します。indexとdocument idを指定し、ratingに関連度を記述します。ratingの数値は整数で、0であれば検索にヒットして欲しくないドキュメント(クエリに関連のないドキュメント)、数値が大きいほど関連のある(検索上位に来て欲しい)ドキュメントとなります。
上記の例だと、_idがdoc3とdoc2のものが検索結果上位に来て、doc1はヒットしないのが理想ということです。
Ranking Evaluation APIでの評価は、実際にクエリを実行した時に、ratingに定義したリストにどれだけ近いかを数値化するものです。
厳密にはこの後に説明するmetricで評価方法を決定します。
metric
評価指標としては次の4つがサポートされています。
- Precision at K
- Mean Reciprocal Rank (MRR)
- Discounted Cumulative Gain (DCG)
- Expected Reciprocal Rank (ERR)
詳細については、本記事では割愛します。
もし評価方法論について興味があれば、個人的には下記の書籍がオススメです。
情報アクセス評価方法論-酒井哲也-
この記事ではもっともシンプルなPrecision at K(以下、P@K)を用います。
これは実際の検索結果の上位Kドキュメントの適合率を表します。
metricにP@Kを設定するには下記のように記述します。
"metric": { "precision": { "k" : 5, "relevant_rating_threshold": 1 } }
この例では、検索結果の上位5件に、rank1以上のドキュメントが何割あるかを評価します。
5件全てが、関連のあるドキュメント(rank1以上)であれば適合率は100%、つまりP@Kは1となります。
実行してみる
では、実際に今回のケースに適用してみます。
例えば検索ユーザーが、「Javascriptのフレームワークに関連するドキュメントが欲しい」と考えたとしましょう。ユーザーは「Javascript Web フレームワーク」などと検索すると仮定します。このクエリで検索した時の結果を評価してみましょう。実際のリクエストは下記のようになります。
GET wiki/_rank_eval { "requests": [ { "id": "javascriptのフレームワークを探すクエリ例", "request": { "query": { "query_string": { "query": "Javascript Web フレームワーク" } } }, "ratings": [ { "_index": "wiki", "_id": "3440787", "rating": 1 }, { "_index": "wiki", "_id": "3387491", "rating": 1 }, { "_index": "wiki", "_id": "2611804", "rating": 1 }, { "_index": "wiki", "_id": "2922947", "rating": 1 }, { "_index": "wiki", "_id": "3672684", "rating": 1 } ] } ], "metric": { "precision": { "k" : 5, "relevant_rating_threshold": 1 } } }
ここでは関連のあるドキュメント上位5件のIDをratingsに登録しています。
実際に実行してみると次のようなレスポンスが返ってきます。
{ "metric_score" : 0.4, "details" : { "javascriptのフレームワークを探すクエリ例" : { "metric_score" : 0.4, "unrated_docs" : [ { "_index" : "wiki", "_id" : "2828794" }, { "_index" : "wiki", "_id" : "3447215" }, { "_index" : "wiki", "_id" : "3609062" } ], "hits" : [ { "hit" : { "_index" : "wiki", "_type" : "page", "_id" : "2828794", "_score" : 32.780136 }, "rating" : null }, { "hit" : { "_index" : "wiki", "_type" : "page", "_id" : "3440787", "_score" : 32.139748 }, "rating" : 1 }, { "hit" : { "_index" : "wiki", "_type" : "page", "_id" : "3447215", "_score" : 31.709887 }, "rating" : null }, { "hit" : { "_index" : "wiki", "_type" : "page", "_id" : "3609062", "_score" : 28.539764 }, "rating" : null }, { "hit" : { "_index" : "wiki", "_type" : "page", "_id" : "3387491", "_score" : 28.265165 }, "rating" : 1 } ], "metric_details" : { "precision" : { "relevant_docs_retrieved" : 2, "docs_retrieved" : 5 } } } }, "failures" : { } }
"metric_score" : 0.4という結果から分かるように、適合率は40%、つまり5件中の2件のみが関連するドキュメントで、残りの3件は関連がない若しくはrateingされていないドキュメントということになります。
実際、unrated_docsというブロックを見ると、3件のドキュメントが入っています。
これは、想定していなかった(リクエスト時にrating指定していなかった)ドキュメントが、検索結果の上位5件に入ってきたことを意味します。
ドキュメントを確認してみたところ、「Vue.js」「Angular.js」などの他に、「シングルページアプリケーション」などがヒットしていました。
今回のケースでは、「シングルページアプリケーション」よりも上位に来て欲しい他のフレームワークなどもありました。
実際には、ここからanalyzerやscoringなどを調整して理想の検索結果に近づくようチューニングをしてゆくことになるでしょう。
その時に再びRanking Evaluation APIを利用して精度が上がったかどうかを客観的数値で測ることができます。
今回の記事の中では、長くなってしまうためチューニングについては割愛します。
さて、ここまでRanking Evaluation APIの使い方を簡単に説明してきました。
真面目に検索システムとして評価するとなると、通常は1つのクエリだけでなく、複数のクエリを用いて総合的に評価するでしょうし、ratingに関してもより網羅性を上げる必要があると思います。ただ、全ドキュメントにレートをつけるのは現実的ではないので、通常はどの程度までratingするものなのか、詳しい人がいたら是非話してみたいものです。
まとめ
以上です。ツッコミ等あれば是非お願いいたします。
お読みいただきありがとうございました。
Acroquest Technologyでは、キャリア採用を行っています。
- ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
- Elasticsearch等を使ったデータ収集/分析/可視化
- マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
- 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。世界初のElastic認定エンジニアと一緒に働きたい人Wanted! - Acroquest Technology株式会社のエンジニア中途・インターンシップの求人 - Wantedlywww.wantedly.com