-
基于用户的协同过滤
先给个例子,有用户 A 喜欢物品 X,Y, Z,用户 B 喜欢物品 X, Y,那么我们可以说用户 A 和 B 是属于同一类的,那么我们就可以把 A 喜欢的 Z 推荐给 B。 这就是基于用户的协同过滤算法的基础。
那么什么是协同过滤,这里是维基百科的介绍:简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人透过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。
那么,问题就变成了我们如何区分兴趣相投的用户。用户之间的相似度应该如何评判。当我们得到用户的相似度的时候,我们就可以对某个用户 A, 选择其相似度高的用户群体的喜爱偏好进行推荐。
对于用户之间的相似度,我们可以用余弦相似度,和皮尔逊相关系数来进行判断。 -
我们下面用四个用户对六类物品的评分来简单的计算下各类相似度。
物品1 | 物品2 | 物品3 | 物品4 | 物品5 | 物品6 | |
---|---|---|---|---|---|---|
用户1 | 5 | 3 | 0 | 0 | 4 | 5 |
用户2 | 0 | 1 | 5 | 2 | 4 | 2 |
用户3 | 1 | 1 | 4 | 0 | 2 | 0 |
用户4 | 4 | 4 | 3 | 5 | 0 | 0 |
首先是余弦相似度:
def consine(data):
sim = np.empty([data.shape[0], data.shape[0]])
for i in range(data.shape[0]):
for j in range(data.shape[0]):
# sim[i][j] = 1 - cosine(data[i], data[j])
sim[i][j] = np.dot(data[i], data[j]) / (
(math.sqrt(np.dot(data[i], data[i])) * (math.sqrt(np.dot(data[j], data[j])))))
print(sim)
用户1 | 用户2 | 用户3 | 用户4 | |
---|---|---|---|---|
用户1 | 1 | 0.47356802 | 0.39389277 | 0.45482819 |
用户2 | 0.47356802 | 1 | 0.8743829 | 0.5048252 |
用户3 | 0.39389277 | 0.8743829 | 1 | 0.52486388 |
用户4 | 0.45482819 | 0.5048252 | 0.52486388 | 1 |
可以看出,用户与自己的相似度是1,而用户2和用户3对物品的评价比较接近,所以表现出了 0.87的强的相似度,用户1和用户3的相似度则比较弱。
再看皮尔逊相关系数,皮尔逊映射的值会在 [-1, 1] 之间,我们乘以 0.5 在加上 0.5 把它映射到 [0, 1] 之间。
import numpy as np
pers = np.corrcoef(X)
print(pers * 0.5 + 0.5)
用户1 | 用户2 | 用户3 | 用户4 | |
---|---|---|---|---|
用户1 | 1 | 0.21554603 | 0.33060005 | 0.2265973 |
用户2 | 0.21554603 | 1 | 0.87277651 | 0.34770351 |
用户3 | 0.33060005 | 0.87277651 | 1 | 0.459004 |
用户4 | 0.2265973 | 0.34770351 | 0.459004 | 1 |
相似度与余弦相似度相差不大。
由此,当我们需要对用户 A 进行推荐的时候,我们可以选择与其相似度高的用户的评价历史,然后对其进行推荐,这里我们需要筛选掉用户 A 已经评价过的物品。
基于用户的协同过滤算法需要有一定的数据积累,即冷引导问题,还有就是用户不可能对所有的物品进行评价,只有极少部分被评价了,这就导致了矩阵的稀疏性。
- 基于物品的协同过滤
相反的,基于物品的协同过滤,我们是计算物品与物品之间的相似度,例如,假设用户 A 购买了 X,Y,用户 B 购买了 X, 那么我们可以看作 X 和 Y 具有一定的相似度,而用户 B 买了 X,那我们就可以给用户 B 推荐 Y。