基于邻域的协同过滤算法(一)
来源:互联网 发布:淘宝证书错误 编辑:程序博客网 时间:2024/04/29 14:15
两个月前我开始学习机器学习,这两个月期间学习了一些基础的机器学习算法及其Python实现。这周我刚开始学习《推荐系统实践》这本书,并打算以后定期将自己的学习情况做个简单的总结。这份总结是我这个博客上的第一篇文章。这周的学习的主要内容是基于邻域的协同过滤算法。基于用户行为分析的推荐算法是个性化推荐系统的重要算法,学术界一般将这种类型的算法称为协同过滤算法。
协同过滤,从名字就可以看出这种方法的本质是先有协同(用户齐心协力)再有过滤(每个用户的推荐列表能够过滤掉他不喜欢的物品)。对协同过滤算法,学术届提出了了很多种方法,比如基于邻域的方法(neighborhood-based)、隐语义模型(laten factor model)、基于图的随机游走算法(random walk on graph)等。
基于邻域的方法主要包括两种算法:基于用户的协同过滤算法(UserCF)和基于物品的协同过滤算法(ItemCF)。
基于用户的协同过滤算法(UserCF):
UserCF的本质就是我要给你推荐物品,我先找到与你兴趣最相似的K个用户,然后把他们喜欢的而你却没产生过行为的物品推荐给你。当然不是把所有的他们喜欢的且你没产生过行为的都推荐给你,而是推荐你最感兴趣的 N个产品。根据上面这些描述,我们看到使用 UserCF需要两步:
- 找到与你兴趣相似的K个用户。
- 确定你最感兴趣的N个物品?
在第一步中,我们需要去计算你与每个用户的兴趣相似度,然后按相似度降序排列,所对应的前K个用户就是我们要找的。
对于用户u和v我们可以通过如下的Jaccard公式来计算:
或者通过余弦相似度计算:
计算相似度的时候,为了减少时间复杂度,需要建立一个物品-用户倒排表。因为当用户数很大时,直接从数据集很费时间,很多时间浪费在了计算
这个公式通过
这里用字典格式来储存数据集和相似度,如:
train={'user1':['a', 'b', 'c'], 'user2':['a','b'],....,'userN':[...]}]W={('user1', 'user2'): w12, ('user1', 'user3'): w13,.....}
下面是计算相似度的代码
def UserSimilarity2(train, flag=1): item_users = dict() for u, item in train.items(): for i in item: if i not in item_users: item_users[i] = set() # 生成一个集合 item_users[i].add(u) C = dict() # C为分子 N = dict() # N[u]表示用户u喜欢的物品个数 "" #用户数很大时计算C耗时 for u in train.keys(): for v in train.keys(): if u==v: continue else: if len(set(train[u] ) & set(train[v]))!=0: C[(u, v)]=len(set(train[u] ) & set(train[v])) for u in train.keys(): N[u]=len(train[u]) print C print N "" for item, users in item_users.items(): for u in users: if u not in N: N[u] = 1 # 如果用户u不在字典N里面,先创建 else: N[u] += 1 for v in users: if u != v: if flag == 0: # 修正前 if (u, v) not in C: C[(u, v)] = 1 else: C[(u, v)] += 1 elif flag == 1: # 修正后 if (u, v) not in C: C[(u, v)] = 1 / log(1 + len(users)) else: C[(u, v)] += 1 / log(1 + len(users)) W = dict() for uv in C.keys(): # pdb.set_trace() u = uv[0] v = uv[1] if u not in W: W[u] = set() # 添加与用户u相关的用户v,第二个意思是他们的权重Wuv W[u].add((v, C[uv] / sqrt(N[u] * N[v]))) return W
这个代码中 flag=0对应的是第一个没有修正的相似度计算公式,flag=1对应的就是修正后的相似度计算公式。
计算出相似度后,下来要做的就是找出与你相似度高的前K个用户,然后去把他们喜欢的你没发生过行为的物品(记为
第二步和第一步的思路差不多,定性问题定量化。计算你对
这里,感兴趣程度是用下面的公式来度量的:
下面是实现推荐的代码:
def Recommend(user, train, W, N, K=10): rank = dict() interacted_items = train[user] for v, wuv in sorted(W[user], key=lambda x: x[1], reverse=True)[0:K]: # 相似度最大的K个用户 for i in train[v]: # v产生过行为的物品 if i not in interacted_items: if i not in rank: rank[i] = wuv * 1 else: rank[i] += wuv * 1 rank = sorted(rank.items(), key=lambda x: x[1], reverse=True) rank = rank[:N] return rank
这里的K是一个很关键的参数,K的选取会影响最后的推荐结果。这本书中K对TopN推荐的好坏,是用这几个指标来衡量的:准确率,召回率,覆盖率 和 流行度。
记U为系统的用户集合,R(u)为训练集上得出的推荐列表, T(u)为测试集上的行为列表。
推荐结果的准确率可定义为:
召回率被定义为
def PrecisionRecall(train, test, N): hit = 0 #两者的分子 n_precision=0 # 准确率的分母 n_recall = 0 #召回率的分母 W = UserSimilarity2(train) for user in train.keys(): try: # 计算分子分母 te_user_items = test[user] recomRank = Recommend(user, train, W, N) for recom_item, w in recomRank: if recom_item in te_user_items: hit += 1 n_precision += N n_recall+=len(te_user_items) except: pass return [hit / (1.0*n_precision), hit/(1.0*n_recall)]
覆盖率的计算公式为:
这里
def Coverage(train, N): recommend_items = set() #分子 all_items = set() #分母 W = UserSimilarity2(train) for user in train.keys(): for item in train[user]: all_items.add(item) rank = Recommend(user, train, W, N) for item in rank[0]: recommend_items.add(item) return len(recommend_items) / (len(all_items) * 1.0)
这本书上,目前看的这一章,我没有看到流行度的具体定义,但从给的代码看,似乎平均流行度是这么定义的:
具体代码是这样的:
def Popularity(train,N): item_popularity=dict() for user, items in train.items(): for item in items: if item not in item_popularity: item_popularity[item]=0 item_popularity[item]+=1 ret=0 n=0 W = UserSimilarity2(train, flag=1) for user in train.keys(): rank=Recommend(user, train, W, N, K=10) for item, pui in rank: ret +=log(1+ item_popularity[item]) n +=1 ret /=n*1.0 return ret
- 基于邻域的协同过滤算法(一)
- 基于邻域的协同过滤算法(二)
- 基于邻域的协同过滤算法(三)
- 个性化推荐算法------基于内容的推荐和基于邻域的协同过滤
- 基于Spark MLlib平台和基于模型的协同过滤算法的电影推荐系统(一) 协同过滤算法概述&&基于模型的协同过滤的算法思想(算法模型和结构待补充)
- 基于邻域的算法
- 基于物品的协同过滤推荐算法(矩阵相乘)
- 基于物品的协同过滤算法(Item-CF)
- 基于协同过滤算法的推荐系统
- 基于协同过滤算法推荐的过程
- 基于用户的协同过滤算法
- 基于用户的协同过滤算法
- 基于用户的协同过滤算法
- 基于物品的协同过滤算法
- 基于用户的协同过滤推荐算法
- 基于皮尔森相关系数的协同过滤算法
- 基于用户的协同过滤算法
- 基于用户的协同过滤推荐算法
- CocosPods最新安装教程
- 基于动态规划的0-1背包问题
- Canvas线性水平渐变
- 2016第一弹
- hdu2824(the Euler Function)
- 基于邻域的协同过滤算法(一)
- Lock、Condition
- 如何设计好的RESTful API之安全性
- ulua与unity互传数组
- JUnit 4.8 源码解读
- React Native入门教程 3 -- Flex布局
- 基于邻域的协同过滤算法(二)
- MSDB数据库置疑的解决方法
- CentOS7源码包安装apache