Skip to content

Instantly share code, notes, and snippets.

@yumere
Created July 4, 2015 09:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yumere/7e70bc754623182186d3 to your computer and use it in GitHub Desktop.
Save yumere/7e70bc754623182186d3 to your computer and use it in GitHub Desktop.
#coding: utf-8
from math import sqrt
critics = {
'Lisa Rose': {
'Lady in the Water': 2.5,
'Snakes on a Plane': 3.5,
'Just My Luck': 3.0,
'Superman Returns': 3.5,
'You, Me and Dupree': 2.5,
'The Night Listener': 3.0
},
'Gene Seymour': {
'Lady in the Water': 3.0,
'Snakes on a Plane': 3.5,
'Just My Luck': 1.5,
'Superman Returns': 5.0,
'The Night Listener': 3.0,
'You, Me and Dupree': 3.5
},
'Michael Phillips': {
'Lady in the Water': 2.5,
'Snakes on a Plane': 3.5,
'Superman Returns': 3.5,
'The Night Listener': 4.0
},
'Claudia Puig': {
'Snakes on a Plane': 3.5,
'Just My Luck': 3.0,
'The Night Listener': 4.5,
'Superman Returns': 4.0,
'You, Me and Dupree': 2.5
},
'Mick LaSalle': {
'Lady in the Water': 3.0,
'Snakes on a Plane': 4.0,
'Just My Luck': 2.0,
'Superman Returns': 3.0,
'The Night Listener': 3.0,
'You, Me and Dupree': 2.0
},
'Jack Mattheuws': {
'Lady in the Water': 3.0,
'Snakes on a Plane': 4.0,
'The Night Listener': 3.0,
'Superman Returns': 5.0,
'You, Me and Dupree': 3.5
},
'Toby': {
'Snakes on a Plane': 4.5,
'You, Me and Dupree': 1.0,
'Superman Returns': 4.0
}
}
# Euclidean Distance
def sim_distance(prefs, person1, person2):
# 공통 항목 추출
si = dict()
for item in prefs[person1]:
if item in prefs[person2]:
si[item] = 1
# 공통 평가 항목이 없는 경우 0 리턴
if len(si) == 0: return 0
# person1의 item이 person2에서도 존재한다면, person1과 person2의 item 평점 차이의 제곱한 값을 더한 후 제곱 근을 계산
sum_of_squares = sum([(prefs[person1][item] - prefs[person2][item])**2 for item in prefs[person1] if item in prefs[person2]])
return 1/(1+sqrt(sum_of_squares))
# Pearson correlation coefficient
def sim_pearson(prefs, p1, p2):
# 같이 평가한 항목들의 목록을 구함
si = dict()
for item in prefs[p1]:
if item in prefs[p2]: si[item] = 1
# 공통 항목 개수
n = len(si)
# 공통 항목이 없으면 0 리턴
if n==0: return 0
# 모든 선호도를 합산
sum1 = sum([prefs[p1][it] for it in si])
sum2 = sum([prefs[p2][it] for it in si])
# 제곱의 합을 계산
sum1Sq = sum([(prefs[p1][it])**2 for it in si])
sum2Sq = sum([(prefs[p2][it])**2 for it in si])
# 곱의 합을 계산
pSum = sum([prefs[p1][it] * prefs[p2][it] for it in si])
# 피어슨 점수 계산
num = pSum - (sum1*sum2/n)
den = sqrt((sum1Sq-pow(sum1,2)/n) * (sum2Sq-pow(sum2,2)/n))
if den==0: return 0
r = num/den
return r
# 선호도 dict에 최적의 상대편을 구함
# 결과 개수와 유사도 함수는 옵션
def top_matches(prefs, person, n=5, similarity=sim_pearson):
scores = [(similarity(prefs, person, other), other) for other in prefs if other!=person]
scores.sort()
scores.reverse()
return scores[:n]
# 다른 사람과의 순위의 가중 평균값을 이용해서 특정 사람을 추천
def get_recommendations(prefs, person, similarity=sim_pearson):
totals = dict()
simSums = dict()
for other in prefs:
# 나를 제외 하고
if other == person: continue
sim = similarity(prefs, person, other) # person과 other 사이의 상관계수 점수를 구함
# 0 이하 점수는 무시
if sim<=0: continue
for item in prefs[other]: # ohter가 본 영화들의 list
# 내가 보지 못한 영화만 대상
if item not in prefs[person] or prefs[person][item] == 0:
# 유사도 * 점수
totals.setdefault(item, 0)
totals[item] += prefs[other][item]*sim # other가 평가한 영화의 점수 * person과 other의 상관계수
# 유사도 합계
simSums.setdefault(item, 0)
simSums[item] += sim
# 정규화된 목록 생성
rankings = [ (total/simSums[item], item) for item, total in totals.items() ]
# 정렬된 목록 리턴
rankings.sort()
rankings.reverse()
return rankings
# 사람을 제품 기준으로 dict 변경
def transform_prefs(prefs):
result = dict()
for person in prefs:
for item in prefs[person]:
result.setdefault(item, dict())
result[item][person] = prefs[person][item]
return result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment