狠狠撸

狠狠撸Share a Scribd company logo
Elasticsearch の検索精度のチューニング
~テストを作って高速かつ安全に~
伊藤敬彦
2022/04/20
2
自己紹介
● 名前:伊藤 敬彦
● 所属:Ubie Discover
y

● Twitter: takahi_i
● そのほか:
○ 博士(工学)
○ OSS
:

■ RedPen - Markdown や AsciiDoc の Linte
r

■ Cookiecutter Docker Science - ML プロジェクトのテンプレート
○ 本格的に使ったことのある検索エンジン
■ Fast ESP、Sedue、Solr、Elasticsaerch
3
準備:検索精度のチューニング?
● 検索システムを構築した後におこなう、精度をチューニングする作業を指す
● 具体的な作業
a. 検索精度(CTRなど)を計測するモニタリングダッシュボードを作成
■ ログを仕込む
b. インデクス、クエリの調整
c. 各種ログを用いたブースト(リランキング、ML etc..)
● ダッシュボードを作った後、何度も調整を加えて良い設定を見つけてゆく
4
精度チューニングの辛い点
● 精度のチューニング作業はストレスが多い
○ 適用した施策が思ったようにダッシュボードのスコアに寄与しない
○ E.g., 精度モニタリング用ダッシュボード、A/Bテスト
● 適応した施策が意図したとおりになされているのか分からず不安
○ いくつかクエリ発行してみて期待したように動いているように見えるが。。(確信が持てない)?
○ 施策が思わぬ副作用(デグレ)を起こしてしまっていないか。。。(疑心暗鬼)?
4
5
一般的なソフトウェア開発と検索の精度チューニングの違い
● ソフトウエア開発
○ (ユニット)テストを使って、システムの振る舞いを確認
○ VCSを使うことで昔のバージョンとの差分を確認できる
● 検索精度のチューニング
○ テストする機構がないので、修正の結果デグレが発生しても見落とす可能性がある
○ 昔のインデクス、クエリでどのようなランキングが出力されていたのか分からない
6
アイデア
検索クエリに対する結果を簡単にテストできると修正時の安心感が上がるのでは?
7
実は
● Elasticsearch が提供してくれている Ranking Evaluation API が存在!
○ ElasticsearchのRanking Evaluation APIについて整理してみた by (Acroquest Technology株式
会社のエンジニアブログ)


● 検索インデクスと、クエリを指定したときに結果に含まれるランキングがどの程度期待したものかを
計算してくれる
8
Ranking Evaluation API
● Ranking Evaluation API は精緻な分析ができて素晴らしい
○ 例:クエリに対してP@Kの値を出力
● ただ、自分が利用したい用途(検索精度のテスト)では少し問題:
○ テストが書きにくい(しきい値はどこに設定する?)
○ Failしたときの解釈が面倒(設定が抽象化されたRatingで管理されている)
● ほしいテスト:
○ 指定したクエリに対する結果には
■ 文書Aは3位以内、文書Bは5以下に入っていてほしい
■ 文書Cは10位以内にはいっていてほしくない
○ 条件が満たされていなかったら即エラーを発行し、理由を出力してほしい(エラーが出ないと気が付かないので)
9
そこで
● Esqa (Elasticsearch qa) という簡素なツールを作りました。
● ソースコード:https://github.com/ubie-oss/esqa
● Pypi: https://pypi.org/project/esqa/
10
Esqa が提供する機能
2つの機能を提供する
● Assertio
n

○ ある検索インデクスに対するクエリの結果(ランキング)が満たす条件を記述し、検索結果が条
件を満たさないときにはエラーが発生する
● Distanc
e

○ 指定したクエリ郡に対して過去の時点と今の検索結果ランキングを比較
■ ランキングの差がしきい値以上の事例を抽出
11
Esqa が提供する機能
2つの機能を提供する
● Assertio
n

○ ある検索インデクスに対するクエリの結果(ランキング)が満たす条件を記述し、検索結果が条
件を満たさないときにはエラーが発生する
● Distanc
e

○ 指定したクエリ郡に対して過去の時点と今の検索結果ランキングを比較
■ ランキングの差がしきい値以上の事例を抽出
12
Esqaによる検索精度のAssertion
● esqa assertion コマンドに設定ファイ
ルとインデクスを指定して実行
● 設定ファイル:クエリから返ってくる
ランキングが満たすべき条件をテスト
ケースとして記述
● 設定ファイルに記載された条件が満た
されないときには、エラーが発生する
$ esqa assertion --config config.json --index
document-index


[


{


"message": "[title match] Document with id = 4 is
not ranked in 0. id field value of 0-th item is 6",


}


]
13
設定ファイル:assertion
{

"cases":
[

{

"name": "match query"
,

"request":
{

"query":
{

"match":
{

"message":
{

"query": "engineer
"

}

}

}

}
,

"asserts":
[

{

"type": "higher"
,

"rank": 2
,

"item":
{

"field": "document_id"
,

"value": "24343
"

}

}

]

}

]

}
● テストケースは cases ブロックに列挙される
● 各テストケースは三組の要素を持つ
○ name: テストケースの名前
○ request: Es クエリ
○ asserts: 結果のランキングが満たすべき
条件(複数の条件を指定可能)
名前
クエリ
条件
14
リクエスト:Es クエリ
● リクエストブロックにEs クエリを記述する
● テストケースごとにEsクエリを書くと煩雑な
のでテンプレートもサポートされている
{


"templates": [


{


"name": "basic_query",


"path": "sample/template.json"


}


],


"cases": [


{


"name": "title match",


"request": {


"template": "basic_query",


"query_str": "Windows"


},


"asserts": [...]


}


]


}


テンプレート
ファイル(Es
クエリが保存
されている)
テンプレート
ファイルを指
定
15
Asserts: 検索結果が満たすべき条件の記述
各条件は type, rank, item 要素を持つ
● 例:id = 434 の文書は 2 番目以上にランクされ
る
要素 概要
type 条件のタイプ(higher,
lower, equal)
rank 文書の検索ランキング
item 文書(フィールドのID
で指定)
{

"type": "higher"
,

"rank": 2
,

"item":
{

"field": "id"
,

"value": "434
"

}

}
16
実際、どういったテストケースをつくるのか?
基本戦略:
● タグ付きコーパスを作成するようなコストは掛けたくない(掛けられない)
● 一旦最低限(少々間違っていても良い)のものをつくって、徐々にテストケース自体を良くしてゆく
17
用意するテストケース
2種類のテストケースを作る
1. 検索が満たすべき機能をテストケースとして追加
○ 例:完全一致、標準形での検索、フィールドによる重み付け、前方一致、読みによるマッチ、ストップワード、
ブースト、シノニム etc
…

2. 検索頻度が最も多いクエリと結果からテストケースを自動で生成
○ 例:現在のランキングから最低数個落としたランキング以上になるようなテストケースをつくる
■ 現在1位にランクされる文書は3位以内にランクされなくてはならない
■ 現在2位のランクされる文書は4位以内にランクされなくてはならない
■ 。。。
○ 注:このテストケースはかならず正解というわけではないが、チューニング後にランキングが大きく異なった
場合にエラーが出てくれて便利
18
例:テストケース
● 「すぽーつ おんが」というクエリの結果ラン
キングでは「スポーツ 音楽」という内容(ク
エリがかな漢字変換された内容)を含む文書
(id 4389)が3位以上にランキングされる
{


"name": "yomigana prefix match",


"query": "すぽーつ おんが",


"asserts": [


{


"type": "higher",


"rank": 3,


"item": {


"field": "id",


"value": "4389"


}


}


]


}
19
精度チューニングにおけるEsqaの使い方の流れ
テストケースが用意できたら、以下の作業を繰り返す
1. インデクス or クエリを変更して Assertion が Fail するテストケースがないか確認する
○ 実施しようとしている修正が適切になされているか確認できるテストケースも追加する
2. Failするテストケースがあれば、原因を同定
○ 原因を同定した結果
■ インデクス or クエリが悪い場合 → テストがFailしないようにインデクス or クエリを修正
■ テストケースが悪い場合(結果がより良くなった場合) → テストケースを修正
● Goldenデータセットとしてのテストケースの改善が見込める
20
Esqaを使って検索を改善した所感
● 品質担保がある程度テストできるので、インデクスやクエリを変更する心理的な障壁がかなり下がっ
た。
● 修正したあと開発環境でEsqaを実行して、「こんな副作用がっ!?」ということが何度かあってデグ
レを防げた
● 改善の結果、より関連度の高い文書が上位にランクされることが原因でテストが落ちる→精度向上が
確認できて精神衛生上いい(テストの方を書き換える)
● モニタリングの数値が一時的に悪化した場合でも平常心で居られるようになった
● 修正をリリースするまでの検証プロセスが固定できるので改善する速度も向上
21
Esqa が提供する機能
2つの機能を提供する
● Assertio
n

○ ある検索インデクスに対するクエリの結果(ランキング)が満たす条件を記述し、検索結果が条
件を満たさないときにはエラーが発生する
● Distanc
e

○ 指定したクエリ郡に対して過去の時点と今の検索結果ランキングを比較
■ ランキングの差がしきい値以上の事例を抽出(何%ぐらいの事例に大きな変化があったの
かが理解できる)
22
Esqaを利用したランキング間の距離(distance)を測定
● Ranking Validation API を使うと過去のランキングと現在のランキングの比較ができます。
○ Elasticsearchのクエリ変更による影響度をオフライン評価する (Acroquest Technology株式会
社のエンジニアブログ
)

● 長らくEsqaでも欲しかったので、作ってみました(PoC状態)。
23
モチベーション
● インデクス、クエリの修正前後の高頻度クエリへのランキングを保持しておいて、最もランキングが変
動したクエリを知りたい。
● 修正によってランキングが一定以上変動したクエリは何%程度なのか知りたい
○ 特に础叠テストにおいて
24
使い方
修正前後の2つの状態を比較するには以下の流れ
● 現在のランキングを保存する(save)
○ esqa save --config sample/ranking.json --index sample > output/previous_ranking.json


● 新しい設定(クエリ or インデクスを修正)で保存されたランキングを指定して比較
○ esqa distance --config sample/compared_ranking.json --index sample --ranking output/
previous_ranking.json


注: –config で指定する設定ファイルにはクエリのリストが記載されている
25
今後の開発
● テスト条件で文書の特徴を指定
○ Decay Factorなどのテストでは文書自体よりも文書の条件(作成年月日など)を指定したい
● クエリに対して過去の複数時点でのランキング一覧を表示したい
26
まとめ
● 検索精度のチューニングのツラミ
● 検索精度のチューニングをサポートするツールの紹介
● ツールを使ってテスト駆动で検索精度を向上するサイクルについて绍介
27
ご清聴ありがとうございました

More Related Content

Elasticsearch の検索精度のチューニング ?テストを作って高速かつ安全に?