In [1]:
%matplotlib inline
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
In [2]:
# A dictionary of movie critics and their ratings of a small
# set of movies
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.0,
'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 Matthews': {'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}}
In [3]:
critics['Lisa Rose']['Lady in the Water']
Out[3]:
In [4]:
critics['Toby']['Snakes on a Plane']=4.5
In [5]:
critics['Toby']
Out[5]:
In [6]:
from math import sqrt
# Returns a distance-based similarity score for person1 and person2
def sim_distance(prefs,person1,person2):
# Get the list of shared_items
si={}
for item in prefs[person1]:
if item in prefs[person2]:
si[item]=1
# if they have no ratings in common, return 0
if len(si)==0: return 0
# Add up the squares of all the differences
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in si])
return 1/(1+sqrt(sum_of_squares))
In [7]:
#This function can be called with two names to get a similarity score
#This gives you a similarity score between Lisa Rose and Gene Seymour.
sim_distance(critics,'Lisa Rose','Gene Seymour')
Out[7]:
In [8]:
"""
Returns the Pearson correlation coefficient for p1 and p2. This function will return a value between −1 and 1.
A value of 1 means that the two people have exactly the same ratings for every item. Unlike with the distance metric,
you don't need to change this value to get it to the right scale.
"""
def sim_pearson(prefs,p1,p2):
# Get the list of mutually rated items
si={}
for item in prefs[p1]:
if item in prefs[p2]: si[item]=1
# Find the number of elements
n=len(si)
# if they have no ratings in common, return 0
if n==0: return 0
# Add up all the preferences
sum1=sum([prefs[p1][it] for it in si])
sum2=sum([prefs[p2][it] for it in si])
# Sum up the squares
sum1Sq=sum([pow(prefs[p1][it],2) for it in si])
sum2Sq=sum([pow(prefs[p2][it],2) for it in si])
# Sum up the products
pSum=sum([prefs[p1][it]*prefs[p2][it] for it in si])
# Calculate Pearson score
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
In [10]:
#Run the code
print (sim_pearson(critics,'Lisa Rose','Gene Seymour'))
In [11]:
def dict_to_list(dict):
dictlist = []
for key, value in dict.iteritems():
temp = [key,value]
dictlist.append(temp)
return dictlist
In [ ]:
In [14]:
#Plot Two Movies
import collections
dim1 = critics ['Lisa Rose']
dim2 = critics['Gene Seymour']
dim1 = collections.OrderedDict(sorted(dim1.items()))
dim2 = collections.OrderedDict(sorted(dim2.items()))
print (dim1, dim2)
x = list(dim1.values())
y = list(dim2.values())
print (x, y)
plt.scatter(x,y, alpha=0.5)
plt.xlabel('Lisa Rose')
plt.ylabel('Gene Seymour')
plt.show()
Now that you have functions for comparing two people, you can create a function that scores everyone against a given person and finds the closest matches. In this case, I'm interested in learning which movie critics have tastes simliar to mine so that I know whose advice I should take when deciding on a movie.
The following function uses a Python list comprehension to compare me to every other user in the dictionary using one of the previously defined distance metrics. Then it returns the first n items of the sorted results.
In [15]:
# Returns the best matches for person from the prefs dictionary.
# Number of results and similarity function are optional params.
def topMatches(prefs,person,n=5,similarity=sim_pearson):
scores=[(similarity(prefs,person,other),other)
for other in prefs if other!=person]
# Sort the list so the highest scores appear at the top
scores.sort( )
scores.reverse( )
return scores[0:n]
In [16]:
# Calling this function with a name gives a list of movie critics and their similarity scores, compared to the name:
topMatches(critics,'Toby',n=3)
Out[16]:
In [ ]:
In [ ]: