defloadExData():return[[1,1,1,0,0],
[2,2,2,0,0],
[1,1,1,0,0],
[5,5,5,0,0],
[1,1,0,2,2],
[0,0,0,3,3],
[0,0,0,1,1]]defloadExData2():return[[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
[0, 0, 0,3, 0, 4, 0, 0, 0, 0, 3],
[0, 0, 0, 0,4, 0, 0, 1, 0, 4, 0],
[3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
[0, 0, 0, 0,5, 0, 1, 0, 0, 5, 0],
[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
[0, 0, 0,4, 0, 4, 0, 0, 0, 0, 4],
[0, 0, 0,2, 0, 2, 5, 0, 0, 1, 2],
[0, 0, 0, 0,5, 0, 0, 0, 0, 4, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]]from numpy import *
from numpy importlinalg as la#欧氏距离
defeuclidSim(inA,inB):return 1.0/(1.0+la.norm(inA-inB))#皮尔逊相关系数
defpearsSim(inA,inB):if len(inA)<3:return 1.0
return 0.5+0.5*corrcoef(inA,inB,rowvar=0)[0][1]#余弦相似度
defcosSim(inA,inB):
num=float(inA.T*inB)
denom=la.norm(inA)*la.norm(inB)return 0.5+0.5*(num/denom)#基于物品相似度的推荐引擎(标准相似度计算方法下的用户估计值 )
defstandEst(dataMat,user,simMeas,item):#商品数目
n=shape(dataMat)[1]#两个用于计算估计评分值的变量
simTotal=0.0;ratSimTotal=0.0
#遍历所有商品,并将它与所有的物品进行比较
for j inrange(n):#用户对某个物品的评分
userRating=dataMat[user,j]if userRating==0:continue
#logical_and:矩阵逐个元素运行逻辑与,返回值为每个元素的True,False
#dataMat[:,item].A>0: 第item列中大于0的元素
#dataMat[:,j].A: 第j列中大于0的元素
#overLap: dataMat[:,item],dataMat[:,j]中同时都大于0的那个元素的行下标(一个向量)
overLap=nonzero(logical_and(dataMat[:,item].A>0,\
dataMat[:,j].A>0))[0]print(j)print("------overLap------")print(overLap)if len(overLap)==0:similarity=0#计算overLap矩阵的相似度
else: similarity=simMeas(dataMat[overLap,item],\
dataMat[overLap,j])print("dataMat[overLap,item:")print(dataMat[overLap,item])print("dataMat[overLap,j:")print(dataMat[overLap,j])print ('the %d and %d similarity is:%f' %(item,j,similarity))#累计总相似度(不太理解)#假设A评分未知,A,B相似度0.9,B评分5,;A C相似度0.8,C评分4.#那么按照公式A评分=(0.9*5+0.8*4)/(0.9+0.8)#相当于加权平均(如果除以2),但是因为2个评分的权重是不一样的,所以应除以相似度之和
simTotal+=similarity#ratSimTotal = 相似度*元素值
ratSimTotal+=similarity*userRatingprint("ratSimTotal+=similarity*userRating:")print(ratSimTotal)if simTotal==0:return0else:return ratSimTotal/simTotal#对某个用户产生最高的N个推荐结果#user 表示要推荐的用户编号
def recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):#对给定用户建立一个未评分的物品矩阵
unratedItems=nonzero(dataMat[user,:].A==0)[1] #第user行中等于0的元素#print(dataMat[user,:].A==0)----[[ True True True ..., True False True]]#对于二维数组b2,nonzero(b2)所得到的是一个长度为2的元组。它的第0个元素是数组a中值不为0的元素的第0轴的下标,第1个元素则是第1轴的下标,因此从下面的结果可知b2[0,0]、b[0,2]和b2[1,0]的值不为0:#
#>>> b2 = np.array([[True, False, True], [True, False, False]])#>>> np.nonzero(b2)#(array([0, 0, 1], dtype=int64), array([0, 2, 0], dtype=int64))
if len(unratedItems)==0:return 'you rated everything'
#给未评分物品存放预测得分的列表
itemScores=[]for item inunratedItems:#对每个未评分物品通过standEst()方法来预测得分
print("item------------")print(item)
estimatedScore=estMethod(dataMat,user,simMeas,item)#将物品编号和估计得分存放在列表中
itemScores.append((item,estimatedScore))#sorted排序函数,key 是按照关键字排序,lambda是隐函数,固定写法,
#jj表示待排序元祖,jj[1]按照jj的第二列排序,reverse=True,降序;[:N]前N个
return sorted(itemScores,key=lambda jj:jj[1],reverse=True)[:N]#利用SVD提高推荐效果#基于SVD的评分估计
defsvdEst(dataMat,user,simMeas,item):#商品数目
n=shape(dataMat)[1]
simTotal=0.0;ratSimTotal=0.0
#SVD分解为:U*S*V
U,Sigma,VT=la.svd(dataMat)#分解后只利用90%能量的奇异值,存放在numpy数组里面
Sig4=mat(eye(4)*Sigma[:4])#利用U矩阵将物品转换到低维空间中
xformeditems=dataMat.T*U[:,:4]*Sig4.Ifor j inrange(n):
userRating=dataMat[user,j]if userRating==0 or j==item:continuesimilarity=simMeas(xformeditems[item,:].T,\
xformeditems[j,:].T)print ('the %d and %d similarity is :%f' %(item,j,similarity))
simTotal+=similarity
ratSimTotal+=similarity*userRatingif simTotal==0:return0else: return ratSimTotal/simTotalif __name__ == '__main__':
myMat=mat(loadExData2())print(recommend(myMat,2))