AI

協調フィルタリング(ユークリッド距離)

これを読んでます。集合知プログラミング

集合知プログラミング

参考:協調フィルタリングでアイテムの推薦をする

協調フィルタリングとは?

参考:協調フィルタリング

協調フィルタリング(きょうちょうフィルタリング、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