开发工具:pycharm
语言:python
所需资料:《写给程序员的数据挖掘实践指南》——书和代码包
第 2 章 协同过滤——爱你所爱
问题描述:每个用户对于一些乐队有一些评价,如何针对某一个用户对他进行乐队推荐。
解决思路:寻找与该用户最相似的用户(首先使用曼哈顿距离衡量两者之间的距离),根据最相似用户的评价结果进行推荐。
1. 表示表格中的数据
以前两列为例
users = { "Angelica": { "Blues Traveler": 3.5, "Broken Bells": 2, "Norah Jones": 4.5, "Phoenix": 5,
"Slightly Stoopid": 1.5, "The Strokes": 2.5, "Vampire Weekend": 2 },
"Bill": { "Blues Traveler": 2, "Broken Bells": 3.5, "Deadmau5": 4, "Phoenix": 2,
"Slightly Stoopid": 3.5, "Vampire Weekend": 3 }}
print(users["Angelica"])
输出结果如下
2. 计算曼哈顿距离
公式理解:
因此,曼哈顿距离公式如下:
依据公式,书写曼哈顿距离计算函数
def manhattan (user1, user2):
distance = 0
for key in user1:
if key in user2:
distance += abs(user1[key] - user2[key])
return distance
print(manhattan(users["Hailey"], users["Veronica"]))
print(manhattan(users["Hailey"], users["Jordyn"]))
ps:此处的数据与上表相同,数据录入代码从书本提供代码中获取。
输出如下:
3. 寻找最近的用户(按照相似度从高到低的次序返回用户列表)
def computeNearestNeighbor(username, users):
distances = []
for user in users:
if user != username:
distance = manhattan(users[user], users[username])
distances.append((distance, user))
distances.sort()
return distances
print(computeNearestNeighbor("Hailey", users))
输出如下:
4. 根据最近用户的结果进行推荐
def recommend(username, users):
nearest = computeNearestNeighbor(username, users)[0][1]
recomendations = []
neighborRatings = users[nearest]
userRatings = users[username]
for artist in neighborRatings:
if not artist in userRatings:
recomendations.append((artist, neighborRatings[artist]))
return sorted(recomendations, key=lambda artistTuple: artistTuple[1], reverse=True)
print(recommend('Hailey', users))
print(recommend('Angelica', users))
输出结果如下:
从输出结果可以看出存在空推荐的情况,这是由于最近的邻居并没有评价过用户没有评价的乐队,下文将解决这一问题。
【习题1】
实现Minkowski函数
从上面的函数公式得到以下实现函数
def minkowski (user1, user2, r):
distance = 0
empty = True
for key in user1:
if key in user2:
distance += pow(abs(user1[key] - user2[key]), r)
empty = False
if empty:
return 0
else:
return pow(distance, 1/r)
这个函数可以完全代替前文中实现的曼哈顿距离的函数,将r传入为1即可。
这个函数的实现中学习到,开次方根的时候也可以用pow函数。
【习题2】
实现皮尔逊相关系数函数
这个函数需要对数据进行多变扫描,效率较低,因此皮尔逊相关系数的近似计算公式被提出,它能够通过但遍扫描得到结果,但是缺点是一些微小的错误可能会由于这个公式被放大。函数公式如下:
函数实现如下:
def pearson(user1, user2):
n = 0
sum_x = 0
sum_y = 0
sum_x2 = 0
sum_y2 = 0
sum_xy = 0
for key in user1:
if key in user2:
n += 1
sum_x += user1[key]
sum_y += user2[key]
sum_x2 += user1[key] ** 2
sum_y2 += user2[key] ** 2
sum_xy += user1[key] * user2[key]
d = sqrt(sum_x2 - (sum_x ** 2) / n) * sqrt(sum_y2 - (sum_y ** 2) / n)
if d == 0:
return 0
else:
return (sum_xy - sum_x * sum_y / n) / d
print(pearson(users['Angelica'], users['Bill']))
print(pearson(users['Angelica'], users['Hailey']))
print(pearson(users['Angelica'], users['Jordyn']))
从函数代码中我们可以看出,经过一个for循环的扫描,即可得到结果。
输出结果如下:
5. 余弦相似度
在稠密数据集上,曼哈顿距离和欧式距离的效果都比较理想。但对于一些稀疏的数据集,在对缺失值没有较好处理的情况下,它们的评判结果可能不尽人意。在这种情况下,采用余弦相似度可能是更好的选择。
余弦相似度计算公式如下:
6. 实现推荐类
注意:文件录入时为左划线,直接复制的路径为右划线,不可直接粘贴使用。在路径的最后也要加入左划线,表示文件在该文件夹内。