对于推荐系统大家都很熟悉,几乎每天都能碰到,今天我们就再来看看基于物品的协同过滤的推荐引擎。这里的协同过滤推荐引擎主要是根据用户已经对商品的评分来估计用户对没有进行评分的商品的可能评分。要想估算物品的评分就要算出物品间的相似度,这里介绍几种用于计算相似度的方法:
def ecludSim(inA,inB):
return 1.0/(1.0 + la.norm(inA - inB))
第一中我们最常见的欧氏距离,不再多说。
def pearsSim(inA,inB):
if len(inA) < 3 : return 1.0
return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]
第二中皮尔逊相关系数,它相对于欧氏距离的优势在于它对于用户评级的量级并不敏感。我们用0.5+0.5*corrcoef()这个函数计算。
def cosSim(inA,inB):
num = float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom)
第三中是余弦相似度,通过计算两个向量之间的夹角来计算相似度,夹角为九度,则相似度为0,如果两个方向相同则相似度为1.
接下来就可以对物品进行评分了。
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
上面的函数用于计算评分的估计值,输入参数包括数据矩阵、用户编号,商品编号和相似度计算方法。首先我们得到数据集中物品的数目,然后对后面进行估计评分值的变量进行初始化。接着我们就开始遍历整个数据集,如果发现评分为0就跳过继续遍历,接下来就寻找两个用户都进行评分的物品,如果没有这种元素相似度就为0,否则进行计算基于物品的相似度。计算出的相似度会不断的累加,最后除以总评分,进行归一化处理,这样就估计出了评分,接下来就是针对评分进行推荐。
def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
unratedItems = nonzero(dataMat[user,:].A==0)[1]
if len(unratedItems) == 0: return 'you rated everything'
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]
这个函数的输入包括数据集、用户、以及要推荐的个数、相似度计算方法和评分算法。这个函数首先寻找未进行评分的物品,然后判断是否全部已经进行评分。如果全部都进行评分就返回。对每个没有进行评分的物品调用上面的函数进行估计评分。将评分的物品编号和得分放进列表中,最后进行排序选择出的分最高的N个。