算法介绍
基于物品的协同过滤推荐算法不是根据物品内容的属性计算物品之间的相似度,而是通过分析用户的行为记录来计算用户的相似度。该算法认为物品A和物品B相似的依据是因为喜欢物品A的用户也喜欢物品B。
基于物品的协同过滤算法实现步骤:
计算物品之间的相似度
根据物品的相似度和用户的历史行为记录给用户生成推荐列表
算法核心:从物品角度找到相似度高的商品,进行推荐。
算法思想:基于物品的协同过滤推荐算法的原理和基于用户的协同过滤推荐算法类似,只是在计算邻居时采用物品本身,而不是从用户的角度,即基于用户对物品的偏好找到相似的物品,然后根据用户的历史偏好,推荐相似的物品给他。从计算的角度看,就是将所有用户对某个物品的偏好作为一个向量来计算物品之间的相似度,得到物品的相似物品后,根据用户历史的偏好预测当前用户还没有表示偏好的物品,计算得到一个排序的物品列表作为推荐。
算法示例:下图展示了一个例子,对于物品A,根据所有用户的历史偏好,喜欢物品A的用户都喜欢物品C,得出物品A和物品C比较相似,而用户C喜欢物品A,那么可以推断出用户C可能也喜欢物品C。
算法优势
最大的优点是工程上容易实现,可以方便应用到产品中。目前绝大多数实际应用的推荐算法都是协同过滤推荐算法。
参数介绍
数据格式:userId,itemId, rating
userId:用户ID
itemId:物品ID
rating:当前用户ID的用户对当前物品ID的物品的评分
topN:为用户i推荐前N个物品
调优方法
尽量选取更精准的rating值。
选择合适的距离公式,如:欧氏距离公式、余弦相似度距离公式、皮尔逊相关系数、曼哈顿距离公式、闵可夫斯基距离公式、杰卡德相似系数等。
根据应用场景选择合适的topN。
适用场景
在非社交网络的网站中,内容内在的联系是很重要的推荐原则,它比基于相似用户的推荐原则更加有效。比如在购书网站上,当你看一本书的时候,推荐引擎会给你推荐相关的书籍,这个推荐的重要性远远超过了网站首页对该用户的综合推荐。可以看到,在这种情况下,基于物品的协同过滤推荐成为了引导用户浏览的重要手段。同时基于物品的协同过滤推荐算法便于为推荐做出解释,在一个非社交网络的网站中,给某个用户推荐一本书,同时给出的解释是某某和你有相似兴趣的人也看了这本书,这很难让用户信服,因为用户可能根本不认识那个人;但如果解释说是因为这本书和你以前看的某本书相似,用户可能就觉得合理而采纳了此推荐。
demo示例
from math import sqrtimport operator#2.计算# 2.1 构造物品-->物品的共现矩阵# 2.2 计算物品与物品的相似矩阵def similarity(data): # 2.1 构造物品:物品的共现矩阵 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(喜欢物品i的总人数):',N) print('C(喜欢物品i也喜欢物品j的人数):',C) #2.2 计算物品与物品的相似矩阵 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#3.根据用户的历史记录,给用户推荐物品def recommandList(data,W,user,k=3,N=10): rank={}; #获得用户user历史记录,如A用户的历史记录为{'a': '1', 'b': '1', 'd': '1'} for item_i,score in data[user].items(): for item_j,w in sorted(W[item_i].items(),key=operator.itemgetter(1),reverse=True)[0:k]:#获得与物品i相似的k个物品 if item_j not in data[user].keys():#该相似的物品不在用户user的记录里 rank.setdefault(item_j,0); rank[item_j]+=(float(score) * w); print("---3.推荐----") sortedList = sorted(rank.items(),key=operator.itemgetter(1),reverse=True)[0:N]; print(sortedList)return sortedList;#加载数据集def loadData(path): f = open(path, 'r') dataList = f.readlines() users = {} for data in dataList: dataArr = data.strip('\n').split(",") userId = dataArr[0] itemId = dataArr[1] rating = float(dataArr[2]) items = {} if userId in users: items = users[userId] items[itemId] = rating users[userId] = itemsreturn usersif __name__=='__main__': print("---1.构造数据---") ''' data = {'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 'The Night Listener': 3.0}, 'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 'You, Me and Dupree': 3.5}, 'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0, 'Superman Returns': 3.5, 'The Night Listener': 4.0}, 'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'The Night Listener': 4.5, 'Superman Returns': 4.0, 'You, Me and Dupree': 2.5}, 'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0, 'You, Me and Dupree': 2.0}, 'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5}, 'Toby': {'Snakes on a Plane': 4.5, 'You, Me and Dupree': 1.0, 'Superman Returns': 4.0} } ''' path = "/home/ai/recommandSystem/ALS1_rating.txt" data = loadData(path) print("data:",data) W=similarity(data);#计算物品相似矩阵 recommandList(data,W,'5',10,10);#推荐