概要
OpenSearchで、Vega-Liteを使ってPrecision、Recall、F1スコアを算出して表示できた。
背景と目的
先日、Vega-LiteでPrecision、Recall、F1スコアを算出して表示ができたので、OpenSearchのVegaタイプのVisualizeで同様に表示をしてみる。
詳細
0. 環境
- OpenSearch 2.6
- Docker Desktop for Windowsにてコンテナを実行
1. サンプルデータでコーディング
ひとまず、以前Vega-LiteでコーディングしたものをそのままOpenSearchに書いてみる。データもその時と同じものをべた書き。
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": { "values": [ {"predicted": "1", "actual": "1"}, {"predicted": "1", "actual": "0"}, {"predicted": "0", "actual": "1"}, {"predicted": "1", "actual": "1"}, {"predicted": "1", "actual": "1"}, {"predicted": "0", "actual": "1"}, {"predicted": "1", "actual": "1"}, {"predicted": "1", "actual": "1"}, {"predicted": "0", "actual": "1"}, {"predicted": "1", "actual": "0"}, {"predicted": "0", "actual": "0"} ] }, transform: [ { "joinaggregate": [ { "op": "count", "as": "actual-count" } ], "groupby": ["actual"] }, { "joinaggregate": [ { "op": "count", "as": "predicted-count" } ], "groupby": ["predicted"] }, { "joinaggregate": [ { "op": "count", "as": "confusion-matrix" } ], "groupby": ["predicted", "actual"] }, { "calculate": "datum['confusion-matrix'] / datum['actual-count']", "as": "recall" }, { "calculate": "datum['confusion-matrix'] / datum['predicted-count']", "as": "precision" }, { "calculate": "2 / (1 / datum.recall + 1 / datum.precision)", "as": "F1-score" }, { "filter": "datum.predicted == datum.actual" } ], "repeat": {"layer": ["recall", "precision", "F1-score"]}, "spec": { "mark": "rect", "encoding": { "x": { "field": "predicted", "type": "nominal" }, "y": { "field": {"repeat": "layer"}, "type": "quantitative", "title": "score" }, "color": {"datum": {"repeat": "layer"}, "title": "性能指標"}, "xOffset": {"datum": {"repeat": "layer"}} } }, "config": { "mark": {"invalid": null} } }
実績のあるコードなので、当然ちゃんと表示される。
2. OpenSearch上のデータを使って表示させる
2.1 使うデータ
以下のような疑似的な予測、正解のラベルがセットになった30アイテムが"iris-result"というindexに挿入されているものとする。
{"predicted": "setosa", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "virsicolor", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "virsinica", "actual": "setosa"}, {"predicted": "virsinica", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "setosa", "actual": "setosa"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "setosa", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsicolor", "actual": "virsicolor"}, {"predicted": "virsinica", "actual": "virsinica"}, {"predicted": "virsinica", "actual": "virsinica"}, {"predicted": "setosa", "actual": "virsinica"}, {"predicted": "setosa", "actual": "virsinica"}, {"predicted": "virsinica", "actual": "virsinica"}, {"predicted": "virsinica", "actual": "virsinica"}, {"predicted": "virsicolor", "actual": "virsinica"}, {"predicted": "virsicolor", "actual": "virsinica"}, {"predicted": "virsicolor", "actual": "virsinica"}, {"predicted": "virsinica", "actual": "virsinica"}
混同行列は、
predicted | 計 | setosa | setosa | setosa | |
---|---|---|---|---|---|
actual | setosa | 7 | 1 | 2 | 10 |
virsicolor | 1 | 9 | 0 | 10 | |
virsinica | 2 | 3 | 5 | 10 | |
計 | 10 | 13 | 7 | 30 |
となるので、Precision、Recall、F1スコアの正解は、
setosa | virsicolor | virginica | |
---|---|---|---|
precision | 0.7 | 0.692307692307692 | 0.714285714285714 |
recall | 0.7 | 0.9 | 0.5 |
F1 | 0.7 | 0.782608695652174 | 0.588235294117647 |
である。
2.2 データ参照部分を少し変更
上記データを取り出すために変更したものが以下。data.format.propertyはクエリで何も集計しない場合hits.hitsから取り出す必要がある。また、encoding.xやyのfield参照先は、_source.フィールド名とする必要がある。
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json" "title": "混同行列", "data": { "url": { "index": "iris-result", "body": { "size": 30 } }, "format": {"property": "hits.hits"} }, "encoding": { "y": { "field": "_source.actual", "type": "ordinal", "title": "実データ" }, "x": { "field": "_source.predicted", "type": "ordinal", "title": "予測" } }, "layer": [ { "mark": "rect", "encoding": { "color": { "aggregate": "count", "type": "quantitative", "legend": false, "scheme": "rainbow" } } }, { "mark": "text", "encoding": { "text": { "aggregate": "count", "type": "quantitative" }, "color": { "value": "black" } } } ], "config": { "axis": {"grid": true, "tickBand": "extent"} } }
表示させた結果は以下。正しく表示できている。
まとめと今後の課題
OpenSearchで、Vega-Liteを使ってPrecision、Recall、F1スコアを算出して表示することができた。Vega-Liteの扱いに徐々に慣れてきたので、積極的に使用していきたい。