[原]【推荐系统】协同过滤之基于用户的最近邻推荐

1.算法简介


协同过滤(collaborative
filtering)的核心思想:利用其他用户的行为来预测当前用户。协同过滤算法是推荐系统中最基本的,同时在业界广为使用。根据使用的方法不同,可以分为基于用户(user-based)、基于物品(item-based)的最近邻推荐。

基于用户的最近邻推荐的主要思想与kNN有点相似:对于一个给定的评分集,找出与当前用户u口味相近的k个用户;然后,对于用户u没有见过的物品p,利用k个近邻对p进行预测评分。由此引出了两个问题,一是如何度量用户与用户间的相似性(涉及到相似性度量),二是如何进行预测。

相似性度量

常见的用于推荐的相似性度量:Pearson相关系数、余弦相似度、改进的余弦相似度。pearson相关系数用来描诉两组向量一同变化的趋势,取值从+1(强正相关)到-1(强负相关)。用户a和用户b的相似度

其中,表示用户a对物品p的评分,表示用户a的平均评分。Pearson相关系数越接近于1,则说明用户a、b越相似。但Pearson相关系数存在着下列缺陷:

  • 未考虑重叠物品项的数量对相似度的影响

比如:①用户a与用户b有2个重叠项;②用户a与用户c有10个重叠项,且Pearson相关系数小于①。但这并不能说明用户b比用户c更相似于用户b,因为用户的口味(或者说是偏好)是通过一定数量的物品评分反映出来的。过少的重叠项不能用于计算相似度。

  • 如果只有一个重叠项,或重叠项的评分相等,则无法计算Pearson相关系数

在此种情况下,方差为0;由于Pearson相关系数的分母为方差相乘,即为0,0除0无法计算。

余弦相似度定义为向量之间夹角的余弦

基本的余弦方法没有考虑用户的平均评分。针对这个问题,改进余弦相似度

取值在-1到+1之间,与Pearson相关系数一样。

预测评分

先选取k个用户的近邻,利用这k个近邻的评分数据来做预测。对物品p,具体做法是对近邻中给物品p的评分做加权平均;预测用户a对物品p的评分:

其中,N为近邻的集合。

2. 实战

本文采用GoupLens研究组的电影评分MovieLens数据集,MovieLens数据集共有3种,本文选的是ml-100k。

为了便于统计哪些用户对同一部电影进行了评分,我们建立电影-用户的倒排表:输入电影id,输出给过评分的用户。扫描倒排表,即可得到用户间的交互行为。

读取文件,建立词典

import scipy.spatial.distance as ssd
from texttable import Texttable

def getMovieList(item_file):
"""读取u.item文件,获取电影列表: movies[mid]=mtitle
"""

movies = dict()
f = open(item_file)
for raw_item in f.readlines():
item = raw_item.split(‘|‘)
movies[item[0]] = item[1]
return movies

def getRatingsInfo(data_file):
"""读取u.data文件,获取三个词典
用户-电影的评价信息: ratings[uid][mid]=(rating)
用户的平均评分: avgrating[mid]=average_rating
电影-用户的倒排表: movieTouser[mid]=(uid)
"""

ratings = dict()
avgratings = dict()
movieTouser = dict()
f=open(data_file)
for raw_data in f.readlines():
data = raw_data.split(‘\t‘)
#用户-电影词典
if data[0] not in ratings:
ratings[data[0]] = {}
ratings[data[0]][data[1]] = int (data[2])

#电影-用户的倒排表
if data[1] not in movieTouser:
movieTouser[data[1]] = []
movieTouser[data[1]].append(data[0])

#用户的平均评分
for u, movies in ratings.items():
avgratings[u] = 0
for mid, rating in movies.items():
avgratings[u] += rating
avgratings[u] /= float (len(ratings[u]))

return ratings, movieTouser, avgratings


计算用户间的相似度,因为Pearson相关系数容易出现分母为0的情况,这里采用cosine作为相似度度量。考虑到重叠项数量的影响,如果重叠项少于5个,则相似度取接近于0

def calcSimilarity(ratings, u1, u2, args = 5):
"""计算用户u1 u2的相似度"""

ratings_u1=[]; ratings_u2=[]
for mid1, rating1 in ratings[u1].items():
for mid2, rating2 in ratings[u2].items():
if mid1 == mid2:
ratings_u1.append(rating1)
ratings_u2.append(rating2)

if len(ratings_u1) < args: #如果重叠项少于5个,相似度取接近于0
return 0.001
return ssd.cosine(ratings_u1, ratings_u2)


寻找用户u的k近邻。为了避免依次扫描每个用户,只把与用户u发生过交互行为的用户列为可能的近邻(所谓交互行为,即给过同一部电影评分);计算出与用户最相似的k个用户。

def kNearestNeighbor(ratings, movieTouser, user, k):
"""寻找用户user的k个近邻"""

neighbors = []
#如果用户neighbor与用户user都看过一部电影
#那么将用户neighbor看作可能的近邻
for mid, rating in ratings[user].items():
for neighbor in movieTouser[mid]:
if neighbor != user and neighbor not in neighbors:
neighbors.append(neighbor)

dis = dict()
for neighbor in neighbors:
dis[neighbor] = calcSimilarity(ratings, user, neighbor)

return sorted(dis.items(), key = lambda dic: dic[1], reverse = True)[:k]


协同过滤。用户u对电影p是否感兴趣,需要有一个度量来衡量。本文做了简化处理:如果对电影p的评分高于用户u的平均评分,则说明用户u对电影p感兴趣。

def predictRating(user, mid, sorted_dis, ratings, avgratings):
"""预测用户user对电影mid的评分"""

pred = avgratings[user]
numerator = 0.0; denominator = 0.0
for neighbor, dis in sorted_dis:
if mid in ratings[neighbor]:
numerator += dis*(ratings[neighbor][mid] - avgratings[neighbor])
denominator += dis
pred += numerator/denominator
return pred

def userBasedCF(movies, ratings, avgratings, movieTouser, user, k = 20):
"""基于用户的协同过滤"""

recommendList = []; usedList = []
sorted_dis = kNearestNeighbor(ratings, movieTouser, user, k)
for neighbor, dis in sorted_dis:
for mid, rating in ratings[neighbor].items():
#剪枝:用户看过的电影,或已经推荐过的电影
if mid not in ratings[user].items() and mid not in usedList:
pred = predictRating(user, mid, sorted_dis, ratings, avgratings)
if pred > avgratings[user]:
recommendList.append((mid,round(pred,2)))
usedList.append(mid)

recommendList.sort(key = lambda x:x[1], reverse = True)
return recommendList

测试与结果可视化。输入用户‘2’,返回预测评分最高的15部电影。

"""测试与结果可视化"""
if __name__ == "__main__":
#读取数据集,生成字典
movies = getMovieList("u.item")
ratings, movieTouser, avgratings = getRatingsInfo("u.data")

recomMovies = userBasedCF(movies, ratings, avgratings, movieTouser, ‘2‘)[:15]

table = Texttable()
table.set_deco(Texttable.HEADER)
table.set_cols_dtype([‘t‘, # text
‘t‘]) # float (decimal)
table.set_cols_align(["l", "l"])
rows=[]
rows.append([u"recommended movie",u"predicted rating"])
for mid, pred in recomMovies:
rows.append([movies[mid], pred])
table.add_rows(rows)
print table.draw()

代码参考了[2],存在着问题:预测的评分大于5,在数据集中最高评分==5。

3.Referrence

[1] Dietmar
Jannach, et al., Recommender systems : an introduction.

[2] ygrx,[推荐算法]基于用户的协同过滤算法.

[3] Pearson 相关系数--最佳理解及相关应用.

作者:lifehack 发表于2014-5-23 16:22:32 原文链接

阅读:57 评论:0 查看评论

[原]【推荐系统】协同过滤之基于用户的最近邻推荐

时间: 2024-10-12 00:03:27

[原]【推荐系统】协同过滤之基于用户的最近邻推荐的相关文章

【推荐系统】协同过滤之基于用户的最近邻推荐

1.算法简介 协同过滤(collaborative filtering)的核心思想:利用其他用户的行为来预测当前用户.协同过滤算法是推荐系统中最基本的,同时在业界广为使用.根据使用的方法不同,可以分为基于用户(user-based).基于物品(item-based)的最近邻推荐. 基于用户的最近邻推荐的主要思想与kNN有点相似:对于一个给定的评分集,找出与当前用户u口味相近的k个用户:然后,对于用户u没有见过的物品p,利用k个近邻对p进行预测评分.由此引出了两个问题,一是如何度量用户与用户间的相

推荐系统协同过滤基于的两种假设

基于用户的协同过滤,基于的假设是:喜欢相同物品的用户具有相似性. 相同物品越多,用户相似性越大.(有点基于统计的意思) 基于用户的协同过滤推荐机制和基于人口统计学的推荐机制都是计算用户的相似度,并基于“邻居”用户群计算推荐,但它们所不同的是如何计算用户的相似度,基于人口统计学的机制只考虑用户本身的特征,而基于用户的协同过滤机制可是在用户的历史偏好的数据上计算用户的相似度,它的基本假设是,喜欢类似物品的用户可能有相同或者相似的口味和偏好. 基于项目的协同过滤,基于的假设是:同一个人喜欢的几个物品具

推荐算法简介:基于用户的协同过滤、基于物品的协同过滤、基于内容的推荐

参考来源: https://blog.csdn.net/u011748319/article/details/90269818 1.推荐算法 1.1.协同过滤 协同过滤是目前应用最广泛的推荐算法,它仅仅通过了解用户与物品之间的关系进行推荐,而根本不会考虑到物品本身的属性. 可分成两类: 1.基于用户(user-based)的协同过滤 2.基于商品(item-based)的协同过滤 1.1.1.基于用户的协同过滤 基本思想: 基于用户对物品的偏好找到邻居用户(相似用户),然后将邻居用户(相似用户)

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

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

mahout实现基于用户的Mahout推荐程序

/* * 这里做的是一个基于用户的Mahout推荐程序 * 这里利用已经准备好的数据. * */ package byuser; import java.io.File; import java.io.IOException; import java.util.List; import org.apache.mahout.cf.taste.common.TasteException; import org.apache.mahout.cf.taste.impl.model.file.FileDa

《推荐系统》基于用户和Item的协同过滤算法的分析与实现(Python)

1:协同过滤算法简介 2:协同过滤算法的核心 3:协同过滤算法的应用方式 4:基于用户的协同过滤算法实现 5:基于物品的协同过滤算法实现 一:协同过滤算法简介 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐.在问的时候,都习惯于问跟自己口味差不 多的朋友,这就是协同过滤的核心思想. 协同过滤是在海量数据中挖掘出小部分与你品味类似的用户,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的东西

《推荐系统》--协同过滤推荐

<Recommender System An Introduction>,第二章,协同过滤推荐. 定义 协同过滤推荐方法的主要思想是,利用已有用户群过去的行为或意见预测当前用户最可能喜欢哪些东西或对哪些东西感兴趣.此类型的推荐系统当前在业界广泛使用. 纯粹的协同方法的输入数据只有给定的用户-物品评分矩阵,输出数据一般有以下几种类型: (1)表示当前用户对物品喜欢或不喜欢程度的预测数值: (2)n项推荐物品的列表. 基于用户的最近邻推荐 主要思想 这是一种早期方法,user-based near

【读书笔记】《推荐系统(recommender systems An introduction)》第二章 协同过滤推荐

输入:"用户-物品"评分矩阵 输出:(1)用户对某个物品喜欢程度的评分:(2)对于用户,n个推荐的物品列表 1. 基于用户的最近邻推荐(user-based cf) 算法基本假设:(1)如果用户过去有相似的偏好,那么他们未来也会有相似的偏好:(2)用户的偏好不随时间变化而变化 用户相似度计算:user-based cf中pearson相关系数比较好:item-based cf中余弦相似度比较好.学术界在相似度方面有较为深入的研究,例如:很多领域都存在一些所有人都喜欢的物品(热门物品),

推荐系统之协同过滤的原理及C++实现

1.引言 假如你经营着一家网店,里面卖各种商品(Items),有很多用户在你的店里面买过东西,并对买过的Items进行了评分,我们称之为历史信息,现在为了提高销售量,必须主动向用户推销产品,所以关键是要判断出用户除了已经买过的商品之外还会喜欢哪些商品,这就需要利用用户购买商品过程产生的历史信息.协同过滤通常分为基于用户的协同过滤和基于商品的协同过滤. 基于用户的协同过滤:利用用户之间的相似度进行推荐 基于物品的协同过滤:利用物品之间的相似度进行推荐 2.原理 关于协同过滤的原理网上到处都有,思想