#基于物品的协同过滤算法 from math import sqrt import operator #构建用户-->物品的倒排 import matplotlib.pyplot as plt def loadData(files): data ={}; for line in files: user,score,item=line.split(","); data.setdefault(user,{}); data[user][item]=score; print("用户:物品的倒排:" ) print(data ) return data #计算 # 构造物品-->物品的共现矩阵 # 计算物品与物品的相似矩阵 def similarity(data): # 构造物品:物品的共现矩阵 N={};#喜欢物品i的总人数 C={};#喜欢物品i也喜欢物品j的人数 for user,item in data.items(): for i,score in item.items(): N.setdefault(i,0); N[i]+=1; C.setdefault(i,{}); for j,scores in item.items(): if j not in i: C[i].setdefault(j,0); C[i][j]+=1; print("2.构造的共现矩阵:" ) print ('N:',N); print ('C',C); #计算物品与物品的相似矩阵 W={}; for i,item in C.items(): W.setdefault(i,{}); for j,item2 in item.items(): W[i].setdefault(j,0); W[i][j]=C[i][j]/sqrt(N[i]*N[j]); print("3.计算的相似矩阵:" ) print(W ) return W #根据用户的历史记录,给用户推荐物品 def recommandList(data,W,user,k=3,N=10): rank={}; for i,score in data[user].items():#获得用户user历史记录,如A用户的历史记录为{'a': '1', 'b': '1', 'd': '1'} for j,w in sorted(W[i].items(),key=operator.itemgetter(1),reverse=True)[0:k]:#获得与物品i相似的k个物品 if j not in data[user].keys():#该相似的物品不在用户user的记录里 rank.setdefault(j,0); rank[j]+=float(score) * w; print("4.推荐:" ) print(sorted(rank.items(),key=operator.itemgetter(1),reverse=True)[0:N] ) return sorted(rank.items(),key=operator.itemgetter(1),reverse=True)[0:N]; if __name__=='__main__': print("***基于物品的协同过滤算法的电影推荐实例实现***") print("1.构造数据:" ) data ={ 'UserA': {'《老炮儿》': 4.5, '《唐人街探案》': 4.5,'《星球大战》': 4.0, '《寻龙诀》': 3.5,'《神探夏洛特》': 3.0, '《小门神》': 2.5}, 'UserB': {'《老炮儿》': 4.0, '《唐人街探案》': 3.5,'《星球大战》': 4.5, '《寻龙诀》': 3.0, '《神探夏洛特》': 3.0,'《小门神》': 3.5}, 'UserC': {'《老炮儿》': 4.5, '《唐人街探案》': 4.0, '《寻龙诀》': 3.5, '《神探夏洛特》': 3.0}, 'UserD': { '《唐人街探案》': 4.5, '《星球大战》': 4.0,'《寻龙诀》': 4.0, '《神探夏洛特》': 3.5,'《小门神》': 2.5}, 'UserE': {'《老炮儿》': 4.0, '《唐人街探案》': 4.0,'《星球大战》': 4.0, '《寻龙诀》': 4.5, '《神探夏洛特》': 3.0,'《小门神》': 3.0}, 'UserF': {'《老炮儿》': 4.0, '《唐人街探案》': 4.0, '《寻龙诀》': 3.5, '《神探夏洛特》': 3.0,'《小门神》': 3.5}, 'UserG': { '《唐人街探案》': 4.5, '《寻龙诀》': 4.0, '《小门神》': 2.0} } W=similarity(data);#计算物品相似矩阵 recommandList(data,W,'UserG',10,10);#推荐 运行结果: #基于协同过滤算法
# A dictionary of movie critics and their ratings of a small# critics = { 'A': {'老炮儿': 3.5, '唐人街探案': 1.0}, 'B': {'老炮儿': 2.5, '唐人街探案': 3.5, '星球大战': 3.0, '寻龙诀': 3.5, '神探夏洛克': 2.5, '小门神': 3.0}, 'C': {'老炮儿': 3.0, '唐人街探案': 3.5, '星球大战': 1.5, '寻龙诀': 5.0, '神探夏洛克': 3.0, '小门神': 3.5}, 'D': {'老炮儿': 2.5, '唐人街探案': 3.5, '寻龙诀': 3.5, '神探夏洛克': 4.0}, 'E': {'老炮儿': 3.5, '唐人街探案': 2.0, '星球大战': 4.5, '神探夏洛克': 3.5, '小门神': 2.0}, 'F': {'老炮儿': 3.0, '唐人街探案': 4.0, '星球大战': 2.0, '寻龙诀': 3.0, '神探夏洛克': 3.0, '小门神': 2.0}, 'G': {'老炮儿': 4.5, '唐人街探案': 1.5, '星球大战': 3.0, '寻龙诀': 5.0, '神探夏洛克': 3.5} } # print(critics['B']['星球大战'])=3.0 from math import sqrt def sim_distance(prefs, person1, person2): si = {} for item in prefs[person1]: if item in prefs[person2]: si[item] = 1 # 如果两者没有共同之处,则返回0 if len(si) == 0: return 0 # sum函数参数:sum(iterable[, start]),其中iterable为可迭代对象,可以是list、tuple或者dictionary等 # "item for item in a if item in b" 这种表达式叫作列表推导式,是在一组字符串或者一组对象上执行一条相同操作的简洁写法! sum_of_squares = sum([pow(prefs[person1][item] - prefs[person2][item], 2) for item in prefs[person1] if item in prefs[person2]]) return 1 / (1 + sqrt(sum_of_squares)) # print(sim_distance(critics, 'A', 'B')) # Gets recommendations for a person by using a weighted average # of every other user's rankings def getRecommendations(prefs, person, similarity=sim_distance): totals = {} simSums = {} for other in prefs: # don't compare me to myself if other == person: continue sim = similarity(prefs, person, other) # ignore scores of zero or lower if sim <= 0: continue for item in prefs[other]: # only score movies I haven't seen yet if item not in prefs[person] or prefs[person][item] == 0: # Similarity * Score totals.setdefault(item, 0) totals[item] += prefs[other][item] * sim # Sum of similarities simSums.setdefault(item, 0) simSums[item] += sim # Create the normalized list rankings = [(total / simSums[item], item) for item, total in totals.items()] # Return the sorted list rankings.sort() rankings.reverse() return rankings print(getRecommendations(critics, 'A'))
运行结果: