协同过滤介绍和简单推荐系统的实现

本文引自http://blog.csdn.net/database_zbye/article/details/8664516

本文介绍推荐系统、协同过滤思想,两种基本的相似度衡量,并用python实现。最后就MovieLens数据集上作出简单的推荐。

一、相关知识

(1)推荐系统

如今,推荐系统已经在多方面得到应用,例如淘宝、当当、亚马逊等网站的商品推荐。而个性化推荐系统则是通过发掘用户的兴趣爱好,作出针对性的推荐。个性化推荐的方法较多,最常用的是协同过滤方法,而本文主要讲的也是基于协同过滤的个性化推荐。

(2)协同过滤

协同过滤技术出现于20世纪70年代,到90年代形成较为成熟的理论框架。协同过滤的基本假设是如果用户x和y对n个项目的评价或行为是相似的,那么他们对其他项目所持有的观点也是相似的,即行为相似的用户兴趣也可能相似。

一个协同过滤算法的基本方法是对大批用户进行搜索,从中找出兴趣相似的用户群。算法会对这些人的所偏爱的内容进行考察,然后构造出推荐列表,推荐给该群体的用户。

(3)Python语言

Python语言一种是一种面向对象的解释型语言,具有跨平台、简单实用、扩展性强等特性,数据结构也非常灵活。Python俗称胶水语言,其语法简洁,类库很多,适合快速开发程序。在做爬虫抓取数据和社交网络分析时学的,此处用的版本是python3.2。

二、相似度测量方法

主要有两种:欧几里得距离和皮尔逊相关度(pearson)

(1)数据集

Prefer以字典形式存放用户看过的电影和评分。

Prefer = {"tommy":{‘War‘:2.3,‘The lord of wings‘:3.0,‘Kongfu‘:5.0},

"lily":{‘War‘:2.0,‘The lord of wings‘:3.6,‘Kongfu‘:4.1},

"jim":{‘War‘:1.9,‘The lord of wings‘:4.0,‘Beautiful America‘:4.7,‘the big bang‘:1.0},

‘jack‘:{‘War‘:2.8,‘The lord of wings‘:3.5,‘Kongfu‘:5.5}

}

(2)、寻找有相似兴趣的用户,方式是比较各用户的评价数据,计算用户间的相似度。主要方法有2种即欧几里得距离和皮尔逊相关度。

2-1欧几里得距离

使用欧几里得距离计算用户的相似度时,将用户评价的物品作为坐标轴,用户填充到坐标体系中。以二维为例,

上图中,Snakes和Dupree为电影,Toby,Lasclle等人对应的点根据其评分情况被画在相应的位置。这样两者在偏好空间中的距离越近,他们的兴趣就越相似。而此模型可以推广至多维情况。

2-2 Pearson相关度评价

欧几里得距离评价法是一种比较简单的方法。但是由于存在一些用户总是倾向于评分过高或过低(相对平均值),这是兴趣相似的用户并不能通过此方法计算出来。Pearson相关系数是根据两组数据与某一直线的拟合程度来衡量的。

此坐标系以用户为坐标轴,用户所评分的电影显示在对应位置。本方法可修正结果,增强准确性。例如TOM, Lily对电影A,B,C的评分为(2, 4.1, 4), (3, 5, 5 ),则用pearson方法得到两者相似度仍然较高,而欧几里得距离法得到的相似度则偏低。实际上是用户Lily倾向于评分更高。

(3)、编程并测试

#---------------欧几里得空间距离方法---------------

设原先距离L,L越小,越相似。本处采用改进的测量方法:sim=1/L+1,sim越大,越相似

def sim_distance(prefer, person1, person2):

sim = {}

for item in prefer[person1]:

if item in prefer[person2]:

sim[item] = 1       #添加共同项到字典中

#无共同项,返回0

if len(sim)==0:

return 0

#计算所有共有项目的差值的平方和

sum_all = sum([pow(prefer[person1][item]-prefer[person2][item], 2)

for item in sim])

#返回改进的相似度函数

return 1/(1+sqrt(sum_all))

#测试

print("\n测试计算欧几里得距离的方法sim_distance()....")

print("sim_distance(dic,‘lily‘,‘jim‘) = ",sim_distance(dic, ‘lily‘, ‘jim‘))

print("sim_distance(dic,‘tommy‘,‘jim‘) = ",sim_distance(dic, ‘tommy‘, ‘jim‘))

print("sim_distance(dic,‘tommy‘,‘lily‘) = ",sim_distance(dic, ‘tommy‘, ‘lily‘))

print("sim_distance(dic,‘tommy‘,‘jack‘) = ",sim_distance(dic, ‘tommy‘, ‘jack‘))

"""

结果:

0.7080595631785951

0.4814560089181300

0.471143138585317

0.5358983848622454

"""

#-----------------------pearson相关度系数------------------------

def sim_pearson(prefer, person1, person2):

sim = {}

#查找双方都评价过的项

for item in prefer[person1]:

if item in prefer[person2]:

sim[item] = 1           #将相同项添加到字典sim中

#元素个数

n = len(sim)

if len(sim)==0:

return -1

# 所有偏好之和

sum1 = sum([prefer[person1][item] for item in sim])  #1.sum([1,4,5,,,])  2.list的灵活生成方式!(Python灵活)

sum2 = sum([prefer[person2][item] for item in sim])  #!!!!写成person1,导致程序一直runtime error!!!!

#求平方和

sum1Sq = sum( [pow(prefer[person1][item] ,2) for item in sim] )

sum2Sq = sum( [pow(prefer[person2][item] ,2) for item in sim] )

#求乘积之和 ∑XiYi

sumMulti = sum([prefer[person1][item]*prefer[person2][item] for item in sim])

#Pearson系数计算 http://baike.baidu.com/view/3891263.htm,计算错误

#num1 = n*sumMulti - sum1*sum2                                 #分子

#num2 = sqrt(n*sum1Sq-pow(sum1,2))*sqrt(n*sum2Sq-pow(sum2,2))

num1 = sumMulti - (sum1*sum2/n)

num2 = sqrt( (sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))

if num2==0:

return 0

return num1/num2

#测试

print("\n测试计算Pearson系数的方法sim_pearson()....")

print("sim_pearson(dic,‘lily‘,‘jim‘) = ",sim_pearson(dic, ‘lily‘, ‘jim‘))

print("sim_pearson(dic,‘tommy‘,‘jim‘) = ",sim_pearson(dic, ‘tommy‘, ‘jim‘))

print("sim_pearson(dic,‘tommy‘,‘lily‘) = ",sim_pearson(dic, ‘tommy‘, ‘lily‘))

print("sim_pearson(dic,‘tommy‘,‘jack‘) = ",sim_pearson(dic, ‘tommy‘, ‘jack‘))

"""

结果:

0.9999999999999991

0.9999999999999988

0.8446877845160871

0.9999999999999973       **[比较tommy和jack,皮尔逊系数和欧几里得距离差别很大,原因是jack一直评分偏高]**

"""

三、获取推荐列表

依然以上面的prefer数据集为基础,根据计算结果将兴趣相似的用户评分较高的电影推荐给用户。

(1)获取相似用户

#从用户评价字典中返回Top-K匹配者

#K,相似度函数 为可选参数

def topMatches(prefer, person, n=2, similarity=sim_pearson):

scores=[ (similarity(prefer,person,other),other) for other in prefer if other!=person ]

#对scores列表排序,从高到底

scores.sort()

scores.reverse()

return scores[0:n]               #返回排序列表, 注意[0:n],仅返回前n项;

#测试

print("\n测试topMatches()方法......")

print(topMatches(dic, ‘tommy‘))

"""

结果:[(0.9999999999999988, ‘jim‘), (0.9999999999999973, ‘jack‘)]   (相似度,姓名)

"""

(2)、获取推荐

# 提供推荐,利用所有人评价的加权均值。  相似度高,影响因子越大。

def getRecommendations(prefer, person, similarity=sim_pearson):

totals = {}

simSums = {}

for other in prefer:

if other == person:

continue

else:

sim = similarity(prefer, person, other)    #计算比较其他用户的相似度

#相似度>0

if sim<=0: continue

for item in prefer[other]:

if item not in prefer[person]:

#加权评价值:相似度*评价值

totals.setdefault(item,0)  #每轮循环开始时初始化为0

totals[item] += prefer[other][item]*sim

#相似度之和

simSums.setdefault(item,0)

simSums[item] += sim

#建立归一化列表

ranks = [ (total/simSums[item],item) for item,total in totals.items() ]

#返回经排序后的列表

ranks.sort()

ranks.reverse()

return ranks

#测试

print("\n测试推荐方法getRecommendations(prefer, person, similarity=sim_pearson)......")

print(getRecommendations(dic, ‘tommy‘))

"""

结果: [(4.7, ‘Beautiful America‘)]

"""

四、利用MovieLens公开数据集做推荐

(1)、文件一loadMovieLens.py,加载测试集数据

def loadMovieLens():

str1 = ‘/data/movielens/u.item‘

#获取影片的id和标题(其他项类似)

movies = {}

for line in open(str1,‘r‘):

(id,title) = line.split(‘|‘)[0:2]   #将返回列表的前2元素赋给元组

movies[id] = title

#print(movies[id])       [测试输出正常,但是遇到UnicodeEncodeError?]

# 加载数据

prefer = {}

for line in open(‘/data/movielens/u.data‘):

(user, movieid, rating,ts) = line.split(‘\t‘)   #数据集中每行有4项

prefer.setdefault(user, {})    #设置字典的默认格式,元素是user:{}字典

prefer[user][movies[movieid]] = float(rating)

# 返回字典:user以及评价过的电影

return prefer

(2)、文件二:recommendation.py 做推荐

和三中介绍的方法放置于同一文件recommendation.py下。

from loadMovieLens import loadMovieLens

print("\n-------------------MovieLens 测试数据集的推荐系统--------------------")

prefers =  loadMovieLens()

print("\n1.*********基于用户的推荐**********\n")

print("用户87的评价列表为:",prefers[‘87‘])

print("\n**********推荐影片*********\n")

tuijian = getRecommendations(prefers, ‘87‘)[0:20]

print(tuijian)

(3)利用MovieLens做测试是出现编码错误提示,后来发现时数据集中某行格式不规范,用软件打开u.item,修改下即可。

参考书籍:programing collective intelligence.

五、MovieLens数据集、Python源代码

下面是数据集和代码下载地址,原先的实验是2013年做的,自己最近整理了下。 这里仅仅实现了评分预测,用来评估算法的精确度(MAE,RMSE,F-Measure)。

(至于”如何向用户u推荐电影“,其实可以对u的所有未评分项目进行评分预测,将预测评分高的推荐给用户u即可!)

时间: 2024-12-16 21:13:27

协同过滤介绍和简单推荐系统的实现的相关文章

推荐系统-协同过滤原理与实现

一.基本介绍 1. 推荐系统任务 推荐系统的任务就是联系用户和信息一方面帮助用户发现对自己有价值的信息,而另一方面让信息能够展现在对它感兴趣的用户面前从而实现信息消费者和信息生产者的双赢. 2. 与搜索引擎比较 相同点:帮助用户快速发现有用信息的工具 不同点:和搜索引擎不同的是推荐系统不需要用户提供明确的需求而是通过分析用户的历史行为来给用户的兴趣建模从而主动给用户推荐出能够满足他们兴趣和需求的信息. 3. 长尾理论 长尾讲述的是这样一个故事:以前被认为是边缘化的.地下的.独立(艺人?)的产品现

推荐算法之基于用户的协同过滤算法

协同过滤是推荐算法中最基本的算法,主要分为基于用户的协同过滤算法和基于物品的协同过滤算法. 这篇文章主要介绍基于用户的协同过滤算法,简单来说,要给用户u作推荐,那么只要找出那些和u之前的行为类似的用户,即和u比较像的用户,把他们的行为推荐给用户u即可.所以基于用户的系统过滤算法包括两个步骤:1)找到和目标用户兴趣相似的用户集合  2)找到这个集合中的用户喜欢的,且目标用户没有听说过的物品推荐给目标用户. 第一步的关键点在于计算用户之间的相似度,相似度一般通过Jaccard公式或者余弦相似度即可求

【Spark机器学习速成宝典】推荐引擎——协同过滤

目录 推荐模型的分类 条目2 条目3 条目4 条目5 条目6 条目7 条目8 条目9 推荐模型的分类 最为流行的两种方法是基于内容的过滤.协同过滤. 基于内容的过滤: 比如用户A买了商品A,商品B与商品A相似(这个相似是基于商品内部的属性,比如"非常好的协同过滤入门文章"和"推荐系统:协同过滤collaborative filtering"比较相似),那么就能将商品B推荐给用户. 协同过滤: 利用的是训练数据是大量用户对商品的评分,即(userID,productI

基于用户的协同过滤算法

基于用户的协同过滤算法-参考<推荐系统实践>一书,作者:项亮 1 import random 2 import math 3 class UserBasedCF: 4 def __init__(self,datafile = None): 5 self.datafile = datafile 6 self.readData() 7 self.splitData(3,47) 8 def readData(self,datafile = None): 9 """ 10

基于flink的协同过滤

最近flink较火,尝试使用flink做推荐功能试试,说干就干,话说flink-ml确实比较水,包含的算法较少,且只支持scala版本,以至flink1.9已经将flink-ml移除,看来是准备有大动作,但后期的实时推荐,flink能派上大用场.所幸基于物品的协同过滤算法相对简单,实现起来难度不大.先看目前推荐整体的架构. 先说一下用到的相似算法:X=(x1, x2, x3, - xn),Y=(y1, y2, y3, - yn)那么欧式距离为: 很明显,值越大,相似性越差,如果两者完全相同,那么

个性化推荐系统原理介绍(基于内容过滤/协同过滤/关联规则/序列模式)

个性化推荐根据用户兴趣和行为特点,向用户推荐所需的信息或商品,帮助用户在海量信息中快速发现真正所需的商品,提高用户黏性,促进信息点击和商品销售.推荐系统是基于海量数据挖掘分析的商业智能平台,推荐主要基于以下信息: 热点信息或商品 用户信息,如性别.年龄.职业.收入以及所在城市等等 用户历史浏览或行为记录 社会化关系 基于人口统计学的推荐机制(Demographic-based Recommendation)是一种最易于实现的推荐方法,它只是简单的根据系统用户的基本信息发现用户的相关程度,然后将相

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

【推荐系统实战】:C++实现基于用户的协同过滤(UserCollaborativeFilter)

好早的时候就打算写这篇文章,但是还是参加阿里大数据竞赛的第一季三月份的时候实验就完成了,硬生生是拖到了十一假期,自己也是醉了...找工作不是很顺利,希望写点东西回顾一下知识,然后再攒点人品吧,只能如此了. 一.问题背景 二.基于用户的协同过滤算法介绍 三.数据结构和实验过程设计 四.代码 一.问题背景 首先介绍一下问题的背景,现在我有四个月的用户.品牌数据<user,brand>,即用户在这四个月中的某一天购买了某个品牌(当然为了简化算法模型,将购买时间省去,后面再说).即现在有这四个月的数据

基于协同过滤的推荐系统

在上一篇博文中,我已经总结了几种主要的推荐方法,其中,基于内容和基于协同过滤是目前的主流算法,很多电子商务网站的推荐系统都是基于这两种算法的.基于内容在第一篇博文中已经详细介绍了,因此本博文主要是介绍基于协同过滤的个性化推荐系统. 协同过滤是一种基于一组兴趣相同的用户或项目进行的推荐,它根据邻居用户(与目标用户兴趣相似的用户)的偏好信息产生对目标用户的推荐列表.协同过滤算法主要分为基于用户的协同过滤算法和基于项目的协同过滤算法. 基于用户的(User based)协同过滤算法是根据邻居用户的偏好