これを読んでます。集合知プログラミング
協調フィルタリングとは?
参考:協調フィルタリング
協調フィルタリング(きょうちょうフィルタリング、Collaborative Filtering、CF)は、多くのユーザの嗜好情報を蓄積し、あるユーザと嗜好の類似した他のユーザの情報を用いて自動的に推論を行う方法論である
ユークリッド距離とは?
参考:ユークリッド距離
数学におけるユークリッド距離(ユークリッドきょり、英: Euclidean distance)またはユークリッド計量(ユークリッドけいりょう、英: Euclidean metric; ユークリッド距離函数)とは、人が定規で測るような二点間の「通常の」距離のことであり、ピタゴラスの公式によって与えられる。
つまりただの2点間の距離です。ピタゴラスの定理は、直角三角形の斜辺cは、他の2辺a、bとすると、が成り立ちます。よって、となります。
ユークリッド距離で嗜好が似てる人を探す
AさんとBさんがいて、芸能人あと、芸能人いがいるとします。Aさんは、あの好き度が10で、いの好き度が5です。Bさんは、あの好き度が3で、いの好き度が3です。AさんとBさんの嗜好の類似度をユークリッド距離で計算するには、x軸にあの好き度、y軸にいの好き度をおいて、Aさん、Bさんをプロットします。Aさん座標とBさん座標の距離が短ければ嗜好が似ていることになります。好き度が完全に同じであれば距離は0になります。座標同士の距離をピタゴラスの定理で計算できます。
でもこれだと2人の芸能人に対する嗜好の類似度しか測れません。複数の場合は、それぞれの芸能人の好き度の差の2乗を全部足せばいいらしいです。平方ユークリッド距離というらしいです。
Pythonでやってみる
データを用意する。
data = { 'A': {'あ': 10, 'い': 5, 'う': 3, 'え': 4, 'お': 9, 'か': 6}, 'B': {'あ': 3, 'い': 3, 'う': 3, 'え': 4, 'お': 3, 'か': 4}, 'C': {'あ': 2, 'い': 10, 'う': 4, 'え': 2, 'お': 4}, 'D': {'あ': 6, 'い': 3, 'う': 5, 'え': 2, 'お': 5}, 'E': {'あ': 8, 'い': 4, 'う': 3, 'え': 2, 'お': 9}, 'F': {'あ': 1, 'い': 2, 'う': 9, 'え': 3, 'お': 8}, 'G': {'あ': 9, 'い': 4, 'う': 3, 'え': 4, 'お': 9, 'か': 5}, 'H': {'あ': 10, 'い': 0, 'う': 1, 'え': 2, 'お': 5}, 'I': {'あ': 9, 'い': 10, 'う': 10, 'え': 5, 'お': 3}, 'J': {'あ': 3, 'い': 8, 'う': 8, 'え': 1, 'お': 5}, 'K': {'あ': 7, 'い': 4, 'う': 1, 'え': 2, 'お': 9}, 'L': {'あ': 8, 'い': 3, 'う': 1, 'え': 4, 'お': 1}, 'M': {'あ': 1, 'い': 5, 'う': 4, 'え': 5, 'お': 5}, 'N': {'あ': 1, 'い': 5, 'う': 4, 'え': 6, 'お': 3}, 'O': {'あ': 10, 'い':4} }
AさんとBさんの似ている度を、あ・いを対象に計測してみる
score = 1 / (1 + sqrt(pow(data['A']['あ'] - data['B']['あ'], 2) + pow(data['A']['い'] - data['B']['い'], 2))) print(score)
0.12077134402462537と表示されます。
Aさんと嗜好が似ている人順に表示する
#person1とperson2の嗜好似ている度を返す #高い方が似ている。0〜1の間の数値を返す def euclid_distance(data, person1, person2): item_list = [] for item in data[person1]: if item in data[person2]: item_list.append(item) if len(item_list) < 1: return 0 return 1 / (1 + sum([pow(data[person1][item] - data[person2][item], 2) for item in item_list])) #meに嗜好が似ている人順に並んだリストを返す def get_similar_list(data, me): person_list = {} for person in data: if person == me: continue person_list[person] = euclid_distance(data, me, person) return sorted(person_list.items(), key = itemgetter(1), reverse = True) a_sim = get_similar_list(data, 'A') for person in a_sim: print(person[0], person[1])
下記のように表示されます。
O 0.5 G 0.25 E 0.1 K 0.05263157894736842 D 0.022222222222222223 H 0.02 L 0.012987012987012988 B 0.010638297872340425 M 0.01 J 0.009174311926605505 I 0.008849557522123894 C 0.008333333333333333 N 0.008130081300813009 F 0.007751937984496124