2章 - 推薦を行う
協調フィルタリングについての章
類似度を求める関数
入力
どのユーザーが、どのアイテムに、何点付けたか。
どのユーザーとどのユーザーの類似度を計算するか。
pref = [ {'A':5, 'B':4, 'C':1, 'D':0}, {'C':1, 'D':0}, {'A':4, 'B':2, 'C':0}, ]
?この点数は名義尺度, 順序尺度でも意味がある? --> 類似度の計算方法による。 cf. 尺度水準 - Wikipedia
出力
類似度が大きいほど、値が大きくなる値を返す。
ユークリッド距離を使うなり
def sim_euclidean(pref, a, b): duplicated = [x for x in pref[a] if x in pref[b]] if len(duplicated) == 0: return 0 ss = 0 for d in duplicated: ss += (pref[a][d] - pref[b][d]) ** 2 return 1 / (1 + ss)
ピアソンの相関係数なり
def sim_pearson(pref, a, b): duplicated = [x for x in pref[a] if x in pref[b]] n = len(duplicated) if n == 0: return 0 s = {person: sum([pref[person][it] for it in duplicated]) for person in [a,b]} ss = {person: sum([pref[person][it]**2 for it in duplicated]) for person in [a,b]} sp = sum([pref[a][it]*pref[b][it] for it in duplicated]) num = sp - (s[a]*s[b]/n) den = ((ss[a]-s[a]**2/n) * (ss[b]-s[b]**2/n))**0.5 if den == 0: return 0 return num/den
レコメンド
類似のユーザーが知りたいわけではなく、おすすめのアイテムが知りたい。
類似度と評点の積を類似度の和で除したもの(以下、スコア)を順序付けすれば良い。
入力
- どのユーザーが、どのアイテムに、何点付けたか。 = pref
- どのユーザーに対してアイテムをレコメンドするか
出力
- おすすめのアイテム
アイテムベースのフィルタリング
ユーザーベースのフィルタリングのデータ数が増える事による問題 - ユーザーごとに評価しているアイテムがバラバラで類似度の計算が難しい。
辞書をどのアイテムが、どのユーザーに、何点を付けられたか。という持ち方に変更する。
- 疎なデータセットで結果が良いらしい
まとめ
類似度の計算方法とデータセットの相性がキモ!