基于内容的推荐引擎是怎么工作的

基于内容的推荐系统,正如你的朋友和同事预期的那样,会考虑商品的实际属性,比如商品描述,商品名,价格等等。如果你以前从没接触过推荐系统,然后现在有人拿枪指着你的头,强迫你在三十秒之内描述出来,你可能会描述这样一个基于内容的系统:呃,呃,我可能会给你看一大堆来自同一个厂家,并且拥有类似的说明的产品。

你正在利用商品本身的属性来推荐类似的商品。这样做非常合理,因为这就是我们在真实世界中买东西的方式。我们去卖烤箱的那一排货架,然后看这些烤箱,它们可能根据不同的品牌,价格,或着能在30分钟之内烤熟一只完整的火鸡,等等特点在货架上摆放。

现今,推荐系统被用来个性化你在网上的体验,告诉你买什么,去哪里吃,甚至是你应该和谁做朋友。人们口味各异,但通常有迹可循。人们倾向于喜欢那些与他们所喜欢的东西类似的东西,并且他们倾向于与那些亲近的人有相似的口味。推荐系统试图捕捉这些模式,以助于预测你还会喜欢什么东西。电子商务、社交媒体、视频和在线新闻平台已经积极的部署了它们自己的推荐系统,以帮助它们的客户更有效的选择产品,从而实现双赢。

两种最普遍的推荐系统的类型是基于内容和协同过滤(CF)。协同过滤基于用户对产品的态度产生推荐,也就是说,它使用“人群的智慧”来推荐产品。与此相反,基于内容的推荐系统集中于物品的属性,并基于它们之间的相似性为你推荐。一般情况下,协作过滤(CF)是推荐引擎的主力。该算法具有能够自身进行特征学习的一个非常有趣的特性,这意味着它可以开始学习使用哪些特性。CF可以分为基于内存的协同过滤和基于模型的协同过滤。在本教程中,你将使用奇异值分解(SVD)实现基于模型的CF和通过计算余弦相似实现基于内存的CF。Python实现的具体实例

文章内容:基于物品过滤与基于用户过滤。

数据稀疏时候,用物品过滤最优;数据密集,两者效果一样。

下面以电影推荐为例:

一、原始数据处理:

  原始数据为二维矩阵:行是用户,列是电影:

  Lady in the Water Snakes on a Plane Just My Luck Superman Returns You, Me and Dupree The Night Listener
Lisa Rose 2.5 3.5 3.5 3.5 2.5 3
Gene Seymour 3 3.5 1.5 5 3.5 3
Michael Phillips 2.5 3   3.5   4
Claudia Puig   3.5 3 4 2.5 4.5
Mick LaSalle 3 4 2 3 2 3
Jack Matthews 3 4   5 3.5 3
Toby   4.5   4 1  

  采用数据结构:字典套字典:如此即可表现出数据二维矩阵:结构即data[user][movie]=rating

   此数据整体是一个字典,key=用户,value=该用户看过的电影信息 ,其中value又是一个字典(key=电影,value=评分)
data ={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5,
'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5,
'The Night Listener': 3.0},
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Gene Seymour</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Lady in the Water</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.5<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Just My Luck</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 1.5, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 5.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">The Night Listener</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">You, Me and Dupree</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.5<span style="line-height:1.5 !important;">}, </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Michael Phillips</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Lady in the Water</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 2.5, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.5, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">The Night Listener</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 4.0<span style="line-height:1.5 !important;">}, </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Claudia Puig</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.5, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Just My Luck</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">The Night Listener</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 4.5, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 4.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">You, Me and Dupree</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 2.5<span style="line-height:1.5 !important;">}, </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Mick LaSalle</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Lady in the Water</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 4.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Just My Luck</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 2.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">The Night Listener</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">You, Me and Dupree</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 2.0<span style="line-height:1.5 !important;">}, </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Jack Matthews</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Lady in the Water</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 4.0<span style="line-height:1.5 !important;">,
</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">The Night Listener</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 5.0, <span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">You, Me and Dupree</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: 3.5<span style="line-height:1.5 !important;">}, </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Toby</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>: {<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Snakes on a Plane</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>:4.5,<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">You, Me and Dupree</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>:1.0,<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">Superman Returns</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span>:4.0<span style="line-height:1.5 !important;">}

}

二、物品过滤

  1.先计算所有电影(物品)之间的相似度,构造一个包含相近电影(物品)的完整数据集。

   1.1  匹配电影物品,找出那些电影物品是彼此相近的

因为计算以电影物品为主,所以先将上面data[user][movie]数据转换成newdata[movie][user]格式,也即二维矩阵进行行列对换

def transformdata(data):
'''
物品之间的相似度 与 用户之间的相似度 求解 一样。故只需要将用户换成物品即可
'''
newdata = {}
users ={}
for person in data:
for movie in data[person]:
#初始化
newdata.setdefault(movie,{})
#物品与用户对调
newdata[movie][person] = data [person][movie] #字典可以直接写[key],就表示插入key值了。非常简便
return newdata
 '''
调用此方法例子:
print transformdata(data)
结果是:
{'Lady in the Water': {'Lisa Rose': 2.5, 'Jack Matthews': 3.0, 'Michael Phillips': 2.5, 'Gene Seymour': 3.0, 'Mick LaSalle': 3.0},
'Snakes on a Plane': {'Jack Matthews': 4.0, 'Mick LaSalle': 4.0, 'Claudia Puig': 3.5, 'Lisa Rose': 3.5, 'Toby': 4.5, 'Gene Seymour': 3.5, 'Michael Phillips': 3.0},
'Just My Luck': {'Claudia Puig': 3.0, 'Lisa Rose': 3.0, 'Gene Seymour': 1.5, 'Mick LaSalle': 2.0},
'Superman Returns': {'Jack Matthews': 5.0, 'Mick LaSalle': 3.0, 'Claudia Puig': 4.0, 'Lisa Rose': 3.5, 'Toby': 4.0, 'Gene Seymour': 5.0, 'Michael Phillips': 3.5},
'The Night Listener': {'Jack Matthews': 3.0, 'Mick LaSalle': 3.0, 'Claudia Puig': 4.5, 'Lisa Rose': 3.0, 'Gene Seymour': 3.0, 'Michael Phillips': 4.0},
'You, Me and Dupree': {'Jack Matthews': 3.5, 'Mick LaSalle': 2.0, 'Claudia Puig': 2.5, 'Lisa Rose': 2.5, 'Toby': 1.0, 'Gene Seymour': 3.5}}
'''
    1.2 用calSimilarItems()获得所有电影之间的相似度。

               1.2.1 计算相似度,就要涉及相似距离度量,这里列举两种:欧氏距离sim_distance  ,皮尔逊sim_pearson 。两种都已设法表示距离越大,越相似

from math import sqrt
def sim_distance(data,person1,person2):
'''欧氏距离求相似度,距离越大,越相似'''
commonmovies = [ movie for movie in data[person1] if movie in data[person2]]
if len(commonmovies)== 0: return 0
#平方和
sumSq =sum([pow(data[person1][movie] -data[person2][movie],2) for movie in commonmovies ] )
#使最终结果是,越相似,距离越大。所以将上面距离取倒数即可
sim = 1/(1+ sqrt(sumSq))
return sim def sim_pearson(data,person1,person2):

'''

计算上面格式的数据 里的 两个用户 相似度.

基于用户过滤思路:找出两个用户看过的相同电影的评分,从而进行按pearson公式求值。那些非公共电影不列入求相似度值范围。
基于物品过滤思路:找过两部电影相同的观影人给出的评分,从而按pearson公式求值

返回:评分的相似度,[-1,1]范围,0最不相关,1,-1为正负相关,等于1时,表示两个用户完全一致评分

这里的data格式很重要,这里计算相似度是严格按照上面data格式所算。

此字典套字典格式,跟博客计算单词个数 存储格式一样

'''

#计算pearson系数,先要收集两个用户公共电影名单

#commonmovies = [ movie for movie in data[person1] if movie in data[person2]] 分解步骤为如下:

commonmovies = [] #改成列表呢

for movie in data[person1]: #data[person1]是字典,默认第一个元素 in (字典)是指 key.所以这句话是指 对data[person1]字典里遍历每一个key=movie

if movie in data[person2]: #data[person2]也是字典,表示该字典有key是movie.

commonmovies.append(movie) # commonmovie是 两个用户的公共电影名的列表
<span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">看过的公共电影个数</span>
n =<span style="line-height:1.5 !important;"> float(len(commonmovies))
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span> n==<span style="line-height:1.5 !important;">0:
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> 0 </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'''</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">下面正是计算pearson系数公式 </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'''</span>
<span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">分布对两个用户的公共电影movie分数总和</span>
sum1 = sum([data[person1][movie]<span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> movie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> commonmovies ])
sum2 </span>= sum([data[person2][movie]<span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> movie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> commonmovies]) </span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">计算乘积之和</span>
sum12 = sum([data[person1][movie]*data[person2][movie] <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> movie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> commonmovies]) </span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">计算平方和</span>
sum1Sq = sum([ pow(data[person1][movie],2 ) <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> movie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> commonmovies ])
sum2Sq </span>= sum([ pow(data[person2][movie],2 ) <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> movie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> commonmovies ]) </span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">计算分子 </span>
num = sum12 - sum1*sum2/<span style="line-height:1.5 !important;">n
</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">分母</span>
den = sqrt((sum1Sq - pow(sum1,2)/n)*(sum2Sq - pow(sum2,2)/<span style="line-height:1.5 !important;">n))
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span> den==0: <span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> 0 </span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span> num/den</pre>

1.2.2  为单个电影物品返回最匹配结果

def topmatches(data,givenperson ,returnernum = 5,simscore = sim_pearson):
'''
用户匹配推荐:给定一个用户,返回对他口味最匹配的其他用户
物品匹配: 给定一个物品,返回相近物品
输入参数:对person进行默认推荐num=5个用户(基于用户过滤),或是返回5部电影物品(基于物品过滤),相似度计算用pearson计算
'''
#建立最终结果列表
usersscores =[(simscore(data,givenperson,other),other) for other in data if other != givenperson ]
#对列表排序
usersscores.sort(cmp=None, key=None, reverse=True)
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> usersscores[0:returnernum]
    '''
调用以前方法:找物品相关匹配:
moviedata = transformdata(data)
#找出跟“超人回归”这电影相关的电影
print topmatches(moviedata, 'Superman Returns') 结果是:

[(0.6579516949597695, 'You, Me and Dupree'), (0.4879500364742689, 'Lady in the Water'),

(0.11180339887498941, 'Snakes on a Plane'), (-0.1798471947990544, 'The Night Listener'), (-0.42289003161103106, 'Just My Luck')]

其中负数表示,讨厌此电影

'''

       1.2.3 基于上面1.2.2,从为单一物品返回匹配结果 扩展到 为所有物品返回匹配结果
def calSimilarItems(data,num=10):
#以物品为中心,对偏好矩阵转置
moviedata = transformdata(data)
ItemAllMatches = {}
for movie in moviedata:
ItemAllMatches.setdefault(movie,[])
#对每个电影 都求它的匹配电影集,求电影之间的距离用欧式距离,用pearson距离测出的结果是不一样的
ItemAllMatches[movie] = topmatches(moviedata, movie, num,simscore = sim_distance)
return ItemAllMatches
   '''
构造一个物品匹配完整集:包含所有物品的对应的匹配物品
即是电影相似度的字典: key = movie ,value = [(othermovie,simscore)]。其中value是一个元组对的列表
调用例子;
print calSimilarItems(data)
结果为:
{'Lady in the Water': [(0.7637626158259785, 'Snakes on a Plane'), (0.4879500364742689, 'Superman Returns'), (0.3333333333333333, 'You, Me and Dupree'), (-0.6123724356957927, 'The Night Listener'), (-0.9449111825230676, 'Just My Luck')],
'Snakes on a Plane': [(0.7637626158259785, 'Lady in the Water'), (0.11180339887498941, 'Superman Returns'), (-0.3333333333333333, 'Just My Luck'), (-0.5663521139548527, 'The Night Listener'), (-0.6454972243679047, 'You, Me and Dupree')],
'Just My Luck': [(0.5555555555555556, 'The Night Listener'), (-0.3333333333333333, 'Snakes on a Plane'), (-0.42289003161103106, 'Superman Returns'), (-0.4856618642571827, 'You, Me and Dupree'), (-0.9449111825230676, 'Lady in the Water')], .........
'''

2.推荐用户没看过的电影

某一部未看过电影分数= sum(该部未看过的电影与每一部已看电影之间相似度*已看电影的评分) /sum(未看电影与每一部已看电影之间相似度)

   例如:未看电影A,已看电影B,C:

则,电影A分数 =  [sim(A,B)*rating(B) +sim(A,C)*rating(C)] / [ sim(A,B) + sim(A,C)]

def getrecommendations(data,targetperson,moviesAllsimilarity):
'''
输入movieAllSimilarity就是上面calsimilarItems已经计算好的所有物品之间的相似度数据集:
'''
#获得所有物品之间的相似数据集
scoresum = {}
simsum = {}
#遍历所有看过的电影
for watchedmovie in data[targetperson]:
rating = data[targetperson][watchedmovie]
#遍历与当前电影相近的电影
for(similarity,newmovie) in moviesAllsimilarity[watchedmovie]: #取一对元组
#已经对当前物品评价过,则忽略
if newmovie in data[targetperson] :continue

scoresum.setdefault(newmovie,0)
simsum.setdefault(newmovie,0)
#全部相似度求和
simsum[newmovie] += similarity
#评价值与相似度加权之和
scoresum[newmovie] += rating * similarity
rankings </span>= [(score/simsum[newmovie] , newmovie) <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> newmovie,score <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> scoresum.items() ]
rankings.sort(cmp</span>=None, key=None, reverse=<span style="line-height:1.5 !important;">True)
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> rankings</span></pre>
'''调用此方法如下:
itemsAllsim = calSimilarItems(data) #这个值会事先计算好
print '基于物品过滤,为用户Toby推荐的电影是:'
print getrecommendations(data, 'Toby',itemsAllsim)
返回结果是:
[(3.1667425234070894, 'The Night Listener'), (2.936629402844435, 'Just My Luck'), (2.868767392626467, 'Lady in the Water')]

这样基于物品过滤推荐,为Toby用户推荐的电影结果 就完成了。
'''


三、基于用户过滤

3.1 推荐品味相近的用户

 #假设为用户Toby进行推荐品味相当的用户,则调用userstopmatcher方法,会返回一个影评人及其相似度 的列表
print topmatches(data, 'Toby', 3)
#返回结果为:
[(0.9912407071619299, 'Lisa Rose'), (0.9244734516419049, 'Mick LaSalle'), (0.8934051474415647, 'Claudia Puig')]
#所以lisa分数最高,应该推荐lisa Rose品味跟Toby最近

3.2 推荐未看过的电影:

未看过电影分数=sum(被推荐用户与其他用户之间相似度*用户对该电影评分)/sum(被推荐用户与其他用户之间相似度)

def recommendItems(data,givenperson,num =5 ,simscore = sim_pearson):
'''
物品推荐:给定一个用户person,默认返回num=5物品
要两个for,对用户,物品 都进行 遍历
'''
#所有变量尽量用字典,凡是列表能表示的字典都能表示,那何不用字典
itemsimsum={}
#存给定用户没看过的电影的其他用户评分加权
itemsum={}
#遍历每个用户,然后遍历该用户每个电影
for otheruser in data :
#不要和自己比较
if otheruser == givenperson: continue
#忽略相似度=0或小于0情况
sim = simscore(data,givenperson,otheruser)
if sim <=0: continue
    <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> itemmovie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> data[otheruser]:
</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">只对用户没看过的电影进行推荐,参考了其他用户的评价值(协同物品过滤是参考了历史物品相似度值)</span>
<span style="color:rgb(0,0,255);line-height:1.5 !important;">if</span> itemmovie <span style="color:rgb(0,0,255);line-height:1.5 !important;">not</span> <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> data[givenperson]:
</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">一定要初始化字典:初始化itemsum与itemsimsum</span>

itemsum.setdefault(itemmovie,0)

itemsimsum.setdefault(itemmovie,0)

#用户相似度*评价值

itemsum[itemmovie] += sim * data[otheruser][itemmovie]

itemsimsum[itemmovie] += sim

</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">最终结果列表,列表包含一元组(item,分数)</span>
rankings = [(itemsum[itemmovie] / itemsimsum[itemmovie],itemmovie) <span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> itemmovie <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span><span style="line-height:1.5 !important;"> itemsum]
</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">#</span><span style="color:rgb(0,128,0);line-height:1.5 !important;">结果排序</span>
rankings.sort(cmp=None, key=None, reverse=<span style="line-height:1.5 !important;">True);
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span><span style="line-height:1.5 !important;"> rankings

#调用此方法如下:
# print recommendItems(data, 'Toby', 3)

返回结果:
#[(3.3477895267131013, 'The Night Listener'), (2.8325499182641614, 'Lady in the Water'), (2.5309807037655645, 'Just My Luck')]




四、用真实数据:Movielens数据集
4.1数据原型:
u.item 文件:
记录了 电影id与电影名的映射关系
其内容节选:
1|Toy Story (1995)|01-Jan-1995||http://us.imdb.com/M/title-exact?Toy%20Story%20(1995)|0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|0|0|0
2|GoldenEye (1995)|01-Jan-1995||http://us.imdb.com/M/title-exact?GoldenEye%20(1995)|0|1|1|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0 u.data 文件:

每行信息是:用户id,电影id,评分,评分时间(这里我们只用到前三个属性)

其内容节选:

196 242 3 881250949

186 302 3 891717742

22 377 1 878887116

244 51 2 880606923

4.2 将movielens数据转换成上面data数据同样格式:

def formatMovieLens(filepath='D:/eclipse 3.62/workspace/Commendations/data/ml-100k'):
'''
这里用的是ml100k数据,只需要里面u.item和u.data两个文件
把movielens数据转换成此代码要求的数据格式,即转换成如同上面data字典套字典结构:dic[user] = {movie:score}
'''
movie = {}
#获取影片标题。u.item记录着影片id与影片名映射信息
for line in file(filepath+'/u.item'):
(id,title) = line.split("|")[0:2]
movie[id] = title
resultdata </span>=<span style="line-height:1.5 !important;"> {}
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">for</span> line <span style="color:rgb(0,0,255);line-height:1.5 !important;">in</span> file(filepath +<span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">/u.data</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">'</span><span style="line-height:1.5 !important;">):
(user,movieid,rating) </span>= line.split(<span style="color:rgb(128,0,0);line-height:1.5 !important;">"</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">\t</span><span style="color:rgb(128,0,0);line-height:1.5 !important;">"</span>)[0:3<span style="line-height:1.5 !important;">]
resultdata.setdefault(user,{})
movietitle </span>=<span style="line-height:1.5 !important;"> movie[movieid]
resultdata[user][movietitle] </span>=<span style="line-height:1.5 !important;"> float(rating)
</span><span style="color:rgb(0,0,255);line-height:1.5 !important;">return</span> resultdata <br><br></pre>

4.3 测试结果,为用户进行物品推荐。分别尝试物品过滤,用户过滤

mldata= formatMovieLens()
# print "格式化movielens数据集后,取用户id=87看过的电影:"
print mldata['87']
#结果是:{'Birdcage, The (1996)': 4.0, 'E.T. the Extra-Terrestrial (1982)': 3.0, 'Bananas (1971)': 5.0, 'Sting, The (1973)': 5.0, 'Bad Boys (1995)': 4.0, 'In the Line of Fire (1993)': 5.0, 'Star Trek: The Wrath of Khan (1982)': 5.0, 'Speechless (1994)': 4.0, .....} #基于用户过滤推荐

print "基于用户过滤推荐:为用户87推荐的电影排名前4部是:"

print getrecommendation(mldata, '87' )[0:30]

#结果是: [(5.0, 'They Made Me a Criminal (1939)'), (5.0, 'Star Kid (1997)'), (5.0, 'Santa with Muscles (1996)'), (5.0, 'Saint of Fort Washington, The (1993)'), (5.0, 'Marlene Dietrich: Shadow and Light (1996) '), (5.0, 'Great Day in Harlem, A (1994)'), (5.0, 'Entertaining Angels: The Dorothy Day Story (1996)'), (5.0, 'Boys, Les (1997)'), (4.89884443128923, 'Legal Deceit (1997)'), ...] #基于物品过滤推荐

计算所有物品之间的相似度

itemsim = calSimilarItems(mldata, 50)

print "基于物品过滤推荐:为用户87推荐的电影排名前4部是:"

print getrecommendedItems(mldata, '87', itemsim)[0:10]

# 结果是:[(5.0, "What's Eating Gilbert Grape (1993)"), (5.0, 'Vertigo (1958)'), (5.0, 'Usual Suspects, The (1995)'), (5.0, 'Toy Story (1995)'), (5.0, 'Titanic (1997)'), (5.0, 'Sword in the Stone, The (1963)'), (5.0, 'Stand by Me (1986)'), (5.0, 'Sling Blade (1996)'), (5.0, 'Silence of the Lambs, The (1991)'), (5.0, 'Shining, The (1980)')]

				<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>

Python实现个性化推荐二的更多相关文章

  1. Python实现个性化推荐一

    现如今,网站用推荐系统为你提供个性化的体验,告诉你买啥,吃啥甚至你应该和谁交朋友.尽管每个人口味不同,但大体都适用这个套路.人们倾向于喜欢那些与自己喜欢的其他东西相似的东西,也倾向于与自己身边的人有相 ...

  2. Python个人项目--豆瓣图书个性化推荐

    项目名称: 豆瓣图书个性化推荐 需求简述:从给定的豆瓣用户名中,获取该用户所有豆瓣好友列表,从豆瓣好友中找出他们读过的且评分5星的图书,如果同一本书被不同的好友评5星,评分人数越多推荐度越高. 输入: ...

  3. python 书籍推荐 二

    Python是一中面向对象的编程语言,语法简洁而清晰,具有丰富和强大的类库.对于初学编程者来说,首选Python是个非常棒的选择.   工具/原料 Python Python学习前的准备 1 学习任何 ...

  4. 使用Python3.7配合协同过滤算法(base on user,基于人)构建一套简单的精准推荐系统(个性化推荐)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_136 时至2020年,个性化推荐可谓风生水起,Youtube,Netflix,甚至于Pornhub,这些在互联网上叱咤风云的流媒体 ...

  5. 机器学习算法与Python实践之(二)支持向量机(SVM)初级

    机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...

  6. python机器学习实战(二)

    python机器学习实战(二) 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7159775.html 前言 这篇noteboo ...

  7. 从0开始做垂直O2O个性化推荐-以58到家美甲为例

    从0开始做垂直O2O个性化推荐 上次以58转转为例,介绍了如何从0开始如何做互联网推荐产品(回复"推荐"阅读),58转转的宝贝为闲置物品,品类多种多样,要做统一的宝贝画像比较难,而 ...

  8. 个性化推荐调优:重写spark推荐api

    最近用spark的mlib模块中的协同过滤库做个性化推荐.spark里面用的是als算法,本质上是矩阵分解svd降维,把一个M*N的用户商品评分矩阵分解为M*K的userFeature(用户特征矩阵) ...

  9. 搜索实时个性化模型——基于FTRL和个性化推荐的搜索排序优化

    本文来自网易云社区 作者:穆学锋 简介:传统的搜索个性化做法是定义个性化的标签,将用户和商品通过个性化标签关联起来,在搜索时进行匹配.传统做法的用户特征基本是离线计算获得,不够实时:个性化标签虽然具有 ...

随机推荐

  1. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  2. Servlet过滤器Filter和监听器

    一.Servlet过滤器的概念: *********************************************************************************** ...

  3. js中哪些值会被认为false?

    在javascript中,只有 false null undefined 空字符串 即 “” 数字  0 数字 NaN 会被当作false,其余都是真. 注:字符串 “false” 也会被当作真.

  4. 集合Gk表示这样一堆数字,该集合内的数字有k个1

    问题描述 集合Gk表示这样一堆数字,该集合内的数字有k个1.比如,G1 = { 1, 10, 100, 1000, ...} G2 = {11, 110, 1110 }, ... , Gk { ... ...

  5. chromium之task

    // A task is a generic runnable thingy, usually used for running code on a // different thread or fo ...

  6. postman中 form-data、x-www-form-urlencoded、raw、binary的区别【转】

    链接:https://blog.csdn.net/wangjun5159/article/details/47781443 1.form-data: 就是http请求中的multipart/form- ...

  7. Linux 学习第六天

    一.VIM 1.VIM编辑器 1.1.VIM工作模式 1.1.1.命令模式:复制.剪切.粘贴.搜索等等 1.1.2.输入模式:随意对文件进行内容编辑 1.1.3.末行模式(:):保存退出,编辑环境设置 ...

  8. html5 video获取当前时间和视频总时间长度

    html: <video id="video-active" class="video-active" width="640" hei ...

  9. Discuz被挂马 快照被劫持跳转该如何处理 如何修复discuz漏洞

    Discuz 3.4是目前discuz论坛的最新版本,也是继X3.2.X3.3来,最稳定的社区论坛系统.目前官方已经停止对老版本的补丁更新与升级,直接在X3.4上更新了,最近我们SINE安全在对其安全 ...

  10. categorical[np.arange(n), y] = 1 IndexError: index 2 is out of bounds for axis 1 with size 2

    我的错误的代码是:train_labels = np_utils.to_categorical(train_labels,num_classes = 3) 错误的原因: IndexError: ind ...