智能推荐--协同过滤(电影推荐)
什么是协同过滤:
协同过滤(Collaborative Filtering recommendation)简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。
协同过滤是应用较广的智能推荐算法,电子商务系统中可以通过用户的历史使用数据向用户推荐用户潜在喜爱的商品。
协同过滤分为基于用户的协同过滤(User-Based)和基于物品的协同过滤(Item-Based)。
1.基于用户的协同过滤(UBCF):
基于用户的协同过滤的基本思想相当简单,基于用户对物品的偏好找到相邻邻居用户,然后将邻居用户喜欢的推荐给当前用户,为具有相同或相似的价值观、思想观、知识水平和兴趣偏好的用户,其对信息的需求也是相似的。
计算上,就是将一个用户对所有物品的偏好作为一个向量来计算用户之间的相似度,找到 K 邻居后,根据邻居的相似度权重以及他们对物品的偏好,预测当前用户没有偏好的未涉及物品,计算得到一个排序的物品列表作为推荐。
举例:
对于用户 A,根据用户的历史偏好,这里只计算得到一个邻居 - 用户 C,然后将用户 C 喜欢的物品 D 推荐给用户 A。
2.基于物品的协同过滤(IBCF):
基于物品的协同过滤的原理和基于用户的协同过滤类似,只是在计算邻居时采用物品本身,而且是从用户的角度,即基于用户对物品的偏好找到相似的物品,然后根据用户的历史偏好,推荐相似的物品给他。
从计算的角度看,就是将所有用户对某个物品的偏好作为一个向量来计算物品之间的相似度,得到物品的相似物品后,根据用户历史的偏好预测当前用户还没有表示偏好的物品,计算得到一个排序的物品列表作为推荐。
例子:
对于物品 A,根据所有用户的历史偏好,喜欢物品 A 的用户都喜欢物品 C,得出物品 A 和物品 C 比较相似,而用户 C 喜欢物品 A,那么可以推断出用户 C 可能也喜欢物品 C。
计算相似度
在构建协同过滤推荐模型时,一个重要的环节就是如何选择合适的相似度计算方法。建立相似度矩阵,计算相似度普遍有这几种方法:皮尔逊相关系数(Pearson Correlation Coefficient)、基于欧几里德距离的相似度、余弦相似度(Cosine-based Similarity)、杰卡德系数(Jaccard similarity coefficient) 。
a 皮尔逊相关系数
皮尔逊相关系数一般用于计算两个定距变量间联系的紧密程度,它的取值在 [-1,+1] 之间。用数学公式表示,皮尔森相关系数等亍两个变量的协方差除于两个变量的标准差。计算公式如下所示:
由于皮尔逊相关系数描述的是两组数据变化移动的趋势,所以在基于用户的协同过滤系统中,经常使用。描述用户购买或评分变化的趋势,若趋势相近则皮尔逊系数趋近于1,也就是我们认为相似的用户。
设(X1,Y1),…,(Xn,Yn)为从样本总体F(x,y)中抽取的样本,则
相关系数和协方差的关系:
皮尔逊相关系数
其中,X,Y不是相互独立,即它们之间存在着一定的关系。
协方差和方差的关系:
b 基于欧几里德距离的相似度
欧几里德距离计算相似度是所有相似度计算里面最简单、最易理解的方法。计算出来的欧几里德距离是一个大于0的数,为了使其更能体现用户之间的相似度,可以把它规约到(0, 1]之间,最终得到如下计算公式:
只要至少有一个共同评分项,就能用欧几里德距离计算相似度;如果没有共同评分项,那么欧几里德距离也就失去了作用。
c 余弦相似度
余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦相似度更加注重两个向量在方向上的差异,而非距离戒长度上。计算公式如下所示:余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦相似度更加注重两个向量在方向上的差异,而非距离戒长度上。计算公式如下所示:
从图上可以看出距离度量衡量的是空间各点间的绝对距离,跟各个点所在的位置坐标(即个体特征维度的数值)直接相关。如果保持X点的位置不变,Y点朝原方向进离坐标轴原点,那么这个时候余弦相似度是保持不变的,因为夹角不变,而X、Y两点的距离显然在发生改变,这就是欧氏距离和余弦相似度的不同之处。
d 杰卡德系数
Jaccard相似系数用于比较有限样本集之间的相似性于差异性。Jaccard系数越大,样本相似度越大。
主要用于比较文本相似度。
案例:电影推荐
读取数据,部分电影的评分如下:
import json
content = None
with open(‘movie_score.txt’, ‘r’, encoding=‘utf-8’) as file:
content = file.read()
content = content.replace("’", ‘"’)
data = json.loads(content)
#转换为数据框
data = pd.DataFrame(data)
#将数据中的空值nan变为0
data = data.fillna(0)
求不同电影的相似度:
mcors = np.corrcoef(mdata, rowvar=0)
mcors = 0.5+mcors*0.5
mcors = pd.DataFrame(mcors, columns=mdata.columns, index=mdata.columns)
计算每个用户每个电影的评分(没有用户评分的电影用相似度估算评分):
def cal_score(matrix,mcors,item,user):
totscore = 0
totsims = 0
score = 0
if pd.isnull(matrix[item][user]) or matrix[item][user]==0:
for mitem in matrix.columns:
if matrix[mitem][user]==0:
continue
else:
totscore += matrix[mitem][user]*mcors[item][mitem]
totsims += mcors[item][mitem]
score = totscore/totsims
else:
score = matrix[item][user]
return score
编写一个函数输入用户名查看推荐的电影与推荐系数:
score_matrix = cal_matscore(mdata,mcors)
for i in range(10):
user = input(str(i)+’.’+‘please input the name of user:’)
print(recommend(mdata,score_matrix,user,2))
user = ‘Toby’ # 检验
while True:
user = input(‘please input the name of user:’)
if user == ‘Stop’:
print(‘Stop recommend!’)
break
else:
print(recommend(mdata,score_matrix,user,2))
运行结果:
输入用户名返回推荐的电影,我们查看Toby的推荐
可以看到首先推荐电影 Lady in the water 推荐系数3.22