タイトルの通りですが、Movie Lendsから入手したサンプルデータを用いて、あるユーザが評価した評価データからコサイン類似度が0.9以上のアイテムから最も遠いユークリッド距離を持つものを算出したいのですが、いかんせん初心者なのでどのようなプログラムを組めばいいかわからないです。
コサイン類似度とユークリッド距離を指定したユーザ同士で算出する方法は勉強して何とか実装して理解できる状況まで行ったのですが、自分で取得したデータ量では足りなかったので、サンプルデータが多いMovie Lensを用いて実施しようと思いました。
コサイン類似度(1)とユークリッド距離(2)の算出方法は以下になっていて、そこからさまざまなブログを拝見して以下のコード(3)から順位付けできるようにはなったので、それを活用してタイトルのようなことをしたいんですが、コサイン類似度を一定以下にするという条件で躓き、そこからユークリッド距離のソートもできない状態です。
下記のコードではデータセットは自分で設定したものになっていますが、理想はMovie Lensの膨大なデータを用いたいです。
イメージとしては、あるユーザのコサイン類似度が0.9以上の絞り込みをして、そこからユークリッド距離のソートをすればやりたいことができると思っています。
端的に言えばMovie Lensのデータからコサイン類似度の絞り込みをして、ユークリッド距離のソートをしたいです。
以下にコードを示しておきます。
理解していること:それぞれユークリッド距離などの算出の仕方
理解していないこと:Movie Lensのデータをデータセットとして扱うこと
あるユーザとコサイン類似度の角度が一定以上ある人だけを絞る方法
python
1(1)def new_recomend(person1, person2): 2 person1_reviews = dataset[person1] 3 person2_reviews = dataset[person2] 4 5 # 共通のものを取得 6 both_rated = person1_reviews.keys() & person2_reviews.keys() 7 if not both_rated: 8 return 0 # 共通のものが存在しない場合 9 10 # 共通のものの点数をそれぞれ取得 11 scores1 = [person1_reviews[item] for item in both_rated] 12 scores2 = [person2_reviews[item] for item in both_rated] 13 for item, score1, score2 in zip(both_rated, scores1, scores2): 14 15 # コサイン類似度の算出 16 cos_similarity = np.dot(scores1, scores2) / (np.linalg.norm(scores1) * np.linalg.norm(scores2)) 17 18 return cos_similarity 19 20 21print(cos_similarity("A", "B"))
pyton
1(2)from math import sqrt 2import numpy as np 3def similarity_score(person1,person2): 4 5 both_viewed = {} # 双方に共通のアイテムを取得 6 7 ##両者とも見た映画の集合を取る 8 set_person1 = set(dataset[person1].keys()) 9 set_person2 = set(dataset[person2].keys()) 10 set_both = set_person1.intersection(set_person2) 11 12 # 共通のアイテムを持っていなければ 0 を返す 13 if len(set_both) == 0: 14 return 0 15 16 17 #ユークリッド距離の計算 18 sum_of_eclidean_distance = [] 19 for item in set_both: 20 sum_of_eclidean_distance.append( 21 pow(dataset[person1][item] - dataset[person2][item], 2) 22 ) 23 total_of_eclidean_distance = sum(sum_of_eclidean_distance) 24 25 #return sum_of_eclidean_distanceこれで各アイテム間のユークリッド距離が出る 26 27 return 1 / (1 + sqrt(total_of_eclidean_distance)) 28 29similarity_score('A','B')
python
1(3)def most_eclidean_distance(person, number_of_users): 2 # 似たユーザーとその類似度を返す 3 4 eclidean_distance = [(similarity_score(person, other_person), other_person) 5 for other_person in dataset if other_person != person] 6 7 # 最高の類似度の人物が最初になるようにソートする 8 eclidean_distance.sort() 9 #reverse消すと低い順になる 10 eclidean_distance.reverse() 11 return eclidean_distance[0:number_of_users] 12 13print("ユークリッド距離",most_eclidean_distance('A',10))
あなたの回答
tips
プレビュー