Elasticsearch 分類予測 Percolator編

Kunihiko Kido
Hello! Elasticsearch.
8 min readSep 4, 2015

--

機械学習せずに新しいドキュメントの分類を予測する。Percolator編

Elasticsearch with Amazon Machine Learning では、機械学習による分類予測について紹介しました。今回は、機械学習せずにElasticsearchのPercolatorを使って、分類予測する方法について紹介したいと思います。

Percolatorとは?

Percolatorは、Elasticsearchが提供する仕組みの一つです。通常の検索では、インデックスされているドキュメントに対してクエリーをリクエストし、マッチしているドキュメントを抽出します。

Search API: Query -> Documents

Percolatorはその逆で、インデックスされているクエリーに対してドキュメントをリクエストし、マッチしているクエリーを抽出することができる機能です。

Percolate API: Document -> Queries

今回の分類予測はこの仕組みを利用します。

トレーニング

それでは早速。ここでのトレーニングとは各種分類ごとの Percolator Query の作成です。マニュアルで作成しても良いのですが、ここでは Significant Terms Aggregation を使用して分類済みのドキュメントから自動で作成します。

分類済みのドキュメントの内容はこんな感じです。

{
"title": "原油安の「マイナス面」無視できず…"
"contents": "原油相場の下落が続いている。21日のニューヨーク市場で原油先物相場は国際指標の米国産標準油種(WTI)が …"
"category": "経済"
}

"title"、"contents" フィールドの内容をもとに、"category" フィールドのカテゴリに分類するためのクエリーを作成します。

考え方としては、例えば「経済」にタグ付けされているドキュメント群の"title"と"contents"フィールドからそのドキュメント群を表す重要なキーワード群を抽出して、そのキーワードから「経済」のドキュメントに分類するためのクエリーを生成します。

重要な単語を抽出する

まずは、Search APIを使用して、各カテゴリ毎の重量な単語を抽出します。以下は、「経済」カテゴリのドキュメント群から "title" と "contents" フィールドの重要な単語を集計するクエリーです。

{
"query": {"term": {"category": "経済"}},
"aggs": {
"significantTitleTerms": {
"significant_terms":{"field": "title", "size": 100}
},
"significantContentsTerms": {
"significant_terms":{"field": "contents", "size": 100}
}
},
"size": 0
}

結果は以下のような感じで取得することができます。それっぽい単語が抽出できてますね。

{
...
"aggregations": {
"significantTitleTerms": {
"doc_count": 400,
"buckets": [
{"key": "時事通信", ...},
{"key": "株式", ...},
{"key": "東京", ...},
{"key": "外為", ...},
{"key": "", ...},
{"key": "日経", ...},
...
]
},
"significantContentsTerms": {
"doc_count": 400,
"buckets": [
{"key": "市場", ...},
{"key": "株式", ...},
{"key": "株価", ...},
{"key": "指数", ...},
{"key": "日経", ...},
{"key": "相場", ...},
...
]
}
}
}

あとは、この抽出したキーワードを使って Percolator 用のクエリーを組み立てて登録します。

登録は、通常のドキュメントの登録と同じ感じで、特殊な .percolator というドキュメントタイプにインデックスするだけです。ドキュメントのIDは Percolatorの結果がわかりやすいようにカテゴリ名称をそのまま使用しました。

POST /index-news-ja/.percolator/経済
{
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "時事通信 株式 東京 外為 株 ...",
"operator": "or",
"minimum_should_match": "2%"
}
}
},
{
"match": {
"contents": {
"query": "市場 株式 株価 指数 日経 ...",
"operator": "or",
"minimum_should_match": "2%"
}
}
}
]
}
}
}

クエリーの説明を簡単にすると、title フィールドに並べたキーワードのうち2%がマッチ、かつ contents フィールドに並べたキーワードのうち同じく2%がマッチするドキュメントを探すクエリーです。

予測

各カテゴリ用の Percolator が登録できたら新しいドキュメントを使用して早速予測してみましょう!

予測には Percolator API を使用します。次の例のように新しいドキュメントを Percolator APIにリクエストします。

POST /index-news-ja/posts/_percolate
{
"doc": {
"url": "http://headlines.yahoo.co.jp/hl?a=..."
"title": "飲食料品、消費税負担を軽減…10%後に給付金",
"contents": "消費税率を10%に引き上げる際の負担軽減策の..."
}
}

結果は以下のように取得できます。(予測結果)

{ ...
"matches": [
{"_index": "index-news-ja", "_id": "経済"}
]
}

今回は、シンプルに1カテゴリに対して1つの Percolator Query をそれぞれ作成する方法を紹介しました。このやり方でのチューニングは、キーワードの数を増やしたり、最小マッチ数を調整することで精度を調整可能です。

しかし、単語数を増やしすぎたりすると予測結果はの精度が下がったり(関連の低い予測結果が多く出てしまったり)、逆にマッチする条件を厳しくしすぎると予測できないドキュメントが多くなってしまいます。

より精度を上げるには

より精度を上げたい場合にはどうしたらよいかというと、Percolator Quey は、クエリー以外に任意の属性も一緒にインデックスできます。

POST /index-news-ja/.percolator/経済-時事通信
{
"query": {...},
"category": "経済" # 任意の属性と値
}

さらにマッチしたクエリーのその属性を使って Aggregation も使用できます。

POST /index-news-ja/posts/_percolate
{
"doc": {
"url": "http://headlines.yahoo.co.jp/hl?a=..."
"title": "飲食料品、消費税負担を軽減…10%後に給付金",
"contents": "消費税率を10%に引き上げる際の負担軽減策の..."
},
"aggs": {
"significantCategory": {
"significant_terms": {"field": "category"}}
}
}

この仕組みを使って、1カテゴリに対して複数の Percolator Query を作成し、予測する時はマッチしたクエリー群から Significant Terms Aggregation を使って、最適な分類を割り出すと、より精度の高い分類機が作成できます。

さいごに

この仕組みさえ作成してしまえば、トレーニング -> 予測 -> 分類 の流れを各種APIを使用して自動化も可能です。さらにトレーニング元と分類先は同じデータなので、機械学習のようにモデル作成用のデータを作らなくてもよいという利点もあります。ちょっとライトに自動分類したい時にオススメです。

--

--