Help us understand the problem. What is going on with this article?

Elasticsearchを推薦システムとして使う(関連アイテム推薦)

こんにちはrilmayerです。
この記事はアドベントカレンダー「Search&Discovery 全部俺」18日目の記事となります。(遅れ

本日は定番のOSS全文検索エンジンであるElasticsearchを推薦システムとして使ってみようと思います。

基本的な操作は以前こちらの記事でご紹介しましたが、おさらいをかねてやっていこうと思います。

Elasticsearchの立ち上げ

やはりDockerが楽なのでDockerイメージで立ち上げてみます。

Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:7.5.0
RUN bin/elasticsearch-plugin install analysis-kuromoji

以下のようにbuildしてrunすれば立ち上がります。

# build
docker build -t es .

# run
# 中に入る場合
docker run -i  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" es bash

# デーモンとして起動する場合
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node"  es

アイテムの投入

今までと同じくアイドルデータを追加してみます。

from elasticsearch import Elasticsearch

# インデックス作成
host = 'http://localhost:9200/'
es = Elasticsearch(host)
index_name = 'my_favorite_idols'
es.indices.create(index=index_name, body={
    'settings': {
            'number_of_shards': 5,
            'number_of_replicas': 0
    },
    'mappings': {
        'properties': {
            'idol_name': {
                'type': 'text',
                'analyzer': 'kuromoji'
            },
            'description': {
                'type': 'text',
                'analyzer': 'kuromoji'
            }
        }
    }
})

アイドルデータの追加

チクチクアイドルデータを追加していたのですが、めんどくさくなったのでこちらのサイトでSPARQという問い合わせ言語を使ってwikiのデータをバコッと取得しました。

select distinct ?name ?abstract where {
    ?idol <http://dbpedia.org/ontology/wikiPageWikiLink> <http://ja.dbpedia.org/resource/Category:日本のアイドルグループ> .
    ?idol rdfs:label ?name .
    ?idol <http://dbpedia.org/ontology/abstract> ?abstract .
}
LIMIT 1000

上記で取得したデータをCSVとして取得して以下のようにアイテムを追加します。
おそらく650くらいのアイドル情報が入手できるはずです。

# ファイル読み込み
import pandas as pd
csv_file_path = "idol.csv"
df = pd.read_csv(csv_file_path)

# アイテム投入
for i, row in df.iterrows():
    item = {'idol_name': row["name"], 'description': row.abstract}
    es.index(index=index_name, body=item)

これでアイテムが投入されました。

特定アイテムに似ているアイテムを取得する

Elasticsearchにはmore_like_thisという便利な機能が提供されています。

アイテムのIDを取得して以下のアイテムをベースに類似検索(関連アイテム推薦)を行ってみます。

query = '東京女子流'
es_query = {
    "query": {
        "multi_match": {
            "query":    query
        }
    }
}
results = es.search(index=index_name, body=es_query)
print('hit:  ', results['hits']['total']['value'])
for i, result in enumerate(results['hits']['hits']):
    print(f"[{result['_id']}]", result['_source']['idol_name'], ':  ', result['_source']['description'][0:50])

上記で取得したIDを元に類似検索をします。

def get_similar_items(item_id):
    es_query = {
        "query": {
            "more_like_this" : {
                "fields" : ["title", "description"],
                "like" : [
                    {
                        "_id" : item_id
                    }
                ],
                "min_term_freq" : 1,
                "max_query_terms" : 12,
                "minimum_should_match": 1
            }
        }
    }
    results = es.search(index=index_name, body=es_query)
    return results

item_id = [取得したID]
results = get_similar_items()
for i, result in enumerate(results['hits']['hits']):
    print(f"[{result['_id']}]", result['_source']['idol_name'], ':  ', result['_source']['description'][0:50])

以下のような結果が得られました。

[0] SweetS :   SweetS(スイーツ)は、日本の女性5人組ダンス&ボーカルユニット。エイベックス・エンタテインメン
[1] Cheeky Parade :   Cheeky Parade(チィキィパレード)は、2012年に結成された日本の9人組女性アイドルグル
[2] GEM (アイドルグループ) :   GEM(ジェム)は、2012年に結成された日本の女性アイドルグループ、ダンス&ボーカルグループ。所属
[3] SUPER☆GiRLS :   SUPER☆GiRLS(スーパーガールズ)は、エイベックスのオーディションにより、2010年に結成さ
[4] フェアリーズ :   フェアリーズ(Fairies)は、日本の6人組女性アイドルグループ、ダンスボーカルグループで、201
[5] SPEED :   SPEED(スピード)は、日本の女性4人組のボーカル&ダンスグループ。メンバー全員が沖縄県出身。プロ
[6] W-inds. :   w-inds. (ウィンズ)は、日本の男性ダンス&ボーカルユニット。所属事務所はライジングプロダクシ
[7] DA PUMP :   DA PUMP(ダパンプ)は、日本のヒップホップダンスボーカルユニット。所属事務所はライジングプロダ
[8] Dancing Dolls :   Dancing Dolls(ダンシングドールズ)は、日本の5人組女性ダンス・ボーカルユニット。
[9] チェリーブロッサム :   チェリーブロッサムは、日本の6人組女性アイドル・ダンス&ボーカルグループである。愛称は、チェリブロ。

ぽいような気もするけれど、あくまで出てくる単語ベースなのでもう少し頑張りたいという感じもあります。
パラメータもいくつかあるのでチューニングしながら使ってみると良いかもしれません。

おわりに

アイテムをインプットとして関連するアイテムを推薦するのも推薦システムの一つの方法です。
この方法はユーザー行動がなくてもできるので、立ち上げたばかりのサービスな度で非常に有効です。

ユーザーの情報を使ってランキングなどを行うのはまた別の工夫が必要となります。

rilmayer
最近糖質制限をしている。
http://frsw.net
libora
e-Learning一括検索サービス『LIBORA』の開発・運営を行っています。
https://libora.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした