基于协同过滤的推荐引擎

推荐引擎对因特网用户而言已经不再是什么新鲜事。Amazon会根据顾客的购买历史向他们推荐物品,Netflix会向其用户推荐电影,新闻网站会对用户推荐新闻报道…..当然,有很多方法可以实现推荐功能,这里我们只使用一种称为协同过滤(collaborative filtering)的方法。协同过滤是通过将用户和其他用户的数据进行对比来实现推荐的

1.1 相似度计算
计算物品之间的相似度,一般来说,我们有3种方法:
1. 欧氏距离:我们希望相似度值在0到1之间变化,并且物品对越相似,它们的相似度值也就越大。可以用“相似度=1/(1+距离)”这样的算式来计算相似度。当距离为0时,相似度值为1;如果距离很大,相似度也就趋近于0。

def  eulidSim(inA, inB):
       return 1.0/(1.0+linalg.norm(inA-inB)) #norm求范数

2.皮尔逊相关系数: 它度量的是两个向量之间的相似度,在Numpy中,皮尔逊相关系数的计算是由函数corrcoef()进行的。皮尔逊相关系数的取值范围从-1到1,通过0.5+0.5*corrcoef()这个函数计算,把取值范围归一化到0到1之间。

def pearsSim(inA,inB):
      if len(inA)<3 :return 1.0
      return 0.5+0.5*corrcoef(inA,inB,rowvar = 0)[0][1]

3. 余弦相似度: 计算的是两个向量夹角的余弦值。夹角为90度,则相似度为0;如果两个向量的方向相同,则相似度为1.0。

def cosSim(inA,inB):
      num = float(inA.T*inB)
      denom = linalg.norm(inA)*linalg.norm(inB)
      return 0.5+0.5*(num/denom)

1.2 示例:餐馆菜肴推荐引擎(推荐未尝过的菜肴)
推荐系统的工作过程是:给定一个用户,系统会为此用户返回N个最好的推荐菜。为了实现这个,我们需要做到:
1. 寻找用户没有评级的菜肴,即在用户-物品矩阵中的0值;
2. 在用户没有评级的所有物品中,对每个物品预计一个可能的评级分数。这就是,我们认为用户可能会对物品的打分(这就是相似度计算的初衷)
3. 对这些物品的评分从高到低进行排序,返回前N个物品

程序清单: 基于物品相似度的推荐引擎

def standEst(dataMat,user,simMeas,item):
      n = shape(dataMat)[1]
      simTotal = 0.0; ratSimTotal = 0.0
      for j in range(n):
            userRating = dataMat[user,j]
            if userRating == 0: continue #终止循环
            overLap = nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]
            if len(overLap) == 0:similarity = 0
            else:similarity = simMeas(dataMat[overLap,item],dataMat[overLap,j])
            #print 'the %d and %d similarity is:%f' %(item,j,similarity)
            simTotal += similarity
            ratSimTotal +=similarity*userRating
      if simTotal == 0:return 0
      else:return ratSimTotal/simTotal                  

函数standEst用来计算给定相似度计算方法的条件下,用户对物品的估计评分值。参数包括数据矩阵,用户编号,物品编号和相似度计算方法。数据矩阵的形式为:行对应用户,列对应物品。接着,我们遍历每一个物品,如果某个物品评分值为0,就意味着用户没有对该物品评分,跳过了这个物品。循环大体上是对用户评过分的每个物品进行遍历,并将它和没有评分的物品进行相似度计算。overLap给出的是两个物品都被评分的值对应的行数。如果两者没有任何重合元素,则相似度为0且终止本次循环。但是如果存在重合评分值的物品,则基于这些重合物品计算相似度。随后,相似度会不断累加,每次计算还考虑相似度和当前用户评分的乘积。最后,通过所有的评分总和除以总的相似度,使得最后的评分值在0-5之间,这些评分值则用于对预测值进行排序。

def recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):
    unratedItems = nonzero(dataMat[user,:].A==0)[1]
    if len(unratedItems) == 0:return 'you rated everthing'
    itemScores =[]
    for item in unratedItems:
        estimatedScore = estMethod(dataMat,user,simMeas,item)
        itemScores.append((item,estimatedScore))
    return sorted(itemScores,key=lambda jj:jj[1],reverse=True)[:N]

recommend函数产生评分最高的N个推荐结果。改函数先对给定用户建立一个未评分的物品列表。如果不存在未评分物品,那么就退出函数;否则在所有未评分物品上进行循环。对每个未评分物品,则调用standEst函数产生该物品的预测得分。该物品的编号和估计得分值会放在一个元素列表itemScores中。

(利用SVD可以提高推荐的效果,后续添加这个功能)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值