3.1. 평균제곱차이 유사도 (Mean Squared Difference Similarity)
3.2. 코사인 유사도 (Cosine Similarity)
3.3. 피어슨 유사도 (Pearson Similarity)
</p>
def sim_msd(data, name1, name2):
sum = 0
count = 0
for movies in data[name1]:
if movies in data[name2]: #같은 영화를 봤다면
sum += pow(data[name1][movies]- data[name2][movies], 2)
count += 1
return 1 / ( 1 + (sum / count) )
sim_msd(ratings, 'Dave','Alex')
sim_msd(ratings, 'Dave','Andy')
코사인 유사도(Cosine Similarity)는 두 특성 벡터간의 유사 정도를 코사인 값으로 표현한 것임
Cosine Similarity는 −1에서 1까지의 값을 가지며, −1은 서로 완전히 반대되는 경우, 0은 서로 독립적인 경우, 1은 서로 완전히 같은 경우를 의미함
$$ x \cdot y = |x| |y| \cos\theta $$$$ \cos\theta = \dfrac{x \cdot y}{|x| |y|}$$이를 사용하여 Consine Similarity를 적용하면
두 벡터 의 스칼라곱(두 벡터로 스칼라를 계산하는 연산)은 다음과 같다:
이를 다음과 같이 코사인 함수를 사용해서도 표현함
import math
def sim_cosine(data, name1, name2):
sum_name1 = 0
sum_name2 = 0
sum_name1_name2 = 0
count = 0
for movies in data[name1]:
if movies in data[name2]: #같은 영화를 봤다면
sum_name1 += pow(data[name1][movies], 2)
sum_name2 += pow(data[name2][movies], 2)
sum_name1_name2 += data[name1][movies]*data[name2][movies]
return sum_name1_name2 / (math.sqrt(sum_name1)*math.sqrt(sum_name2))
sim_cosine(ratings, 'Dave','Alex')
sim_cosine(ratings, 'Dave','David')
sim_cosine(ratings, 'Dave','Andy')
피어슨 유사도는 두 벡터의 상관계수(Pearson correlation coefficient)를 의미
피어슨 유사도는 유사도가 가장 높을 경우 값이 1, 가장 낮을 경우 -1의 값을 가짐
특정인물의 점수기준이 극단적으로 너무 낮거나 높을 경우 유사도에 영향을 크게 주기 때문에, 이를 막기 위해 상관계수를 사용하는 방법
$\mu_u$는 사용자 $u$의 평균 평점
$\mu_i$는 상품 $i$의 평균 평점
def sim_pearson(data, name1, name2):
avg_name1 = 0
avg_name2 = 0
count = 0
for movies in data[name1]:
if movies in data[name2]: #같은 영화를 봤다면
avg_name1 = data[name1][movies]
avg_name2 = data[name2][movies]
count += 1
avg_name1 = avg_name1 / count
avg_name2 = avg_name2 / count
sum_name1 = 0
sum_name2 = 0
sum_name1_name2 = 0
count = 0
for movies in data[name1]:
if movies in data[name2]: #같은 영화를 봤다면
sum_name1 += pow(data[name1][movies] - avg_name1, 2)
sum_name2 += pow(data[name2][movies] - avg_name2, 2)
sum_name1_name2 += (data[name1][movies] - avg_name1) * (data[name2][movies] - avg_name2)
return sum_name1_name2 / (math.sqrt(sum_name1)*math.sqrt(sum_name2))
sim_pearson(ratings, 'Dave','Alex')
def top_match(data, name, index=3, sim_function=sim_pearson):
li=[]
for i in data: #딕셔너리를 돌고
if name!=i: #자기 자신이 아닐때만
li.append((sim_function(data,name,i),i)) #sim_function()을 통해 상관계수를 구하고 li[]에 추가
li.sort() #오름차순
li.reverse() #내림차순
return li[:index]
top_match(ratings, 'Dave', 3)
top_match(ratings, 'Dave', 3, sim_function=sim_msd)
top_match(ratings, 'Dave', 3, sim_function=sim_cosine)
top_match(ratings, 'Dave', 3, sim_function=sim_pearson)