본문 바로가기
python 및 머신러닝/집단지성 프로그래밍

[Programming Collective Intelligence] - 집단지성 프로그래밍 2장 추천시스템 만들기

by java개발자 2015. 8. 22.
# -*- coding: utf-8 -*-
from myutil import consolePrintWithLineNumber as c
'''
Created on 2015. 5. 7.
revised on 2015. 8. 18.

@author: Administrator

  2장 추천시스템 만들기
    2.유사 사용자 찾기 - 유사도 측정
      > 나와 다른 사람간의 공통된 항목에 대한 점수를 비교하여 유사도를 측정한다.
        >> 유클리디안 거리점수 : 절대적인 값의 비교
        >> 피어슨 상관점수 : 얼마나 직선으로 잘 표현되나?
    3.평론가 순위 - 나와 가장 비슷한 사람 찾기
    4.항목추천
      > 나에게 없는 항목을 추천 받기
      >> 나와 유사한 사람에게 가중치(유사도)를 곱해서 그 사람의 의견에 더 많은 영향을 받도록
    5.제품 매칭 - 사람과 사물을 바꿔서, 1,2,3을 적용해보기 - 제품에게 제품을 소개하자
    6.딜리셔스 링크 추천 기능 만들기 - 사이트 변경으로 PASS
    7.항목 기반 필터링 - 항목간의 유사도를 미리 측정해놓자 > 딕셔너리에 저장
    8.무비렌즈 데이터 세트 이용하기
    9.사용자 기반 필터링과 항목 기반 필터링
    
'''

# 2장 추천시스템 만들기
# 2-2 선호 정보 수집

critics = {'리사': {'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},
         '지니': {'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},
         '마이클': {'Lady in the Water': 2.5,
                              'Snakes on a Plane': 3.0,
                              'Superman Returns': 3.5,
                              'The Night Listener': 4.0},
         '클라우디아': {'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},
         '라살리': {'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},
         '잭': {'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},
         '토비': {'Snakes on a Plane':4.5,
                  'You, Me and Dupree':1.0,
                  'Superman Returns':4.0},
         '토비2': {'Snakes on a Plane':4.0,
                  'You, Me and Dupree':0.5,
                  'Superman Returns':3.5}
         }

# 30p
c(critics['리사']['Lady in the Water'])
critics['토비']['Snakes on a Plane'] = 4.5
c(critics['토비'])

# 2-3 유사 사용자 찾기
# 2-3-1 유클리디안 거리점수

# 31p
from math import sqrt

  # 오타 - 정확히 보자면, pow(5... 가 아니라 pow(4.5 .. 이다
c(sqrt(pow(4.5 - 4, 2) + pow(2 - 1, 2)))
c(1 / (1 + sqrt(pow(5 - 4, 2) + pow(2 - 1, 2))))

'''
  person1 과 person2의 유사도 측정
  기존 문제점 : si를 단순히 크기 측정에만 사용하고 있다. 
  아래 함수 내용을 효율적으로 변경함 > si를 재사용하기 위해, 결과는 정확히 일치한다.
'''
def sim_distance(db, person1, person2):
  si = {}    # 작업할 항목(영화) 분류
  for item in db[person1]: 
    if item in db[person2]:    # p1, p2가 가진 교집합의 경우에만 작업
        si[item] = 1    # 작업할 항목을 담아놓는다.

  # 공통항목(교집합)이 없는 경우 return
  if len(si) == 0: return 0
  
  sum_of_squares = sum([pow(db[person1][item] - db[person2][item], 2) for item in si])

  return 1 / (1 + sqrt(sum_of_squares))

c(sim_distance(critics, '리사', '지니'))    # p1, p2 순서는 상관없음

# 응용 : 다른 사용자들도 비교해서 순위 측정
def practice1():
  critics_key_list = list(critics.keys())
  temp = set()
  # 두 사람을 각각 짝을 지은다. 자신은 자신과 짝이 되지 못하고, 앞뒤로 중복되지 않도록.
  # > 잘못된예: 리사-지니, 지니-리사
  for index, x in enumerate(critics_key_list):
    for y in critics_key_list[index + 1:]:
      temp.add((x, y))
  res_d = {p1 + '-' + p2:sim_distance(critics, p1, p2) for (p1, p2) in temp}
  # 순위를 매겨보자  
  from operator import itemgetter
  res_l = list(res_d.items())    # 딕셔너리를 리스트<튜플>로 변경함
  res_l.sort(key=itemgetter(1), reverse=True)
  return res_l
c(practice1())

# 2-3-2 피어슨 상관점수

def sim_pearson(db, p1, p2):
  si = {}
  for item in db[p1]: 
    if item in db[p2]: 
      si[item] = 1

  if len(si) == 0: return 0

  n = len(si)

  sum1 = sum([db[p1][it] for it in si])
  sum2 = sum([db[p2][it] for it in si])
  
  sum1Sq = sum([pow(db[p1][it], 2) for it in si])
  sum2Sq = sum([pow(db[p2][it], 2) for it in si])    
  
  pSum = sum([db[p1][it] * db[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

c(sim_pearson(critics, '리사', '지니'))
# 항목을 비교하는 다른 측정 지표 : https://en.wikipedia.org/wiki/Metric_%28mathematics%29#Examples

# 2-3-3 유사도 측정 지표 선택 방법
# 평론가 순위
def topMatches(db, person, n=5, similarity=sim_pearson):
  scores = [(similarity(db, person, other), other) for other in db if other != person]
  scores.sort()
  scores.reverse()
  return scores[0:n]

c(topMatches(critics, '토비', 3))

# 2-4 항목 추천

def getRecommendations(db, person, similarity=sim_pearson):
  totals = {}    # 합계
  simSums = {}    # 유사도합계
  for other in db:

    if other == person: continue
    sim = similarity(db, person, other)    # 나와 같지 않은 특정 사람과의 유사도를 구한다.

    if sim <= 0: continue
    for item in db[other]:    # 특정 사람이 평가한 영화목록을 하나씩 살펴본다.
        
      if item not in db[person] or db[person][item] == 0:    # 특정 사람의 영화목록중 내가 보지 않은 것만 하나씩 살펴본다.
        # Sum of similarities
        simSums.setdefault(item, 0)
        simSums[item] += sim    # 유사도sim 합계
        # Similarity * Score
        totals.setdefault(item, 0)
        totals[item] += db[other][item] * sim    # 유사도*영화점수 를 구성해 나간다.

  # c(totals)
  # c(totals.items())
  # c(simSums)
  # Create the normalized list
  rankings = [(total / simSums[item], item) for item, total in totals.items()]

  # Return the sorted list
  rankings.sort()
  rankings.reverse()
  return rankings

c(getRecommendations(critics, '토비'))
c(getRecommendations(critics, '토비', sim_distance))

# 2-5 제품 매칭

def transformPrefs(db):
  
  result = {}
  for person in db:
    for item in db[person]:
      result.setdefault(item, {})
      
      result[item][person] = db[person][item]
  return result

movies = transformPrefs(critics)
c(movies)

c(topMatches(movies, 'Superman Returns'))
c(getRecommendations(movies, 'Just My Luck'))
c(sim_pearson(movies, 'Superman Returns', 'Just My Luck'))

'''
  2-6 딜리셔스 링크 추천 기능 만들기
  http://del.icio.us 사이트의 API URL 이 변경된 듯하다.
  delicious.py를 거치지 않고, feedparser를 이용해서, rss접속 및 파싱까지 직접 하자.
  >>>... 포기....

# 에러 관련 http://stackoverflow.com/questions/514371/whats-the-bad-magic-number-error
import feedparser
def get_popular(tag):
  return feedparser.parse('http://feeds.delicious.com/v2/rss/tag/'+tag)
c(get_popular('programming'))
def get_urlposts(href):
  return feedparser.parse(href)
c(get_popular('http://feeds.delicious.com/v2/rss/pebre79'))

'''

# 2-7 항목 기반 필터링
def calculateSimilarItems(db, n=10):
  result = {}
  movies = transformPrefs(db)
  c = 0
  for item in movies:
    c += 1
    if c % 100 == 0:
      print("%d / %d" % (c, len(movies)))
    result[item] = topMatches(movies, item, n=n, similarity=sim_distance)    # similarity=sim_pearson 가능(결과가 많이 달라진다.)
  
  return result
itemsim = calculateSimilarItems(critics)
c(itemsim)

def getRecommendedItems(db, itemsim, username):
  userRatings = db[username]
  scores = {}
  totalSim = {}
  
  for (item1, rating) in userRatings.items():
    for(similarity, item2) in itemsim[item1]:
      
      if item2 in userRatings: continue
      
      totalSim.setdefault(item2, 0)
      totalSim[item2] += similarity
      
      scores.setdefault(item2, 0)
      scores[item2] += similarity * rating
      
  rankings = [(score / totalSim[item], item) for item, score in scores.items()]
  
  rankings.sort()
  rankings.reverse()
  return rankings
c(getRecommendedItems(critics, itemsim, '토비'))

# 추천!! - 결과가 서로 많이 다르다-_-;; ?????
# 39 페이지 결과(sim_pearson)
# 39 페이지 결과(sim_distance)
# 49p 페이지 결과(sim_pearson)
# 49p 페이지 결과(sim_distance)
# [(3.3477895267131013, 'The Night Listener'), (2.832549918264162, 'Lady in the Water'), (2.5309807037655645, 'Just My Luck')]
# [(3.4571286944914226, 'The Night Listener'), (2.778584003814923, 'Lady in the Water'), (2.422482042361917, 'Just My Luck')]
# [(3.610031066802183, 'Lady in the Water'), (3.5313950341859766, 'The Night Listener'), (2.960999860724268, 'Just My Luck')]
# [(3.1667425234070894, 'The Night Listener'), (2.9366294028444355, 'Just My Luck'), (2.8687673926264674, 'Lady in the Water')]

# 2-8 무비렌즈
import codecs    # 다음 에러 때문에 사용함. UnicodeDecodeError: 'cp949' codec can't decode byte 0xe9 in position 2892: illegal multibyte sequence

def loadMovieLens():
  movies = {}
  
  for line in open('u.item', 'r', encoding='UTF-8'):
    movieId, title = line.split('|')[0:2]
    movies[movieId] = title 
    
  db = {}
  for line in open('u.data'):
    userId, movieId, rating, ts = line.split('\t')
    db.setdefault(userId, {})
    db[userId][movies[movieId]] = float(rating)
    
  # 콘솔에 출력하면, 로딩시간 길어져서,, 파일로 출력
#   f = open('result.txt', 'w', encoding='UTF-8')
#   f.write(str(db))
#   f.close()  
  
  return db
    
lensdb = loadMovieLens()
c(lensdb['87'])
c(getRecommendations(lensdb, '87')[0:10])
# [(5.0, 'They Made Me a Criminal (1939)'), (5.0, 'Star Kid (1997)'), (5.0, 'Santa with Muscles (1996)'), (5.0, 'Saint of Fort Washington, The (1993)'), (5.0, 'Marlene Dietrich: Shadow and Light (1996) '), (5.0, 'Great Day in Harlem, A (1994)'), (5.0, 'Entertaining Angels: The Dorothy Day Story (1996)'), (5.0, 'Boys, Les (1997)'), (4.89884443128923, 'Legal Deceit (1997)'), (4.815019082242709, 'Letter From Death Row, A (1998)')]

lensSim = calculateSimilarItems(lensdb, n=50)
c(getRecommendedItems(lensdb, lensSim, '87')[0:10])
# [(5.0, "What's Eating Gilbert Grape (1993)"), (5.0, 'Vertigo (1958)'), (5.0, 'Usual Suspects, The (1995)'), (5.0, 'Toy Story (1995)'), (5.0, 'Titanic (1997)'), (5.0, 'Sword in the Stone, The (1963)'), (5.0, 'Stand by Me (1986)'), (5.0, 'Sling Blade (1996)'), (5.0, 'Silence of the Lambs, The (1991)'), (5.0, 'Shining, The (1980)')]

# 2-9 사용자 기반 vs 항목 기반
'''
  책 정리:
  <항목 기반> : 큰 데이터 세트의 경우 추천 목록을 얻을때 <사용자 기반> 에 비해 훨씬 빠름. (단, 유사도 테이블을 유지하기 위함 부담 증가.)
                데이터 세트의 희박 정도에 따른 정확도 차이 발생
    모든 평론가들이 거의 모든 영화를 평가 == 모든 사용자가 대부분의 항목에 관련되어 있으면 데이터 세트는 희박하지 않고, 조밀...
       데이터 세트가 희박한 경우 : 항목 기반 필터링 기법이 더 잘 동작함.
       조밀한 데이터 세트의 경우 : 둘다 비슷하게 동작함.
  <사용자 기반> : 구현 용이, 추가 단계 없음.

  내 느낌:
    사용자 기반 -> 항목 기반 으로 데이터셋을 변경할 때, 비용이 많이 든다. 각 데이터를 빼와서 하나하나 다시 집합을 만들어야 하기 때문에..
    두개의 차이를 모르겠다. 어차피 무엇을 기준으로 하느냐 차이인데...
      특정 사람에게 항목을 추천할 때...
      <사용자 기반> : 사람간  항목의 유사도를 일일이 계산해서 가장 비슷한 사람의 항목을 추천 한다.
      <항목 기반> : (항목간 유사도 미리계산) + 내가 가진 항목점수와 (내가 가진 항목과 나에게 없는 항목과의 유사도)를 곱한 합이 가장 높은 항목을 추천 한다.
'''

'''
  결론
    처음에는 유클리디안 거리 또는 피어슨 상관계수의 차이에 집중했었는데, 어차피 절대치, 상대치의 차이일 뿐이고....
    결국 사용자기반, 항목기반의 차이를 정확히 아는 것이 중요한듯. 데이터세트의 크기, 밀도와 관련해서 무엇을 선택해야 하는지...
    정리를 하면서, 나름 이해해 보려고 노력中...
  
  >> 디자인 패턴도 공부할 당시에만 이해하고, 하루 지나면 까먹는 것처럼... 이것도 뭔가 잘 정리가 안된다;;;
  수학공식으로 만들어 놓으면, 좀더 이해하기 쉬울까??
'''











70 >  2.5
72 >  {'You, Me and Dupree': 1.0, 'Snakes on a Plane': 4.5, 'Superman Returns': 4.0}
81 >  1.118033988749895
82 >  0.4142135623730951
102 >  0.29429805508554946
119 >  [('지니-잭', 0.6666666666666666), ('토비-토비2', 0.5358983848622454), ('마이클-클라우디아', 0.5358983848622454), ('토비2-마이클', 0.5), ('리사-마이클', 0.4721359549995794), ('라살리-리사', 0.4142135623730951), ('라살리-토비', 0.4), ('라살리-토비2', 0.38742588672279304), ('라살리-마이클', 0.38742588672279304), ('리사-클라우디아', 0.38742588672279304), ('토비-마이클', 0.38742588672279304), ('토비-클라우디아', 0.3567891723253309), ('토비-리사', 0.3483314773547883), ('잭-리사', 0.3405424265831667), ('지니-마이클', 0.3405424265831667), ('토비2-리사', 0.3266316347104093), ('잭-마이클', 0.32037724101704074), ('잭-클라우디아', 0.32037724101704074), ('토비2-클라우디아', 0.32037724101704074), ('라살리-클라우디아', 0.31451985913875646), ('지니-리사', 0.29429805508554946), ('라살리-잭', 0.2857142857142857), ('지니-클라우디아', 0.28172904669025317), ('라살리-지니', 0.27792629762666365), ('잭-토비', 0.2674788903885893), ('지니-토비', 0.25824569976124334), ('잭-토비2', 0.22966848451216434), ('지니-토비2', 0.22772999919644132)]
149 >  0.39605901719066977
160 >  [(1.0, '토비2'), (0.9912407071619299, '리사'), (0.9244734516419049, '라살리')]
194 >  [(3.3477895267131013, 'The Night Listener'), (2.832549918264162, 'Lady in the Water'), (2.530980703765565, 'Just My Luck')]
195 >  [(3.457128694491423, 'The Night Listener'), (2.778584003814924, 'Lady in the Water'), (2.422482042361917, 'Just My Luck')]
210 >  {'Snakes on a Plane': {'라살리': 4.0, '지니': 3.5, '토비2': 4.0, '토비': 4.5, '리사': 3.5, '마이클': 3.0, '잭': 4.0, '클라우디아': 3.5}, 'Superman Returns': {'라살리': 3.0, '지니': 5.0, '토비2': 3.5, '토비': 4.0, '리사': 3.5, '마이클': 3.5, '잭': 5.0, '클라우디아': 4.0}, 'Just My Luck': {'라살리': 2.0, '지니': 1.5, '리사': 3.0, '클라우디아': 3.0}, 'You, Me and Dupree': {'라살리': 2.0, '지니': 3.5, '토비2': 0.5, '토비': 1.0, '리사': 2.5, '잭': 3.5, '클라우디아': 2.5}, 'Lady in the Water': {'라살리': 3.0, '지니': 3.0, '잭': 3.0, '마이클': 2.5, '리사': 2.5}, 'The Night Listener': {'라살리': 3.0, '지니': 3.0, '잭': 3.0, '리사': 3.0, '마이클': 4.0, '클라우디아': 4.5}}
212 >  [(0.6644105970267492, 'You, Me and Dupree'), (0.4879500364742689, 'Lady in the Water'), (0.05292561240249631, 'Snakes on a Plane'), (-0.1798471947990544, 'The Night Listener'), (-0.42289003161103106, 'Just My Luck')]
213 >  [(4.0, '마이클'), (3.0, '잭')]
214 >  -0.42289003161103106
246 >  {'Snakes on a Plane': [(0.3483314773547883, 'Lady in the Water'), (0.32037724101704074, 'The Night Listener'), (0.30383243470068705, 'Superman Returns'), (0.2553967929896867, 'Just My Luck'), (0.15278212615814146, 'You, Me and Dupree')], 'Superman Returns': [(0.30383243470068705, 'Snakes on a Plane'), (0.252650308587072, 'The Night Listener'), (0.2402530733520421, 'Lady in the Water'), (0.20799159651347807, 'Just My Luck'), (0.16202097927744855, 'You, Me and Dupree')], 'Just My Luck': [(0.3483314773547883, 'Lady in the Water'), (0.32037724101704074, 'You, Me and Dupree'), (0.2989350844248255, 'The Night Listener'), (0.2553967929896867, 'Snakes on a Plane'), (0.20799159651347807, 'Superman Returns')], 'You, Me and Dupree': [(0.4494897427831781, 'Lady in the Water'), (0.32037724101704074, 'Just My Luck'), (0.29429805508554946, 'The Night Listener'), (0.16202097927744855, 'Superman Returns'), (0.15278212615814146, 'Snakes on a Plane')], 'Lady in the Water': [(0.4494897427831781, 'You, Me and Dupree'), (0.38742588672279304, 'The Night Listener'), (0.3483314773547883, 'Snakes on a Plane'), (0.3483314773547883, 'Just My Luck'), (0.2402530733520421, 'Superman Returns')], 'The Night Listener': [(0.38742588672279304, 'Lady in the Water'), (0.32037724101704074, 'Snakes on a Plane'), (0.2989350844248255, 'Just My Luck'), (0.29429805508554946, 'You, Me and Dupree'), (0.252650308587072, 'Superman Returns')]}
269 >  [(3.1667425234070894, 'The Night Listener'), (2.9366294028444346, 'Just My Luck'), (2.868767392626467, 'Lady in the Water')]
305 >  {'Heathers (1989)': 3.0, 'Addicted to Love (1997)': 4.0, 'Cliffhanger (1993)': 3.0, "Joe's Apartment (1996)": 2.0, 'Terminator, The (1984)': 5.0, 'Groundhog Day (1993)': 5.0, 'Jimmy Hollywood (1994)': 3.0, 'Multiplicity (1996)': 3.0, 'Raging Bull (1980)': 3.0, 'Shadow, The (1994)': 3.0, 'Strictly Ballroom (1992)': 3.0, 'In the Line of Fire (1993)': 5.0, 'Four Weddings and a Funeral (1994)': 5.0, 'Clear and Present Danger (1994)': 5.0, 'Reality Bites (1994)': 3.0, 'Quiet Man, The (1952)': 5.0, 'Adventures of Priscilla, Queen of the Desert, The (1994)': 3.0, "City Slickers II: The Legend of Curly's Gold (1994)": 3.0, 'Bananas (1971)': 5.0, 'Big Squeeze, The (1996)': 2.0, 'True Lies (1994)': 5.0, 'Die Hard: With a Vengeance (1995)': 4.0, 'Apocalypse Now (1979)': 4.0, 'Home Alone (1990)': 4.0, 'Crow, The (1994)': 3.0, 'Return of the Pink Panther, The (1974)': 4.0, 'Lightning Jack (1994)': 3.0, 'House Arrest (1996)': 3.0, 'Sleepers (1996)': 4.0, 'Searching for Bobby Fischer (1993)': 4.0, 'Blade Runner (1982)': 4.0, 'Jurassic Park (1993)': 5.0, 'Dead Poets Society (1989)': 5.0, 'Cool Hand Luke (1967)': 5.0, 'Addams Family Values (1993)': 2.0, 'Coneheads (1993)': 4.0, 'Brady Bunch Movie, The (1995)': 2.0, 'Truth About Cats & Dogs, The (1996)': 4.0, 'Top Gun (1986)': 5.0, 'Demolition Man (1993)': 3.0, 'Baby-Sitters Club, The (1995)': 2.0, 'Citizen Kane (1941)': 4.0, 'Vegas Vacation (1997)': 4.0, 'Dead Man Walking (1995)': 4.0, 'Conan the Barbarian (1981)': 3.0, 'Swimming with Sharks (1995)': 3.0, 'Tommy Boy (1995)': 4.0, 'Fargo (1996)': 5.0, 'Sneakers (1992)': 4.0, 'Hoop Dreams (1994)': 4.0, 'Shawshank Redemption, The (1994)': 5.0, 'Man of the House (1995)': 3.0, 'Heat (1995)': 3.0, 'Fish Called Wanda, A (1988)': 5.0, 'Hot Shots! Part Deux (1993)': 4.0, 'Treasure of the Sierra Madre, The (1948)': 4.0, 'Speed (1994)': 5.0, 'Birdcage, The (1996)': 4.0, 'Full Metal Jacket (1987)': 4.0, 'Forget Paris (1995)': 4.0, 'Private Benjamin (1980)': 4.0, 'Victor/Victoria (1982)': 4.0, 'Cowboy Way, The (1994)': 3.0, 'M*A*S*H (1970)': 5.0, 'Hard Target (1993)': 4.0, 'While You Were Sleeping (1995)': 5.0, 'Terminator 2: Judgment Day (1991)': 5.0, 'Ace Ventura: Pet Detective (1994)': 4.0, 'Days of Thunder (1990)': 5.0, 'Back to the Future (1985)': 5.0, 'Desperado (1995)': 3.0, 'Wizard of Oz, The (1939)': 5.0, 'When Harry Met Sally... (1989)': 5.0, 'Star Trek: First Contact (1996)': 4.0, "Singin' in the Rain (1952)": 4.0, 'Mask, The (1994)': 3.0, 'Big Green, The (1995)': 3.0, 'Alien (1979)': 4.0, 'Deer Hunter, The (1978)': 3.0, 'I Love Trouble (1994)': 3.0, 'French Kiss (1995)': 5.0, 'Kingpin (1996)': 4.0, 'Dunston Checks In (1996)': 1.0, 'Strange Days (1995)': 3.0, 'Sabrina (1995)': 4.0, 'Sleeper (1973)': 4.0, 'Pulp Fiction (1994)': 4.0, 'Twelve Monkeys (1995)': 4.0, 'This Is Spinal Tap (1984)': 5.0, 'Indiana Jones and the Last Crusade (1989)': 5.0, 'Low Down Dirty Shame, A (1994)': 3.0, 'Cops and Robbersons (1994)': 3.0, 'Dances with Wolves (1990)': 5.0, 'Babe (1995)': 5.0, 'Return of the Jedi (1983)': 5.0, 'Wyatt Earp (1994)': 3.0, "Ulee's Gold (1997)": 3.0, 'Mrs. Doubtfire (1993)': 4.0, 'Con Air (1997)': 4.0, 'Grease (1978)': 4.0, 'Professional, The (1994)': 4.0, 'Broken Arrow (1996)': 3.0, 'Mars Attacks! (1996)': 3.0, 'Stargate (1994)': 5.0, 'Clueless (1995)': 4.0, 'Godfather, The (1972)': 4.0, 'Jack (1996)': 3.0, 'Renaissance Man (1994)': 5.0, 'Santa Clause, The (1994)': 4.0, 'Major Payne (1994)': 3.0, 'Mighty Aphrodite (1995)': 3.0, 'In the Army Now (1994)': 4.0, 'Muppet Treasure Island (1996)': 3.0, 'Nutty Professor, The (1996)': 4.0, 'Under Siege (1992)': 4.0, 'Prefontaine (1997)': 5.0, 'Blues Brothers, The (1980)': 5.0, 'Great White Hype, The (1996)': 3.0, 'Speed 2: Cruise Control (1997)': 3.0, 'Die Hard (1988)': 4.0, 'Air Force One (1997)': 3.0, 'Adventures of Robin Hood, The (1938)': 5.0, 'Dave (1993)': 4.0, 'Fugitive, The (1993)': 5.0, 'Endless Summer 2, The (1994)': 3.0, 'Sting, The (1973)': 5.0, 'Evil Dead II (1987)': 2.0, "Schindler's List (1993)": 4.0, 'Sleepless in Seattle (1993)': 5.0, 'Dumb & Dumber (1994)': 4.0, 'I.Q. (1994)': 5.0, 'Maverick (1994)': 3.0, 'Down Periscope (1996)': 4.0, 'Star Trek IV: The Voyage Home (1986)': 5.0, 'Supercop (1992)': 3.0, 'Jeffrey (1995)': 3.0, 'First Wives Club, The (1996)': 2.0, 'Batman & Robin (1997)': 4.0, 'Star Trek III: The Search for Spock (1984)': 4.0, 'Empire Strikes Back, The (1980)': 5.0, "Monty Python's Life of Brian (1979)": 4.0, 'Speechless (1994)': 4.0, 'Get Shorty (1995)': 5.0, "It's a Wonderful Life (1946)": 5.0, '2001: A Space Odyssey (1968)': 5.0, 'Up in Smoke (1978)': 3.0, 'Net, The (1995)': 5.0, 'Twister (1996)': 4.0, 'Batman Returns (1992)': 3.0, 'Young Guns II (1990)': 2.0, "Weekend at Bernie's (1989)": 3.0, 'River Wild, The (1994)': 4.0, 'Boomerang (1992)': 3.0, 'Grumpier Old Men (1995)': 4.0, 'Bad Boys (1995)': 4.0, 'GoodFellas (1990)': 4.0, 'GoldenEye (1995)': 4.0, 'American President, The (1995)': 5.0, 'Annie Hall (1977)': 4.0, 'Son in Law (1993)': 4.0, 'Good, The Bad and The Ugly, The (1966)': 5.0, 'Bridge on the River Kwai, The (1957)': 5.0, 'Lost World: Jurassic Park, The (1997)': 3.0, 'Batman (1989)': 3.0, 'Star Trek: The Wrath of Khan (1982)': 5.0, 'That Old Feeling (1997)': 4.0, 'Dragonheart (1996)': 4.0, 'Serial Mom (1994)': 1.0, 'Platoon (1986)': 3.0, 'Nine Months (1995)': 4.0, 'So I Married an Axe Murderer (1993)': 2.0, 'Waterworld (1995)': 4.0, 'Junior (1994)': 4.0, 'Air Up There, The (1994)': 3.0, 'My Favorite Year (1982)': 3.0, 'Clockwork Orange, A (1971)': 4.0, 'Michael (1996)': 4.0, 'Star Wars (1977)': 5.0, 'Raiders of the Lost Ark (1981)': 5.0, "Pyromaniac's Love Story, A (1995)": 3.0, 'To Die For (1995)': 3.0, 'Young Guns (1988)': 3.0, 'Program, The (1993)': 3.0, 'Magnificent Seven, The (1954)': 5.0, 'Mother (1996)': 2.0, 'Ed Wood (1994)': 3.0, 'Naked Gun 33 1/3: The Final Insult (1994)': 4.0, 'Milk Money (1994)': 4.0, 'Barcelona (1994)': 3.0, 'E.T. the Extra-Terrestrial (1982)': 3.0, 'To Wong Foo, Thanks for Everything! Julie Newmar (1995)': 3.0, 'Butch Cassidy and the Sundance Kid (1969)': 5.0, 'Manchurian Candidate, The (1962)': 4.0, 'Inkwell, The (1994)': 3.0, 'Switchblade Sisters (1975)': 2.0, 'Something to Talk About (1995)': 2.0, 'Executive Decision (1996)': 3.0, 'Young Frankenstein (1974)': 5.0, 'Independence Day (ID4) (1996)': 5.0, 'Glory (1989)': 4.0, 'Star Trek: The Motion Picture (1979)': 3.0, "Dante's Peak (1997)": 3.0, 'That Thing You Do! (1996)': 4.0, 'Boot, Das (1981)': 4.0, 'Raising Arizona (1987)': 3.0, 'Braveheart (1995)': 4.0, 'Mission: Impossible (1996)': 4.0, 'Matilda (1996)': 3.0, 'To Kill a Mockingbird (1962)': 4.0, 'Striptease (1996)': 2.0}
306 >  [(5.0, 'They Made Me a Criminal (1939)'), (5.0, 'Star Kid (1997)'), (5.0, 'Santa with Muscles (1996)'), (5.0, 'Saint of Fort Washington, The (1993)'), (5.0, 'Marlene Dietrich: Shadow and Light (1996) '), (5.0, 'Great Day in Harlem, A (1994)'), (5.0, 'Entertaining Angels: The Dorothy Day Story (1996)'), (5.0, 'Boys, Les (1997)'), (4.89884443128923, 'Legal Deceit (1997)'), (4.815019082242709, 'Letter From Death Row, A (1998)')]
100 / 1664
200 / 1664
300 / 1664
400 / 1664
500 / 1664
600 / 1664
700 / 1664
800 / 1664
900 / 1664
1000 / 1664
1100 / 1664
1200 / 1664
1300 / 1664
1400 / 1664
1500 / 1664
1600 / 1664
310 >  [(5.0, "What's Eating Gilbert Grape (1993)"), (5.0, 'Vertigo (1958)'), (5.0, 'Usual Suspects, The (1995)'), (5.0, 'Toy Story (1995)'), (5.0, 'Titanic (1997)'), (5.0, 'Sword in the Stone, The (1963)'), (5.0, 'Stand by Me (1986)'), (5.0, 'Sling Blade (1996)'), (5.0, 'Silence of the Lambs, The (1991)'), (5.0, 'Shining, The (1980)')]

피어슨 상관점수 구하는 공식 (35p의 파이썬 소스를 수식화 하였다.)

 

 

 

 

사용자기반 추천 (37p의 표 내용을 수식화 하였다. 나 = 토비)

 

 

 

 

 

항목기반 추천 (47p의 표 내용을 수식화 하였다. 나 = 토비)