基于邻域的协同过滤算法(二)
2016-07-02 17:44
134 查看
基于物品的协同过滤算法(ItemCF)
ItemCF更加看重与维系用户的历史兴趣,会给用户推荐与那些他们之前喜欢的物品相似的物品。也就是说ItemCF需要计算物品之间的相似度,而不像UserCF去计算用户的相似度。比如,你购买过物品A,通过计算物品B与物品A有很大的相似度,那么就会给你推荐物品A. 而这里计算物品之间的相似度,也不是利用物品的内容属性,而是通过分析用户的行为记录来计算的。该算法认为,之所以A与B有很大的相似性,是因为喜欢A的用户也喜欢B.ItemCF主要分两步:
计算物品之间的相似度。
根据物品的相似度和用户的历史行为给用户生成推荐列表。
计算两个物品之间的相似度可以用下面的公式:
wij=∣N(i)∩N(j)∣∣N(i)∣∣N(j)∣‾‾‾‾‾‾‾‾‾‾‾‾√
这里,我们看到,共同喜欢这两个物品的用户数目越多,就代表这两个物品的相似度越大。这个应该容易理解些。 计算时,需要先建立用户-物品倒排表,是为了降低时间复杂度,直接对那些同时出现在用户行为列表中的物品进行计数,而不去考虑 ∣N(i)∩N(j)∣=0 的情形。
相似度计算的python代码是:
from math import * def ItemSimilarity(train): C=dict()#分子 N=dict() #分母 for u, items in train.items(): for i in items: if i not in N: N[i] = 1 else: N[i] += 1 for j in items: if i != j: if (i, j) not in C: C[(i, j)] = 1 else: C[(i, j)] += 1 W = dict() for (i,j), val in C.items(): if i not in W: W[i] = {} W[i][j]= val / sqrt(N[i] * N[j]) return W
从上面我们知道,每个用户都会为物品相似度做出贡献。考虑到活跃用户对物品相似度的贡献要小于要不活跃用户的贡献,本书中给出了修正的相似度计算公式,对活跃的用户做了一种软性的惩罚,
wij=∑u∈N(i)∩N(j)1ln(1+∣N(u)∣)∣N(i)∣∣N(j)∣‾‾‾‾‾‾‾‾‾‾‾‾√.
这里说活跃用户对物品相似度的贡献小于不活跃的用户。我是这么理解的,一个活跃的用户买了很多物品,会涉及到很多类型,那么这里面任意两个物品属于同一个类型的概率就比较小,这是假相似。而两个物品被很多不活跃的用户买了,才说明它们是真的相似。另外,对于过于活跃的用户,为了避免相似度矩阵过于稠密,在实际计算中一般直接忽略他的兴趣列表。
下面是修正后的物品相似度计算代码:
from math import * def ItemSimilarity2(train): C=dict() #分子 N=dict() #分母 for u, items in train.items(): for i in items: if i not in N: N[i]=1 else: N[i]+=1 for j in items: if i !=j: if (i,j) not in C: C[(i,j)]=1/log(1+len(items)) else: C[(i,j)]+=1/log(1+len(items)) W=dict() for (i,j), val in C.items(): if i not in W: W[i]={} W[i][j]=val/sqrt(N[i]*N[j]) return W
对于相似度,文章又指出如果可以把得出来的相似度按照最大值归一化,可以提高推荐的准确率,覆盖率和多样性。即
w′ij=wijmax wij
归一化这块理解的还不好,需要再查查资料
相似度计算完后,就是要给用户生成推荐列表了。这里类似于UserCF, 计算用户对物品的兴趣度,然后推荐给用户兴趣度高的。通过下面的公式计算用户u对物品j的兴趣:
puj=∑i∈N(u)∩S(j,K)wjirui
这里,N(u)是u喜欢的物品的集合,S(j,k)是和物品j最形似的K个物品的集合,wji是j和i的相似度,rui为u对i的兴趣(对于隐反馈数据集,u对i有过行为,可令rui=1)。下面的程序封装了计算兴趣度和推荐:
def ItemRecommendation(user, train, W, N, K=10): rank = dict() user_items = train[user] for i in user_items: for j, wij in sorted(W[i].items(), key=lambda x: x[1],reverse=True)[0:K]: if j not in user_items: if j not in rank: rank[j] = wij * 1 else: rank[j] += wij * 1 rank = sorted(rank.items(), key=lambda x: x[1], reverse=True) rank = rank[:N] return rank
接下来就是通过计算准确率,召回率,覆盖率来研究 K对系统的影响。计算公式已经在上一篇文章中给出,这里给出python代码
#准确率 def ItemPrecision(train, test, N, K): hit = 0 alls = 0 W = ItemSimilarity(train) for user in train.keys(): te_user_item = test[user] recomRank = ItemRecommendation(user, train, W, N, K) for recom_item, w in recomRank: if recom_item in te_user_item: hit += 1 alls += N return hit * 1.0 / alls #召回率 def ItemRecall(train, test, N): hit = 0 alls = 0 W = ItemSimilarity(train) for user in train.keys(): te_user_item = test[user] recomRank = ItemRecommendation(user, train, W, N) for recom_item, w in recomRank: if recom_item in te_user_item: hit += 1 alls += len(te_user_item) return hit * 1.0 / alls #覆盖率 def ItemCoverage(train, N): recommend_items = set() all_items = set() W = ItemSimilarity(train) for user in train.keys(): for item in train[user]: all_items.add(item) rank = ItemRecommendation(user, train, W, N) for item in rank: recommend_items.add(item[0]) return len(recommend_items) / (len(all_items) * 1.0)
ItemCF的大概思路应该就是这样。等看了ItemCF 这块的论文了,再补些想法。
相关文章推荐
- 读书笔记--推荐系统实践(2)
- 读书笔记---推荐系统实践(3)
- 广告推荐系统--初探
- 推荐系统的算法
- Mahout分布式程序开发 基于物品的协同过滤ItemCF
- R实现MapReduce的协同过滤算法
- 用R解析Mahout用户推荐协同过滤算法(UserCF)
- 基于协同过滤算法推荐的过程
- 基于邻域的协同过滤算法(一)
- spark中协同过滤算法分析
- mahout之旅---分布式推荐算法ALS-MR
- 推荐系统 --- 协同过滤算法
- 协同过滤推荐算法的优化(稀疏矩阵的处理)
- 机器学习9(2)推荐系统
- 基于用户的协同过滤算法(Java实现或R语言实现
- Spark MLlib中的协同过滤
- Matrix Factorization: A Simple Tutorial and Implementation in Python
- TOP 10 开源的推荐系统简介
- 推荐算法之潜在因子(Latent Factor)算法
- 推荐算法总结Recommendation