matsu7874のブログ

和歌山出身プログラマmatsu7874が書いています。Python3と時々C++11を書きます。

メモ: 集合知プログラミング2章 推薦を行う

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
  • どのユーザーに対してアイテムをレコメンドするか

    出力

  • おすすめのアイテム

アイテムベースのフィルタリング

ユーザーベースのフィルタリングのデータ数が増える事による問題 - ユーザーごとに評価しているアイテムがバラバラで類似度の計算が難しい。

辞書をどのアイテムが、どのユーザーに、何点を付けられたか。という持ち方に変更する。

まとめ

類似度の計算方法とデータセットの相性がキモ!