駆け出しエンジニアの作業ノート

駆け出しエンジニアが作業ノート風にまとめるページ(関係無い事もしばしば)

協調フィルタリングの勉強

本日は協調フィルタリングの勉強を兼ねて、以下の記事のコードを再現実験を行いました。

 

qiita.com

 

ただし、エラーが発生したので、「similarity.py」と「recommend.py」は一部を書き換えて実行しました。

 

# similarity.py
import
math
import dataset


def get_similairty(person1, person2):

## 両者とも見た映画の集合を取る
set_person1 = set(dataset.dataset[person1].keys())
set_person2 = set(dataset.dataset[person2].keys())
set_both = set_person1.intersection(set_person2)

if len(set_both)==0: #共通でみた映画がない場合は類似度を0とする
return 0

list_destance = []

for item in set_both:
# 同じ映画のレビュー点の差の2乗を計算
# この数値が大きいほど「気が合わない」=「似ていない」と定義できる
distance = pow(dataset.dataset[person1][item]-dataset.dataset[person2][item], 2)
list_destance.append(distance)

return 1/(1+math.sqrt(sum(list_destance))) #各映画の気の合わなさの合計の逆比的な指標を返す

if __name__ == '__main__':
get_similairty()

 

 

# recommend.py 
import
dataset
import similarity

def get_recommend(person, top_N):

totals = {}
simSums = {} #推薦度スコアを入れるための箱を作っておく

# 自分以外のユーザのリストを取得してFor文を回す
# -> 各人との類似度、及び各人からの(まだ本人が見てない)映画の推薦スコアを計算するため
list_others = dataset.dataset.keys()
list_others = list(list_others)
list_others.remove(person)

for other in list_others:
# 本人がまだ見たことが無い映画の集合を取得
set_other = set(dataset.dataset[other])
set_person = set(dataset.dataset[person])
set_new_movie = set_other.difference(set_person)

# あるユーザと本人の類似度を計算(simは0~1の数字)
sim = similarity.get_similairty(person, other)

# (本人がまだ見たことがない)映画のリストでFor分を回す
for item in set_new_movie:

# "類似度 x レビュー点数" を推薦度のスコアとして、全ユーザで積算する
totals.setdefault(item,0)
totals[item] += dataset.dataset[other][item]*sim

# またユーザの類似度の積算値をとっておき、これで上記のスコアを除する
simSums.setdefault(item,0)
simSums[item] += sim

rankings = [(total/simSums[item],item) for item,total in totals.items()]
rankings.sort()
rankings.reverse()

result = [i[1] for i in rankings][:top_N]
print(result)

if __name__ == '__main__':
get_recommend('Toby',2)

 

結果は以下の通りとなりました。

 

['The Night Listener', 'Lady in the Water'] 

 

元記事と同じ結果が出力されました。今後はこのコードを使って、last.fmの分析に使えたらと思います。