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
- どのユーザーに対してアイテムをレコメンドするか
出力
- おすすめのアイテム
アイテムベースのフィルタリング
ユーザーベースのフィルタリングのデータ数が増える事による問題 - ユーザーごとに評価しているアイテムがバラバラで類似度の計算が難しい。
辞書をどのアイテムが、どのユーザーに、何点を付けられたか。という持ち方に変更する。
- 疎なデータセットで結果が良いらしい
まとめ
類似度の計算方法とデータセットの相性がキモ!