算法原理:
(1) 杰卡德相似系数
两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。
杰卡德相似系数是衡量两个集合的相似度一种指标。
(2) 杰卡德距离
与杰卡德相似系数相反的概念是杰卡德距离(Jaccard distance)。杰卡德距离可用如下公式表示:
杰卡德距离用两个集合中不同元素占所有元素的比例来衡量两个集合的区分度。
(3) 杰卡德相似系数与杰卡德距离的应用
可将杰卡德相似系数用在衡量样本的相似度上。
样本A与样本B是两个n维向量,而且所有维度的取值都是0或1。例如:A(0111)和B(1011)。我们将样本看成是一个集合,1表示集合包含该元素,0表示集合不包含该元素。
p :样本A与B都是1的维度的个数
q :样本A是1,样本B是0的维度的个数
r :样本A是0,样本B是1的维度的个数
s :样本A与B都是0的维度的个数
那么样本A与B的杰卡德相似系数可以表示为:
这里p+q+r可理解为A与B的并集的元素个数,而p是A与B的交集的元素个数。
而样本A与B的杰卡德距离表示为:
_____________________________________________________________________________________
* 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 * * 分隔符 *
不考虑评分高低,只代表看过同样的电影,初版代码如下:
def sim_jaccard(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
n=len(si)
n1=len(prefs[person1])
n2=len(prefs[person2])
p=n1+n2-n
return n/float(p)
输出:
>>> recommendations.topMatches(recommendations.critics,'Lisa Rose',n=5,similarity=recommendations.sim_jaccard);
[(1.0, 'Mick LaSalle'), (1.0, 'Gene Seymour'), (0.8333333333333334, 'Jack Matthews'), (0.8333333333333334, 'Claudia Puig'), (0.6666666666666666, 'Michael Phillips')]
取评分均值区分喜欢和不喜欢,两部分相似度和
def sim_jaccard1(prefs,person1,person2):
sum1=sum([prefs[person1][it] for it in prefs[person1]])
sum2=sum([prefs[person1][it] for it in prefs[person2]])
avg_p1=sum1/float(len(prefs[person1]))
avg_p2=sum2/float(len(prefs[person2]))
p10={}
p11={}
for item in prefs[person1]:
if prefs[person1][item]>= avg_p1:
p10[item]=prefs[person1][item]
else:
p11[item]=prefs[person1][item]
p20={}
p21={}
for item in prefs[person2]:
if prefs[person2][item]>= avg_p1:
p20[item]=prefs[person2][item]
else:
p21[item]=prefs[person2][item]
si={}
for item in p10:
if item in p20:
si[item]=1
sj={}
for item in p11:
if item in p21:
sj[item]=1
a=len(si)/float(len(p10)+len(p20)-len(si))
b=len(sj)/float(len(p11)+len(p21)-len(sj))
return a+b
输出:
>>> recommendations.topMatches(recommendations.critics,'Lisa Rose',n=5,similarity=recommendations.sim_jaccard1);
[(1.5, 'Claudia Puig'), (1.25, 'Michael Phillips'), (1.0, 'Toby'), (0.9333333333333333, 'Mick LaSalle'), (0.5, 'Jack Matthews')]