用户相似度计算
协同过滤算法主要利用行为的相似度计算兴趣的相似度。给定用户 和用户 ,令 表示用户 感兴趣的物品集合,令 为用户 感兴趣的物品集合。那么我们可以通过 公式或者余弦公式来计算用户 , 的相似程度:
假设目前共有4个用户:、、、;共有5个漫威英雄人物:死侍、钢铁侠、美国队长、黑豹、蜘蛛侠。用户与人物之间的爱好程度如下图所示:
建立物品到用户的倒排表,对于每个物品都保存对该物品产生过行为的用户列表。倒排表为喜欢每个物品对应的用户,如下所示:
假设用户 和用户 同时属于倒排表中 个人物对应的用户列表,就有 。从而,可以扫描倒排表中每个物品对应的用户列表,将用户列表中的两两用户对应的 加1,最终就可以得到所有用户之间不为0的稀疏矩阵 :
用户相似度改进
如果两个用户都喜欢同一个物品,但这不能说明他们兴趣一定相似,比如我们小学的时候基本买过《新华字典》,但是是我们都对这个感兴趣。但如果两个用户都买过《python数据分析与挖掘实战》,那可以认为他们的兴趣比较相似,因为只有研究数据挖掘的人才会买这本书。所以换句话说,两个用户对冷门物品采取过同样的行为更能说明他们兴趣的相似度。因此又提出了如下公式,根据用户行为计算用户的兴趣相似度:
分子中的倒数惩罚了用户和用户共同兴趣列表中热门物品对他们相似度的影响。是对物品有过行为的用户集合,越热门,越大,惩罚越大。
推荐
为用户与用户的相似度,为用户对商品的打分
python实现
import math
class UserCF:
def __init__(self):
self.user_score_dict = self.initUserScore()
# self.users_sim = self.userSimilarity()
# self.users_sim = self.userSimilarityBetter()
self.users_sim = self.UserSimilarityBest()
# 初始化用户评分数据
def initUserScore(self):
user_score_dict = {"A": {"a": 3.0, "b": 4.0, "c": 0.0, "d": 3.5, "e": 0.0},
"B": {"a": 4.0, "b": 0.0, "c": 4.5, "d": 0.0, "e": 3.5},
"C": {"a": 0.0, "b": 3.5, "c": 0.0, "d": 0., "e": 3.0},
"D": {"a": 0.0, "b": 4.0, "c": 0.0, "d": 3.50, "e": 3.0}}
return user_score_dict
# 计算用户之间的相似度,采用的是遍历每一个用户进行计算
def userSimilarity(self):
W = dict()
for u in self.user_score_dict.keys():
W.setdefault(u, {})
for v in self.user_score_dict.keys():
if u == v:
continue
u_set = set([key for key in self.user_score_dict[u].keys() if self.user_score_dict[u][key] > 0])
v_set = set([key for key in self.user_score_dict[v].keys() if self.user_score_dict[v][key] > 0])
W[u][v] = float(len(u_set & v_set)) / math.sqrt(len(u_set) * len(v_set))
return W
# 计算用户之间的相似度,采用优化算法时间复杂度的方法
def userSimilarityBetter(self):
# 得到每个item被哪些user评价过
item_users = dict()
for u, items in self.user_score_dict.items():
for i in items.keys():
item_users.setdefault(i, set())
if self.user_score_dict[u][i] > 0:
item_users[i].add(u)
# 构建倒排表
C = dict()
N = dict()
for i, users in item_users.items():
for u in users:
N.setdefault(u, 0)
N[u] += 1 # 每个商品下用户出现一次就加一次,就是计算每个用户一共购买的商品个数。
C.setdefault(u, {})
for v in users:
C[u].setdefault(v, 0)
if u == v:
continue
C[u][v] += 1
print(C)
print(N)
# 构建相似度矩阵
W = dict()
for u, related_users in C.items():
W.setdefault(u, {})
for v, cuv in related_users.items():
if u == v:
continue
W[u].setdefault(v, 0.0)
W[u][v] = cuv / math.sqrt(N[u] * N[v])
return W
# 计算用户之间的相似度,采用惩罚热门商品和优化算法复杂度的算法
def UserSimilarityBest(self):
# 得到每个item被哪些user评价过
item_users = dict()
for u, items in self.user_score_dict.items():
for i in items.keys():
item_users.setdefault(i, set())
if self.user_score_dict[u][i] > 0:
item_users[i].add(u)
# 构建倒排表
C = dict()
N = dict()
for i, users in item_users.items():
for u in users:
N.setdefault(u, 0)
N[u] += 1
C.setdefault(u, {})
for v in users:
C[u].setdefault(v, 0)
if u == v:
continue
C[u][v] += 1 / math.log(1 + len(users))
# 构建相似度矩阵
W = dict()
for u, related_users in C.items():
W.setdefault(u, {})
for v, cuv in related_users.items():
if u == v:
continue
W[u].setdefault(v, 0.0)
W[u][v] = cuv / math.sqrt(N[u] * N[v])
return W
# 预测用户对item的评分
def preUserItemScore(self, userA, item):
score = 0.0
for user in self.users_sim[userA].keys():
if user != userA:
score += self.users_sim[userA][user] * self.user_score_dict[user][item]
return score
# 为用户推荐物品
def recommend(self, userA):
# 计算userA 未评分item的可能评分
user_item_score_dict = dict()
for item in self.user_score_dict[userA].keys():
if self.user_score_dict[userA][item] <= 0:
user_item_score_dict[item] = self.preUserItemScore(userA, item)
return user_item_score_dict
if __name__ == "__main__":
ub = UserCF()
print(ub.recommend("C"))