본문 바로가기

Programming

집단지성 프로그래밍 2(Recommendations)

이 글은 토비 세가란 저, 윤종완 역의 집단지성 프로그래밍 책을 읽으며 개인적으로 공부하며 정리한 내용이다.


이전 글에서는 Machine LearningEuclidean Distance, Pearson Correlation Coefficient 를 이용해 두 사람의 상관도, 유사도를 구하는 것에 대해서 정리했다.(링크)

평론가 순위

이전 글을 통해 두 사람을 비교하는 함수를 만들었었다. 이제는 주어진 사람을 기준으로 다른 모든 사람들과의 점수를 계산해, 가장 유사한 사람 혹은 평론가를 찾는 함수를 만든다. 이 경우 나와 유사한 성향을 가진 영화 평론가를 찾을 수 있으므로 영화를 고를 때 좋은 판단을 할 수 있을 것이다.

이를 이용하려면 아래의 코드를 recommendations.py 파일에 추가한다.

위의 코드를 이용해 Toby와 가장 유사한 평론가들을 찾으면 아래와 같은 결과를 얻을 수 있다. 아래 결과를 보면 TobyLisa Rose와 가장 유사한 취향을 갖고 있음을 알 수 있다.

>>> import recommendations as re
>>> for score, other in re.top_matches(re.critics, "Toby"):
...     print "Toby and", other, score
...
Toby and Lisa Rose 0.991240707162
Toby and Mick LaSalle 0.924473451642
Toby and Claudia Puig 0.893405147442
Toby and Jack Mattheuws 0.66284898036
Toby and Gene Seymour 0.381246425832

항목 추천

위의 방법을 이용해, 나와 가장 유사한 평론가를 찾고 내가 보지 않았지만 그 평론가가 본 영화를 찾을 수도 있다. 하지만 이러한 방식으로는 내가 좋아할 만 하지만, 그 평론가가 평가하지 않은 영화가 존재할 수 있다. 이러한 문제를 해결하고 영화를 추천하기 위해 평론가 순위를 결정하는 가중점수를 만들어 항목 점수들을 계산해야한다. 모든 다른 평론가들의 평가를 계산한 후 나('Toby')와의 유사도를 그들이 각 영화에 준 점수와 곱한다

>>> for item in [item for item in re.critics if item!="Toby"]:
...     print "Toby and", item, round(re.sim_pearson(re.critics, "Toby", item),2)
...
Toby and Gene Seymour 0.38
Toby and Mick LaSalle 0.92
Toby and Claudia Puig 0.89
Toby and Lisa Rose 0.99
Toby and Michael Phillips 0.0
Toby and Jack Mattheuws 0.66
평론가 유사도 Night S.xNight Lady S.xLady Luck S.xLuck
Rose 0.99 3.0 2.97 2.5 2.48 3.0 2.97
Seymour 0.38 3.0 1.14 3.0 1.14 1.5 0.57
Puig 0.89 4.5 4.02 3.0 2.68
LaSalle 0.92 3.0 2.77 3.0 2.77 2.0 1.85
Matthews 0.66 3.0 1.99 3.0 1.99
합계 12.89 8.38 8.07
유사도 합계 3.84 2.95 3.18
합계/유사도 3.35 2.83 2.53

위의 표에는 각 평론가와의 상관계수 점수와 'Toby'가 평가하지 않은 세 영화(The Night Listener, Lady in the Water, Just My Luck)에 대한 평론가들의 평가 점수가 있다. 이 때, 위 표에서 S.x로 시작하는 곳은 유사도를 평가점수로 곱한 값이다. 이 곱한 값의 의미는 나와 유사한 사람이 평가한 영화에 좀 더 가중치를 둔다는 의미이다.


순위 계산에 단순 합계를 사용할 수 있지만, 이렇게 되면 많은 평론가들이 평가한 영화가 대부분 상위권에 올라올 수 있다. 이러한 문제점 때문에 영화를 리뷰한 모든 평론가들에 대한 유사도 합으로 나눈다.

이러한 연산을 프로그램에서 이용하려면 아래 코드를 recommendations.py에 추가한다

위 코드를 이용해 'Toby'에게 영화를 추천해 보면 아래와 같은 결과를 얻을 수 있다.

>>> import recommendations as re
>>> for score, item in re.get_recommendations(re.critics, "Toby"):
...     print item, round(score,2)
...
The Night Listener 3.35
Lady in the Water 2.83
Just My Luck 2.53

>>> for score, item in re.get_recommendations(re.critics, "Toby", similarity=re.sim_distance):
...     print item, round(score,2)
...
The Night Listener 3.48
Lady in the Water 2.77
Just My Luck 2.42

제품 매칭

위의 방법들은 두 사람의 유사도를 계산하고, 어떤 한 사람에게 유사도를 기반으로 제품들을 추천하는 방법이었다. 이번에는 어떠한 사이트를 처음 방문하는 사람일 경우 다른 사람과의 유사도를 계산할 수 없다. 이때 특정 제품을 좋아한 사람들이 좋아하는 다른 제품과의 유사도를 계산하여 추천하는 방식을 구현해 본다.


이 방식은 두 사람간의 유사도를 측정한 방식과 동일하다. 단지, 아래와 같이 사람을 제품으로 대치하면 된다.

{
    "Lisa Rose": {
        "Lady in the Water": 2.5,
        "Snakes on a Plane": 3.5
    },

    "Gene Seymour": {
        "Lady in the Water": 3.0,
        "Snaeks on a Plane": 3.5
    }
}

# 위를 아래로 변형

{
    "Lady in the Water": {
        "Lisa Rose": 2.5,
        "Gene Seymour": 3.0
    },

    "Snakes on a Plane": {
        "Lisa Rose": 3.5,
        "Gene Seymour": 3.5
    }
}

이를 코딩을 통해 변환 하려면 아래의 코드를 recommendations.py에 추가한다

이제 위 코드와 top_matches 함수를 이용해 Superman Returns와 유사한 영화를 찾으면 아래와 같은 결과가 나온다. 아래의 결과를 보면 음수 값이 존재하는데, 이는 Superman Returns를 좋아하는 사람들은 Just My Luck 영화를 싫어하는 경향이 있다는 의미이다.

>>> import recommendations as re
>>> transformed = re.transform_prefs(re.critics)
>>> for score, item in re.top_matches(transformed, "Superman Returns"):
...     print item, round(score,2)
...
You, Me and Dupree 0.66
Lady in the Water 0.49
Snakes on a Plane 0.0
The Night Listener -0.18
Just My Luck -0.42

recommendations.py여기에서 받을 수 있다.