用戶相似度計算
協同過濾算法主要利用行爲的相似度計算興趣的相似度。給定用戶 和用戶 ,令 表示用戶 感興趣的物品集合,令 爲用戶 感興趣的物品集合。那麼我們可以通過 公式或者餘弦公式來計算用戶 , 的相似程度:
假設目前共有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"))