上一篇博客我简单讲了一下基于用户的协同过滤算法,这里我们一起来学习一下另一种:基于物品的协同过滤算法。基于物品的协同过滤算法是目前业界应用最多的算法,亚马逊、Netflix、Hulu、YouTube等很多平台都采用该算法作为其基础推荐算法。
-
原理
基于物品的协同过滤算法给用户推荐那些和他们之前喜欢的物品相似的物品。但是它并不是利用物品的内容属性计算物品之间的相似度,而是通过分析用户的行为记录计算物品之间的相似度,比如说用户之前买过《数据挖掘导论》,该算法会根据此行为给你推荐《机器学习》,但是 I t e m C F ItemCF ItemCF算法并不利用物品的内容属性计算物品之间的相似度,它主要通过分析用户的行为记录计算物品之间的相似度。 -
流程
1. 计算物品之间的相似度;
2. 根据物品的相似度和用户的历史行为给用户生成推荐列表 -
物品相似度计算
余弦相似度公式:
w i j = ∣ N ( i ) ∩ N ( j ) ∣ ∣ N ( i ) ∣ ∣ N ( j ) ∣ {w_{ij}} = \frac{ {|N(i) \cap N(j)|}}{ {\sqrt {|N(i)||N(j)|} }} wij=∣N(i)∣∣N(j)∣∣N(i)∩N(j)∣
其中 N ( i ) N(i) N(i), N ( j ) N(j) N(j)分别表示对物品 i i i, j j j 喜欢的用户数, N ( i ) ∩ N ( j ) {N(i) \cap N(j)} N(i)∩N(j)为同时喜欢 i i i 和 j j j 的人数。我们这里还是使用漫威英雄举例:假设目前共有5个用户: A A A、 B B B、 C C C、 D D D、 E E E;共有5个漫威英雄人物:死侍、钢铁侠、美国队长、黑豹、蜘蛛侠。用户与人物之间的爱好程度如下图所示:
用户 | 喜爱英雄人物 |
---|---|
A | 死侍、钢铁侠、美国队长 |
B | 钢铁侠、黑豹、蜘蛛侠 |
C | 黑豹、美国队长 |
D | 钢铁侠、黑豹、美国队长 |
E | 死侍、美国队长 |
首先还是处理数据,请参考推荐系统实践(一)----基于用户的协同过滤算法(UserCF),这里就不再仔细讲了。
网络上很多帖子都建立了用户-物品倒排列表,但是个人绝的不是必须的,如果有大佬帮忙提出建立列表的原因,请不吝赐教。我这里直接创建系数矩阵。对于每个用户的喜爱人物集合,我们将里面的人物两两加一,得到一个矩阵。最终将这些矩阵相加得到稀疏 C C C 矩阵。其中 C [ i ] [ j ] C[i][j] C[i][j] 记录了同时爱好 i i i 和 j j j 的用户数。(假设下文的表格为矩阵)
用户A:
死侍 | 钢铁侠 | 美国队长 | |
---|---|---|---|
死侍 | 1 | 1 | |
钢铁侠 | 1 | 1 | |
美国队长 | 1 | 1 |
用户B:
钢铁侠 | 黑豹 | 蜘蛛侠 | |
---|---|---|---|
钢铁侠 | 1 | 1 | |
黑豹 | 1 | 1 | |
蜘蛛侠 | 1 | 1 |
用户C:
黑豹 | 美国队长 | |
---|---|---|
黑豹 | 1 | |
美国队长 | 1 |
用户D:
钢铁侠 | 黑豹 | 美国队长 | |
---|---|---|---|
钢铁侠 | 1 | 1 | |
黑豹 | 1 | 1 | |
美国队长 | 1 | 1 |
用户E:
死侍 | 美国队长 | |
---|---|---|
死侍 | 1 | |
美国队长 | 1 |
我们将上面五个矩阵加起来,得到稀疏 C C C 矩阵:
死侍 | 钢铁侠 | 美国队长 | 黑豹 | 蜘蛛侠 | |
---|---|---|---|---|---|
死侍 | 1 | 2 | |||
钢铁侠 | 1 | 2 | 2 | 1 | |
美国队长 | 2 | 2 | 2 | ||
黑豹 | 2 | 2 | 1 | ||
蜘蛛侠 | 1 | 1 |
建立好稀疏矩阵之后, C [ i ] [ j ] C[i][j] C[i][j] 记录了同时爱好 i i i 和 j j j 的用户数,这样我们就可以带入上面的公式得到物品之间的相似度矩阵W
实现该功能的python方法:
def item_similarity(userSet):
C = dict()
N = dict()
for u, items in userSet.items():
for i in items:
N.setdefault(i, 0)
N[i] += 1
for j in items:
if i == j:
continue
C.setdefault(i, {
})
C[i].setdefault(j, 0)
C[i][j] += 1
print("稀疏矩阵: ", C)
W = dict()
for i,related_items in C.items():
for j, cij in related_items.items():
W.setdefault(i, {
})
W[i].setdefault(j,