基于物品的协同过滤算法。基于物品的协同过滤算法是目前业界应用最多的算法,亚马逊、Netflix、Hulu、YouTube等很多平台都采用该算法作为其基础推荐算法
原理
基于物品的协同过滤算法给用户推荐那些和他们之前喜欢的物品相似的物品。但是它并不是利用物品的内容属性计算物品之间的相似度,而是通过分析用户的行为记录计算物品之间的相似度,比如说用户之前买过《数据挖掘导论》,该算法会根据此行为给你推荐《机器学习》,但是ItemCF算法并不利用物品的内容属性计算物品之间的相似度,它主要通过分析用户的行为记录计算物品之间的相似度。
流程
1. 计算物品之间的相似度;
2. 根据物品的相似度和用户的历史行为给用户生成推荐列表
物品相似度计算
余弦相似度公式:
其中N(i) ,N(j) 分别表示对物品 i ,j 喜欢的用户数,N(i)∩N(j) 为同时喜欢 i 和 j 的人数。我们这里还是使用漫威英雄举例:假设目前共有5个用户: A 、B 、C 、D 、E ;共有5个漫威英雄人物:死侍、钢铁侠、美国队长、黑豹、蜘蛛侠。用户与人物之间的爱好程度如下图所示:
用户 | 喜爱英雄人物 |
---|---|
A | 死侍、钢铁侠、美国队长 |
B | 钢铁侠、黑豹、蜘蛛侠 |
C | 黑豹、美国队长 |
D | 钢铁侠、黑豹、美国队长 |
E | 死侍、美国队长 |
def load_data(filePath):
f = open(filePath, "r", encoding="utf-8")
dataSet = {}
for line in f:
user, hero, rating = line.strip().split(",")
dataSet .setdefault(user, {})
dataSet [user][hero] = rating
return dataSet
# 数据格式如下:
# {'A': {'死侍': '1', '钢铁侠': '1', '美国队长': '1'}, 'B': {'死侍': '1', '黑豹': '1'}, #'C': {'钢铁侠': '1', '蜘蛛侠': '1'}, 'D': {'蜘蛛侠': '1', '黑豹': '1', '美国队长': '1'}}
构建倒排表:
A: | 死侍 | 钢铁侠 | 美国队长 | 黑豹 | 蜘蛛侠 |
---|---|---|---|---|---|
死侍 | 1 | 1 | |||
钢铁侠 | 1 | 1 | |||
美国队长 | 1 | 1 | |||
黑豹 | |||||
蜘蛛侠 |
B: | 死侍 | 钢铁侠 | 美国队长 | 黑豹 | 蜘蛛侠 |
---|---|---|---|---|---|
死侍 | |||||
钢铁侠 | 1 | 1 | |||
美国队长 | |||||
黑豹 | 1 | 1 | |||
蜘蛛侠 | 1 | 1 |
矩阵相加
END | 死侍 | 钢铁侠 | 美国队长 | 黑豹 | 蜘蛛侠 |
---|---|---|---|---|---|
死侍 | 1 | 2 | |||
钢铁侠 | 1 | 2 | 2 | 1 | |
美国队长 | 2 | 2 | 2 | ||
黑豹 | 2 | 2 | 1 | ||
蜘蛛侠 | 1 | 1 |
建立好稀疏矩阵之后,C[i][j] 记录了同时爱好 i 和 j 的用户数,这样我们就可以带入上面的公式得到物品之间的相似度矩阵W
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, 0)
W[i][j] = cij / math.sqrt(N[i] * N[j])
print("物品相似度: ", W)
return W
"""
稀疏矩阵: {'钢铁侠': {'死侍': 1, '美国队长': 2, '黑豹': 2, '蜘蛛侠': 1}, '死侍': {'钢铁侠': 1, '美国队长': 2}, '美国队长': {'钢铁侠': 2, '死侍': 2, '黑豹': 2}, '黑豹': {'钢铁侠': 2, '蜘蛛侠': 1, '美国队长': 2}, '蜘蛛侠': {'钢铁侠': 1, '黑豹': 1}}
物品相似度: {'钢铁侠': {'死侍': 0.4082482904638631, '美国队长': 0.5773502691896258, '黑豹': 0.6666666666666666, '蜘蛛侠': 0.5773502691896258}, '死侍': {'钢铁侠': 0.4082482904638631, '美国队长': 0.7071067811865475}, '美国队长': {'钢铁侠': 0.5773502691896258, '死侍': 0.7071067811865475, '黑豹': 0.5773502691896258}, '黑豹': {'钢铁侠': 0.6666666666666666, '蜘蛛侠': 0.5773502691896258, '美国队长': 0.5773502691896258}, '蜘蛛侠': {'钢铁侠': 0.5773502691896258, '黑豹': 0.5773502691896258}}
"""
推荐
这里我们取用户为 A,K=2 ,即为用户A喜欢的每个人物推荐两个相关度比较高的人物,结果为:
def recommend(user, train, W, K):
pi = 1
rank = dict()
interacted_items = train[user]
for item in interacted_items:
print(" ->", item)
related_item = []
for user, score in W[item].items():
related_item.append((user, score))
for j, v in sorted(related_item, key=itemgetter(1), reverse=True)[0:K]:
print(j, v)
if j in interacted_items:
continue
if j not in rank.keys():
rank[j]=0
rank[j] += pi * v
print("推荐人物: ", rank)
return rank
"""
-> 钢铁侠
黑豹 0.6666666666666666
美国队长 0.5773502691896258
-> 死侍
美国队长 0.7071067811865475
钢铁侠 0.4082482904638631
-> 美国队长
死侍 0.7071067811865475
钢铁侠 0.5773502691896258
推荐人物: {'黑豹': 0.6666666666666666}
"""
从上面可以看出,
和钢铁侠比较相似的人物为黑豹、美国队长,
和死侍比较相似的人物为美国队长、钢铁侠 ,
和美国队长相似的两个人物为死侍、钢铁侠 。
即推荐出来的人物为黑豹、美国队长、钢铁侠、死侍,但是美国队长、死侍、钢铁侠本来就在用户 A 喜爱的人物中,所以不用推荐,那么最终推荐的人物就为黑豹了。根据 ItemCF 算法,用户 A 对黑豹的喜爱程度为:
p(A,黑豹)=w钢铁侠、黑豹=0.6666666666666666