推荐系统:
类似淘宝根据你买过或者浏览过的东西,自动推荐你一些商品。
我们要做的是两种推荐:
一、基于用户过滤
(1)要收集不同人的偏好,以电影为例——建立一个字典,里面包含用户、用户看的电影和看完电影后打分的数据。可以根据对相同电影得分情况的类似程度来说明用户之间的相似性。
(2)计算用户之间相似度,下面是两个相似度度量价值的方法:欧几里得距离和皮尔逊相关度
(3)
二、基于物品过滤
<span style="font-size:14px;">#coding=utf-8 #加载这个文件可以在import recommendations和import distance,每次修改后用reload(recommendations),reload(distance) from math import sqrt #欧几里得距离 def distance(prefs,person1,person2): # 得到shared_items的列表 si={} for item in prefs[person1]: if item in prefs[person2]: si[item]=1 # 如果两者没有共同之处,则返回0 if len(si)==0: return 0 # 计算所以差值的平方和 a=0 for item in prefs[person1]: if item in prefs[person2]: a=a+pow(prefs[person1][item]-prefs[person2][item],2) return 1/(1+sqrt(a)) </span>
#计算皮尔逊相关系数
<span style="font-size:14px;">#计算皮尔逊相关系数 from math import sqrt #返回p1和p2的皮尔逊相关系数 def sim_pearson(prefs,p1,p2): #得到双方都评价过的物品列表 si={} for movie in prefs[p1]: if movie in prefs[p2]:si[movie]=1 #得到列表元素的个数 n=len(si) #如果两者没有共同之处,则返回1 if n==0:return 1 #对所以偏好求和 sum1=0 sum2=0 sum1sq=0 sum2sq=0 psum=0 for movie in si: sum1=sum1+prefs[p1][movie] #对x求和 sum2=sum2+prefs[p2][movie] #对y求和 #求平方和 for movie in si: sum1sq=sum1sq+pow(prefs[p1][movie],2) #对x^2求和 sum2sq=sum2sq+pow(prefs[p2][movie],2) #对y^2求和 for movie in si: psum=psum+prefs[p1][movie]*prefs[p2][movie] #对x*y求和 #计算皮尔逊评价值 shang=psum-(sum1*sum2/n) xia=sqrt((sum1sq-pow(sum1,2)/n)*(sum2sq-pow(sum2,2)/n)) final=shang/xia return final</span>
#输出相关度较高的前几个人
</pre><p><pre name="code" class="python">#返回结果的个数和相似度函数均为可选函数,这里选择了皮尔逊相关系数 def topmatches1(prefs,person,n=5,similarity=sim_pearson): scores=[] for other in prefs: if other!=person: scores.append([similarity(prefs,person,other),other])#scores是一个列表,第一个是分数,第二个是人名 #列表添加要用.append
#对列表进行排序,评价者最高者排在最前面 scores.sort()#排序从小到大 scores.reverse()#翻转,从大到小 return scores[0:n]
#输出电影的评分,按顺序推荐电影给我
<span style="font-size:14px;">def getRecommendations(prefs,person,similarity=sim_pearson): totals={} simSums={} rankings=[] for other in prefs: if other==person: continue#不和自己比较 sim=similarity(prefs,person,other)#相似度计算 if sim<=0: continue for item in prefs[other]: if item not in prefs[person] or prefs[person][item]==0:#person没看过这个电影或打分为0 totals.setdefault(item,0)#相当于C中的a=0 totals[item]=totals[item]+sim*prefs[other][item]#相似度和打分乘积 simSums.setdefault(item,0) simSums[item]=simSums[item]+sim#相似度之和 #注意下面这部分是不在上面循环里的,应该放最外面 for item in totals: rankings.append([totals[item]/simSums[item],item]) rankings.sort() rankings.reverse() return rankings</span>
#重新建立一个字典,将电影和人名对调
#装换key1,key2 def transformPrefs(prefs): result={} for person in prefs: for item in prefs[person]: result.setdefault(item,{})#把item键对应的值设为一个空的字典,先建立第一级的key result[item][person]=prefs[person][item]#将人和电影对调,把person作为第二级的key,同时赋值 return result
1.我是一个人,O是另外一个人
这个人和我很像,我们都给电影A打高分,都给电影B打低分。
这个人还看过【我没看过的】CDEF电影,那么,我根据这个人的口味 给我推荐电影
-
2.我是一个电影,△是另外一个电影
我们两部电影很像,有许多人,给这个电影打高分的同时都给另一个电影△打高分。
那么,将看相似度高的电影△的人推荐给这部电影
#构造物品比较数据集
def calculateSimilarItems(prefs,n=10):#建立字典,给出与这些物品最为相似的所有其他物品
result={}
itemPrefs=transformPrefs(prefs)#以物品为中心对偏好矩阵实施倒置处理
c=0
for item in itemPrefs:#正对大数据集分心状态变量
c+=1
if c%100==0:print "%d / %d" % (c,len(itemPrefs))
scores=topmatches1(itemPrefs,item,n=n,similarity=distance)#寻找最为相近的物品
result[item]=scores
return result
#获得推荐
def getRecommendedItems(prefs,itemMatch,user):
userRatings=prefs[user]
scores={}
totalSim={}
# 循环遍历由当前用户评分的物品
for (item,rating) in userRatings.items( ):
# 循环遍历与当前物品相近的物品
for (similarity,item2) in itemMatch[item]:
# 如果该用户已经对当前物品做过评价,则将其忽略
if item2 in userRatings: continue
#评价值与相似度的加权之和
scores.setdefault(item2,0)
scores[item2]+=similarity*rating
# 全部相似度之和
totalSim.setdefault(item2,0)
totalSim[item2]+=similarity
# 将每个合计值除以加权和,求出平均值
rankings=[(score/totalSim[item],item) for item,score in scores.items( )]
# 按最高到最低的顺序,返回评分结果
rankings.sort( )
rankings.reverse( )
return rankings