微忘録

好奇心に記憶力がついていかない人のブログ

協調フィルタリングで将来レビュー値を予測する

いまコレ↓読んでます。卒論の参考図書です。

情報推薦システム入門 -理論と実践-

情報推薦システム入門 -理論と実践-

協調フィルタリングの端緒であるピアソンの積率相関を用いた推測を、実際にpythonで動かしてみたので備忘録。

ピアソンの積立相関の式

\begin{align} r_{xy} = \frac{\displaystyle \sum_{i = 1}^n (x_i - \overline{x}) (y_i - \overline{y})}{\sqrt{\displaystyle \sum_{i = 1}^n (x_i - \overline{x})^2}\sqrt{\displaystyle \sum_{i = 1}^n (y_i - \overline{y})^2}} \end{align}

正規分布を仮定した変数XとYに対して用いられる相関係数ことピアソンの積立相関
分子が「変数Xと変数Yの共分散」であり、分母が「変数Xと変数Yのそれぞれの標準偏差の積」で計算できる。

よって以下の様に「ユーザーXとユーザーYのレビュー値の共分散」と「ユーザーXとユーザーYのそれぞれのレビュー値の標準偏差の積」で計算できる。

pandasのDataframeを用意

お題は、 『ユーザーXのアイテム5のレビューを、ピアソンの積立相関から推測する。』

import pandas as pd

review_df = pd.DataFrame([[4,2,3,1,],
                          [1,4,3,2,5],
                          [4,2,4,5,1],
                          [5,3,3,2,4],
                          [3,1,2,4,3],
                          [2,2,3,1,3],
                          [3,1,1,1,1],])

review_df.columns = ["item_1","item_2","item_3","item_4","item_5"]
review_df.index   = ["user_X","user_1","user_2","user_3","user_4","user_5","user_6"]
review_df
item_1 item_2 item_3 item_4 item_5
user_X 4 2 3 1 NaN
user_1 1 4 3 2 5.0
user_2 4 2 4 5 1.0
user_3 5 3 3 2 4.0
user_4 3 1 2 4 3.0
user_5 2 2 3 1 3.0
user_6 3 1 1 1 1.0

ピアソンの積立相関とユーザー毎平均レビュー値

#アイテム1~4まで各ユーザーの平均評価値を計算
review_mean = review_df.iloc[:,0:4].T.mean(skipna=True)
review_mean
user_X    2.50
user_1    2.50
user_2    3.75
user_3    3.25
user_4    2.50
user_5    2.00
user_6    1.50
dtype: float64
#ユーザー間の相関係数を見ると、user_Xはuser_3と強い正の相関であることがわかる。
review_corr = review_df.iloc[:,0:4].T.corr(method='pearson')
review_corr
user_X user_1 user_2 user_3 user_4 user_5 user_6
user_X 1.000000 -0.400000 -0.102598 0.923381 -0.200000 0.632456 0.774597
user_1 -0.400000 1.000000 -0.718185 -0.512989 -0.800000 0.316228 -0.774597
user_2 -0.102598 -0.718185 1.000000 -0.157895 0.923381 -0.324443 0.132453
user_3 0.923381 -0.512989 -0.157895 1.000000 -0.102598 0.324443 0.927173
user_4 -0.200000 -0.800000 0.923381 -0.102598 1.000000 -0.632456 0.258199
user_5 0.632456 0.316228 -0.324443 0.324443 -0.632456 1.000000 0.000000
user_6 0.774597 -0.774597 0.132453 0.927173 0.258199 0.000000 1.000000

let's 予測

#user_Xのitem_5の評価値を、近傍のuser_3とuser_6の相関係数を元に算出する
import numpy as np

rev3_5 = review_df.loc[['user_3'],['item_5']].values[0]
rev6_5 = review_df.loc[['user_6'],['item_5']].values[0]

avgX = review_mean['user_X']
avg3 = review_mean['user_3']
avg6 = review_mean['user_6']

corrX_3 = review_corr.loc[['user_X'],['user_3']].values[0]
corrX_6 = review_corr.loc[['user_X'],['user_6']].values[0]

answer = avgX + 1/((corrX_3 + corrX_6) *(corrX_3 * (rev3_5 - avg3) + corrX_6 * (rev6_5 - avg6)))
#推定したレビュー値が以下。
answer
array([ 4.42943831])

4か5のレビューを付けそうなので、アイテムをオススメして良さそうだと判断できました。