nakamura244 blog

所属団体とは関係なく、個人的なblog

類似レコメンドシステムとしてのElasticsearchの活用検討

はじめに

キーワード検索システムに続いて、レコメンドシステムも担当になりました

キーワード検索というのはキーワードというヒントをくれたレコメンドシステムみたいなものといえばそんな感じなので両方を担当しています。

キーワード検索システムの方はこちらの記事を参考にしてください

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

という流れでキーワード検索システムに加えてレコメンドシステムの立ち上げを行っています。(まだひとりチームです)

立ち上げにあたりどんなレコメンドシステムを検討中か

大きく分けて、1:コンテンツベースの類似度レコメンド と 2:支援データを元にした協調フィルタリングをもちいたレコメンド の開発を進めています

1は この商品と似ている商品はこちらです みたいなレコメンドです

2は この商品を購入しているユーザはB商品も購入していますみたいなレコメンドです

で、今回は1のレコメンドの話です

コンテンツベースのレコメンドはググると色々出てくると思います。昔からあるものなので。

で先日、検索システムがリリースされました

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

実はElasticsearchの中でも類似度検索というものがあります。 ... More like this query

More like this query | Elasticsearch Reference [7.4] | Elastic

More like this queryの中身はluceneのTFIDFSimilarityというものでした。TFIDFがベースなんでしょうね

TFIDFSimilarity (Lucene 4.9.0 API)

More like this queryを使ってのコンテンツベースの類似レコメンド機能の実装案を残しておこうかと思います

実現したい具体的なを仮決め

Aというプロジェクトを見ている時にAに似たプロジェクトを表示させたい。

下記はイメージです

f:id:tsuyoshi_nakamura:20191021101506p:plain

デザインやUI / UXは別のチームが担当していて自分に決定権はありません。だけど、具体的な機能をイメージしないととても作りづらい...

仮でも良いのでmockまでできると、色々とアイディアを出してくれる人が増えて、一気にproductionレベルのものになっていく事はよくある事です。

なので、XXという機能を開発すると仮定義して開発を進めています。もちろん仮なのであとで180度変更されても良い心持ちでいます。

どうやって実現していくか

基本はElasticsearchの機能に乗っかるので下記のエントリーで構築したシステムのAPI-Gatewayにエンドポイントを新設してMore like this query 検索を実行する流れになります

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

そして次に類似させたい元のAというPJの特徴語を抽出します。特徴語抽出は基本的にTFIDFを活用する事になると思います

tf-idf - Wikipedia

1. 類似させたい元になるAというPJの特徴語を抽出する

方法は何通りかあるだろうけどここでは2つあげておく

方法A:事前に特徴語を抽出しておく

f:id:tsuyoshi_nakamura:20191015202726p:plain

  1. 自前で形態素解析機を揃えて文章を解析します
  2. 名詞・形容詞以外の文字は捨てます
    • サービスによってはどの品詞を使うかは異なると思います
  3. scikit-learnを使ってtf-idf計算をサクッとします
  4. 最後に集計して特徴語を抽出します

方法B:Significant Terms Aggregationの活用

Significant Terms Aggregation | Elasticsearch Reference [7.4] | Elastic

このクエリーを投げるだけでも特徴語が取れるようです

2. 前の工程で取得できた特徴語をストレージに格納

まぁRDBで良いんじゃないでしょうか

3. 類似レコメンドを取得したい時にElasticsearchのMore like this query検索を実行する

類似させたい元のPJの特徴語を取得して、ElasticsearchのMore like this query検索を実行すれば、見事簡単に類似レコメンド機能が完成する

ここではAというプロジェクトの特徴語を類似検索に投げていますが、別に特徴語を使わなくても良いと思います。

特徴語を使わなくても良いかも?!

単純に類似させたい元のタイトルをそのまま類似検索に投げても思った結果が得られる場合もあります。

それぞれのタイトル名は練りに練った言葉を選択している傾向があるのでこのまま活用するのも良いと思います。

あとは、More like this queryのパラメータ設定でも当然結果が異なるので色々と設定値を探索する必要があります。

More like this queryの検索フィールド(=fields)を本文にするのか、別に作成した文章にするのか等々でも色々と変わってくると思います。

それぞれの特徴を捉えてサービスに合わせたベストな組み合わせを選ぶことになりそうです

難しいのは評価

いわゆる教師なし系のレコメンドは事前に検証が出来ないので、社内でDog Foodしたり、本番にカナリアリリースして様子をみるしかありません。

カナリアリリースの場合は一定期間もしくは、N%のユーザだけに機能を提供して、CTR、CVRで比較して評価してあげると言う感じになると思います。

今回はまだ類似レコメンドシステムが存在しないので社内で下記のようなDog Food環境を作りました

f:id:tsuyoshi_nakamura:20191015210844p:plain

  1. 公開していないclosedなchromeエクステンションを開発し、使ってもらえるユーザに手動でinstall
  2. chromeエクステンションが動いて、More like this queryを実行する一般公開前のエンドポイントへアクセス
  3. 類似データを取得したらここは無理くりhtmlをinner writeする

そうすると特定の人だけに下記のような画面表示になる

f:id:tsuyoshi_nakamura:20191015211653p:plain f:id:tsuyoshi_nakamura:20191015212536p:plain

このchromeエクステンションを使って一般公開前のエンドポイントにアクセスしてコンテンツを形成して追加してしまうという方法の利点は何と言っても本番データでそのままdog foodできる点です。

なのでエンジニアに限らず、いろんな職種の人でテストができる点がGoodだと思っています

最後に

コンテンツベースの類似レコメンドはこの他にItem2vecを元にしたもの、K-meansの教師なしクラスタを活用したものの開発を予定しています

これらの情報共有はまた別の機会にしようと思います

[1603.04259] Item2Vec: Neural Item Embedding for Collaborative Filtering Unsupervised learning: seeking representations of the data — scikit-learn 0.21.3 documentation

まぁともあれキーワード検索でElasticsearchを活用している事で既存資産を活かして最小コストで類似度レコメンドが実装できる点、社内で試せるDog Food方法を示しました

リソース上、お一人で開発を頑張っている方の少しでも足しになる情報になれば幸いです

補足

今後はItem2vecとK-meansの教師なしクラスタでの類似レコメンドを開発し、良さそうな方を採用してリリースまで実装しようと思います