集体智慧编程正式开始了接触,第一课便是如何寻找想进用户(也就是两者的相似程度),正如大多数的推送服务一样,通过计算你和其他的用户的相似程度,给你推荐最佳匹配人认为很好的但是你还没有购买的东西。
这里重点讲了三个计算相似程度的评价方法:欧几里德距离、皮尔逊相关度、Tanimoto
测试数据如下:(就是嵌套字典,共7个人对使用过的商品的评价)
-
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}}
一:欧几里德距离
原理很简单,降维理解:已知直角三角形的两直角边,求斜边长度。
通过两者曾共同使用、评价过的东西来计算。例如:以人们一致评价过的物品为坐标轴,将参与评价的人绘制到图上,以此来考查他们的远近关系。简单的二维图如下:
Toby(1,4.5),若两者在“偏好空间”越相近,则两者越相似。由于这是二维图,所以同一时间只能看到两项评分。可以看下面代码,仔细理解一下,在多维情况下依旧适用。(每个共有物品都会做比较)
-
#欧几里德距离
-
from math
import sqrt
-
def sim_distance(prefs,person1,person2):
-
si = {}
-
for item
in prefs[person1]:
-
if(item
in prefs[person2]):
-
si[item] =
1
-
if(len(si) ==
0):
-
return
0
#上面的代码应该可以省略
-
sum_of_squares = sum([pow(prefs[person1][item]-prefs[person2][item],
2)
for item
in prefs[person1]
if item
in prefs[person2]])
-
return (
1/(
1+sqrt(sum_of_squares)))
#下面解释一下
-
-
sim = sim_distance(critics,
'Lisa Rose',
'Gene Seymour')
-
print(sim)
解释:上面的sum_of_squares越小,两者距离越近,越相似。但我们需要一个函数对偏好越近的情况给出越大值,所以我们对开方后的值加1(防止分母为0),再取倒数。
适合于特征数据量较小的情况
二:皮尔逊相关度
这个相对于欧几里德距离要复杂一点。它的一个好处是,当两者对一件物品的评分差距较大时,并不一定两者不想近,如果他两对于其他的物品评价也有差距,但是都是正相关,那两者的相似度还是相近的。这个比欧几里德距离准确。
它是存在一条拟合线的,这条线尽量靠近所有点,结果也是求所有点和这条线的拟合程度。皮尔逊相关度评价算法首先会找出两位评论者都曾评论过的物品,然后计算两者的评分总和与平方和,并求得评分的乘积之和。最后,算法利用这些计算结果计算出皮尔逊相关度。
-
#皮尔逊相关度
-
from math
import sqrt
-
def sim_pearson(prefs,person1,person2):
-
si = {}
-
for item
in prefs[person1]:
-
if(item
in prefs[person2]):
-
si[item] =
1
-
n = len(si)
-
if(n ==
0):
-
return
0
-
#求和
-
sum1 = sum(prefs[person1][item]
for item
in si)
-
sum2 = sum(prefs[person2][item]
for item
in si)
-
#求平方和
-
sum1_sq = sum(pow(prefs[person1][item],
2)
for item
in si)
-
sum2_sq = sum(pow(prefs[person2][item],
2)
for item
in si)
-
#求乘积和
-
asum = sum(prefs[person1][item]*prefs[person2][item]
for item
in si)
-
#计算皮尔逊评价值
-
num = asum-(sum1*sum2/n)
-
den = sqrt((sum1_sq-pow(sum1,
2)/n)*(sum2_sq-pow(sum2,
2)/n))
-
if(den ==
0):
-
return
0
-
return (num/den)
-
-
sim = sim_pearson(critics,
'Lisa Rose',
'Gene Seymour')
-
print(sim)
适合于特征数据量较大的情况(效果较好)
三:Tanimoto
Tanimoto感觉比较简单:
交集/并集
这是一个计算交集和并集的比率的方法
度量两个集合之间的相似程度的方法。
A=[1,2,3,4] 列表长度:4
B=[1,2,7] 列表长度:3
C = A & B = [1,2] 列表长度:2
T = Nc / ( Na + Nb -Nc) = len(c) / ( len(a) + len(b) - len(c)) = 2 / (4+3-2) = 0.4
-
def tanimoto(p,q):
-
c = [v
for v
in p
if v
in q]
-
return float(len(c)) / ((len(p) + len(q) - len(c)))
可以用户计算用户之间的相似程度,这种方法适用于:数据表示为0、1这种二值化,而非有数量大小的情况
以上为全部内容,在查找物品、人物相似程度上都是比较简单的算法,各自都有适用于的场景。