シンプルにレコメンデーションを実装する

初めに、ここで実装したレコメンデーションはとてもシンプルな実装で、もっと優れた手法は世の中たくさんあるはずなので、ご了承ください。

レコメンデーション

僕はNetflixの「Narcos」というドラマが好きなのですが、見ているうちに「Narcosを見たあなたにオススメな一覧」として怖そうな麻薬戦争物がずらりと並びます。これがレコメンデーションですね。レコメンデーションとはいわゆる「類似度」というやつで、Narcosが好きな人はこんな映画、ドラマも好きですよとオススメしてくれるシステムのことです。

仕組み

ピアソン相関という数式を用いて、二つのデータの関係性を数値化して、-1(相関が薄い)から+1(相関が強い)を返します。 相関が強ければ強いほどレコメンドできるという訳ですね。 数式をみると、見た目とてもしんどそうなのですが、

f:id:keisuke_t:20181111171121g:plain

実態はとてもシンプルで

p = (共分散) / (1つ目のデータの標準偏差) * (2つ目のデータの標準偏差)

というだけです。Pythonで書くと

def pearson(d1, d2):
    d1_cv = d1 - d1.mean()
    d2_cv = d2 - d2.mean()
    return np.sum(d1_cv * d2_cv) / np.sqrt(np.sum(d1_cv ** 2) * np.sum(d2_cv ** 2))

pearson関数にデータを渡すことで、渡したデータの相関を-1から+1で返してくれます。

実験

映画のレコメンデーションシステムを実装するために、706作品の映画データとそれぞれの映画をユーザーがレーティングしたデータ8552件をダウンロードしたので、pandasのpivot_table関数を使って、columnsに映画IDをindexにユーザーIDをとり、ratingsをvalueとしてセットした新しいテーブルデータを作成しました。

import pandas as pd

ratings = pd.read_csv('ratings.csv')
ratings.drop(['timestamp'], axis=1, inplace=True)
table = ratings.pivot_table(index=['userId'], columns=['movieId'], values='rating')

試しに、ToyStoryとジュマンジにどれくらいの相関があるかを調べると、以下の値が返されました。

0.20285118554433546

ジャンルがわりと似ていたのでもっと高いかと思ったんですが、値的にはやや相関がある程度でしたね。

ToyStoryとNow and thenを比べると、、、

-0.0045909827988617324

マイナスの値になったので、相関は低いことがわかります。

作ったテーブルを元に、movie_idから相関性の高い映画をレコメンドしてくれる関数を実装しました。 受け取ったmovie_idとそれぞれのmovie_idとの相関性を計算したデータをrecommendation_ratingsに配列のtupleとして保存し、うちのトップn件を返しています。

def recommends(movie_id, table, limit):
    recommendation_ratings = []
    for target_id in table.columns:
        if target_id != movie_id:
            correlation = pearson(table[movie_id], table[target_id])
            if np.isnan(correlation):
                continue
            else:
                recommendation_ratings.append((target_id, correlation))
    return sorted(recommendation_ratings, key=lambda x: x[1], reverse=True)[:limit]

実際に、ToyStoryを見た人へおすすめのトップ10を計算させてみると、、、

Finding Nemo (2003)
Monsters, Inc. (2001)
Aladdin (1992)
Toy Story 2 (1999)
Bug's Life, A (1998)
Who Framed Roger Rabbit? (1988)
Honey, I Shrunk the Kids (1989)
Ratatouille (2007)
Beauty and the Beast (1991)
Home Alone (1990)

ピクサーの面々が抽出されました!確かにToyStoryとの相関は高いといえそうです! 今回実装したレコメンデーションはgithubにも公開しているので気になる点があったらぜひ、つっこんでください github.com

参照

相関係数について、勉強になりました! www.sekkachi.com