推荐算法-基于协同过滤的推荐算法
推荐算法-基于协同过滤的推荐算法
在如今信息量呈爆炸式增长的时代,谷歌百度等搜索引擎为人们查找信息提供了便利,帮助用户快速查找有价值的信息。然而此类查询方式是大众化的,无法根据个人兴趣为用户展示相关的信息,此外搜索引擎要求用户给出明确的信息需求或者是关键字。推荐系统则用于提供个性化的信息,可通过分析用户行为或社交关系在用户需求不明确的情况下为用户提供信息。传统的推荐算法包括基于内容的推荐算法和基于协同过滤的推荐算法以及混合推荐。这篇博客主要是对协同过滤算法进行介绍,进一步的,协同过滤又可分为基于用户和基于物品两类。
基于用户的协同过滤推荐算法代码借鉴于Danni_hgc的电影推荐算法实例代码
基于物品的推荐算法代码主要借鉴于海天一树X
基于用户的协同过滤推荐算法
基本思想
基于用户的协同过滤推荐算法的基本思想就是根据用户朋友的兴趣爱好来推测用户的兴趣爱好,在日常生活中,当你的朋友看了某部电影时,往往会将这部电影分享给你,而你去观看这部电影的概率也会高于陌生人为你推荐这部电影(除电影本来就有很高的热度以外)。简而言之,可以说相似的用户具有相同的兴趣。基于用户的协同过滤方法可分为两个步骤:
1.计算用户与目标用户之间的相似度。
2.将与目标用户兴趣相似的用户喜欢且目标用户未接触的物品推荐给目标用户。
可以通过计算余弦相似度,或者是杰卡德相似系数等方式来计算用户之间的相似度,设 N(u) 为用户 u 喜欢的物品集合,N(v) 为用户 v 喜欢的物品集合,Wuv表示用户u和用户v之间的相似度:
1)余弦相似度
2)杰卡德相似系数
计算余弦相似度的代码:
def calcCosDistSpe(user1,user2):avg_x=0.0avg_y=0.0for key in user1:avg_x+=key[1]avg_x=avg_x/len(user1)for key in user2:avg_y+=key[1]avg_y=avg_y/len(user2)u1_u2=0.0for key1 in user1:for key2 in user2:if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:u1_u2+=1u1u2=len(user1)*len(user2)*1.0sx_sy=u1_u2/math.sqrt(u1u2)return sx_sy
推荐物品,计算出用户相似度之后,需要找出与用户最相似的k个邻居,并将k个邻居看过且用户感兴趣程度较高的电影(除开用户看过的电影)推荐给用户。
寻找用户最相似的k个邻居代码如下:
def calcNearestNeighbor(userid,users_dic,item_dic):neighbors=[]#neighbors.append(userid)for item in users_dic[userid]:for neighbor in item_dic[item[0]]:if neighbor != userid and neighbor not in neighbors:neighbors.append(neighbor)neighbors_dist=[]for neighbor in neighbors:dist=calcCosDistSpe(users_dic[userid],users_dic[neighbor])neighbors_dist.append([dist,neighbor])neighbors_dist.sort(reverse=True)return neighbors_dist
算法实现
数据介绍
数据:mk-100k
u.data内容
user id movie id 评分 其他
196 242 3 881250949
186 302 3 891717742
22 377 1 878887116
244 51 2 880606923
166 346 1 886397596
u.item内容
movie_id movie_name release
1|Toy Story (1995)|01-Jan-1995|
2|GoldenEye (1995)|01-Jan-1995|
3|Four Rooms (1995)|01-Jan-1995|
完整代码
# -*- coding=utf-8 -*-import math
from texttable import Texttable# 读取文件
def readFile(file_name):contents_lines=[]f=open(file_name,"r",encoding='ISO-8859-1')#The encoding was "ISO-8859-1"contents_lines=f.readlines()f.close()return contents_lines
#
# 解压rating信息,格式:用户id\t电影id\t用户rating\t时间
# 输入:数据集合
# 输出:已经解压的排名信息
#
def getRatingInformation(ratings):rates=[]for line in ratings:rate=line.split("\t")rates.append([int(rate[0]),int(rate[1]),int(rate[2])])return rates
#
# 生成用户评分的数据结构
#
# 输入:所有数据 [[2,1,5],[2,4,2]...]
# 输出:1.用户打分字典 2.电影字典
# 使用字典,key是用户id,value是用户对电影的评价,
# rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
#
def createUserRankDic(rates):user_rate_dic={}item_to_user={}for i in rates:user_rank=(i[1],i[2])#电影id和评分if i[0] in user_rate_dic:user_rate_dic[i[0]].append(user_rank)else:user_rate_dic[i[0]]=[user_rank]if i[1] in item_to_user:item_to_user[i[1]].append(i[0])else:item_to_user[i[1]]=[i[0]]return user_rate_dic,item_to_user
# 使用UserFC进行推荐
# 输入:文件名,用户ID,邻居数量
# 输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
#
def recommendByUserFC(file_name,userid,k=5):#读取文件数据test_contents=readFile(file_name)#文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]test_rates=getRatingInformation(test_contents)#格式化成字典数据# 1.用户字典:dic[用户id]=[(电影id,电影评分)...]# 2.电影字典:dic[电影id]=[用户id1,用户id2...]test_dic,test_item_to_user=createUserRankDic(test_rates)#寻找邻居neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]recommend_dic={}for neighbor in neighbors:neighbor_user_id=neighbor[1]movies=test_dic[neighbor_user_id]for movie in movies:#print movieif movie[0] not in recommend_dic:recommend_dic[movie[0]]=neighbor[0]else:recommend_dic[movie[0]]+=neighbor[0]#print len(recommend_dic)#建立推荐列表recommend_list=[]for key in recommend_dic:#print keyrecommend_list.append([recommend_dic[key],key])recommend_list.sort(reverse=True)#print recommend_listuser_movies = [ i[0] for i in test_dic[userid]]return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
# 获取电影的列表
def getMoviesList(file_name):#print sys.getdefaultencoding()movies_contents=readFile(file_name)movies_info={}for movie in movies_contents:movie_info=movie.split("|")movies_info[int(movie_info[0])]=movie_info[1:]return movies_info
#主程序
#输入 : 测试数据集合
if __name__ == '__main__':movies=getMoviesList("D:/PycharmProject/recomender system/data/ml-100k/u.item")recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("D:/PycharmProject/recomender system/data/ml-100k/u.data",305,80)# 推荐列表(电影,用户相似度),用户看的所有电影,看某电影的所有用户,用户邻居(相似度,邻居id)neighbors_id=[ i[1] for i in neighbors]table = Texttable()table.set_deco(Texttable.HEADER)table.set_cols_dtype(['t', # text't', # float (decimal)'t']) # automatictable.set_cols_align(["l", "l", "l"])rows=[]rows.append([u"movie name",u"release", u"from userid"])for movie_id in recommend_list[:20]:#寻找与推荐项目相关的邻居用户from_user=[]for user_id in items_movie[movie_id]:if user_id in neighbors_id:from_user.append(user_id)rows.append([movies[movie_id][0],movies[movie_id][1],from_user[0:5]])#只显示与推荐结果相关的5个邻居用户table.add_rows(rows)print (table.draw())
运行结果
from userid表示这些用户都看过这些电影,为了结果的美观,只打印了五个用户id。
上述计算用户相似度时仅仅考虑到用户与项目之间的关系,而忽略了外在因素。比如最近新上映了两部大导演制作的电影,该导演具有很高的知名度且作品宣传力度大,因此很多用户都会选择去看这两部电影,此时根据用户A和用户B都观看了电影,就简单的认为两个用户相似比较局限。
基于物品的协同过滤推荐算法
基本思想
基于物品的推荐算法主要是根据用户的历史行为信息来推测用户未来的兴趣,将基于物品的协同过滤推荐算法应用于电影推荐中,最基本的思想就是为用户推荐最近看过的电影列表中相似的电影。该方法也可分为计算物品相似度和物品推荐两个步骤,计算物品相似度的方法与计算用户相似度的方法类似。
算法实现
基于物品的协同过滤算法使用的数据集同上,不再作详细的介绍。
1.获取电影的列表
def getMoviesList(file_name):#print sys.getdefaultencoding()movies_contents=readFile(file_name)movies_info={}for movie in movies_contents:movie_info=movie.split("|")movies_info[int(movie_info[0])]=movie_info[1:]return movies_info
2.读取数据
def readData(self):# 读取文件,并生成用户-物品的评分表和测试集self.train = dict()# 用户-物品的评分表for line in open(self.train_file):user, item, score,other = line.strip().split("\t")self.train.setdefault(user, {})self.train[user][item] = int(float(score))
3.3.计算物品相似度
def ItemSimilarity(self):# 建立物品-物品的共现矩阵cooccur = dict() # 物品-物品的共现矩阵buy = dict() # 物品被多少个不同用户购买Nfor user, items in self.train.items():for i in items.keys():buy.setdefault(i, 0)buy[i] += 1cooccur.setdefault(i, {})for j in items.keys():if i == j: continuecooccur[i].setdefault(j, 0)cooccur[i][j] += 1# 计算相似度矩阵self.similar = dict()for i, related_items in cooccur.items():self.similar.setdefault(i, {})for j, cij in related_items.items():self.similar[i][j] = cij / (math.sqrt(buy[i] * buy[j]))return self.similar
4.给用户做推荐
给用户user推荐,前K个相关用户,前N个物品def Recommend(self, user, K=3, N=10):rank = dict()action_item = self.train[user]# 用户user产生过行为的item和评分for item, score in action_item.items():sortedItems = sorted(self.similar[item].items(), key=lambda x: x[1], reverse=True)[0:K]for j, wj in sortedItems:if j in action_item.keys():continuerank.setdefault(j, 0)rank[j] += score * wjreturn dict(sorted(rank.items(), key=lambda x: x[1], reverse=True)[0:N])
5.创建表格,显示推荐结果
table = Texttable()
table.set_deco(Texttable.HEADER)
table.set_cols_dtype(['t', # text't']) # automatic
table.set_cols_align(["l", "l"])
rows=[]
rows.append([u"movie name",u"release"])
6.main()函数
movies=getMoviesList("D:/PycharmProject/recomender system/data/ml-100k/u.item")#得到电影Item的信息
item = ItemBasedCF("D:/PycharmProject/recomender system/data/ml-100k/u.data")
item.ItemSimilarity()
recommedDict = item.Recommend("166")
for movieid in recommedDict:movieid=int(movieid)rows.append([movies[movieid][0], movies[movieid][1]])
table.add_rows(rows)
print(table.draw())
结果展示
结论
基于物品的推荐算法可以预先计算所有物品之间的相似度,对于在线实验来说,基于物品的协同过滤推荐算法优于基于用户的协同过滤算法,但二者都面临着数据稀疏性和冷启动问题。此外,传统的这两类算法的推荐覆盖率和多样性低,难以解决长尾问题。长尾理论中的头部代表的是绝大部分用户的日常需求,尾部则代表少数用户的个性化需求。
推荐算法-基于协同过滤的推荐算法相关推荐
- 基于协同过滤的推荐引擎
探索推荐引擎内部的秘密"系列将带领读者从浅入深的学习探索推荐引擎的机制,实现方法,其中还涉及一些基本的优化方法,例如聚类和分类的应用.同时在理论讲解的基础上,还会结合 Apache Maho ...
- 基于内容的推荐和基于协同过滤推荐
1.基于内容的推荐:根据物品或内容的元数据,发现物品或内容的相关性,然后基于用户以前的喜好记录推荐给用户相似的物品. 如:对于用户 A,他喜欢看电影 A,那么系统就可以给他推荐类似的电影 C. 2.基 ...
- 旅游推荐平台|酒店推荐平台|基于协同过滤算法实现旅游酒店推荐系统
作者主页:编程千纸鹤 作者简介:Java.前端.Python开发多年,做过高程,项目经理,架构师 主要内容:Java项目开发.毕业设计开发.面试技术整理.最新技术分享 收藏点赞不迷路 关注作者有好处 ...
- 基于协同过滤的推荐算法(用户协同、物品协同、模型协同)
文章目录 一.介绍 1.基于用户的协同过滤推荐 2.基于项目(物品)的协同过滤推荐 3.基于模型的协同过滤推荐 二.实现步骤 1.用户协同过滤和物品协同过滤的实现方法 1)收集用户偏好 2)计算用户或 ...
- 基于协同过滤的推荐引擎(理论部分)
记得原来和朋友猜测过网易云的推荐是怎么实现的,大概的猜测有两种:一种是看你听过的和收藏过的音乐,再看和你一样听过这些音乐的人他们喜欢听什么音乐,把他喜欢的你没听过的音乐推荐给你:另一种是看他听过的音乐 ...
- python协同过滤电影推荐_基于协同过滤的电影推荐系统的设计与实现
龙源期刊网 http://www.qikan.com.cn 基于协同过滤的电影推荐系统的设计与实现 作者:张玉叶
- 推荐算法——基于协同过滤CF
https://www.toutiao.com/a6643326861214482957/ 2019-01-06 18:21:09 前边我们已经介绍了推荐算法里的基于内容的推荐算法CB,今天我们来介绍 ...
- 基于协同过滤算法为电视产品制订个性化推荐
1 绪论 1.1 背景 在互联网技术日益发展和进步的时代,各种数据呈现井喷式增长状态,仅2017 年"双十一"天猫旗下购买物品所产生的交易额最终定格在 1682 亿元,其中,无线成 ...
- 推荐算法概述:基于内容的推荐算法、协同过滤推荐算法和基于知识的推荐算法
"无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家.教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家.点这里可以跳转到教程." 所谓推 ...
最新文章
- perf + 火焰图分析程序性能
- 算法系列15天速成——第十天 栈
- POJ 3342 Party at Hali-Bula ——(树型DP)
- 全局容器的创建和使用---单件模式和IOC的容器的应用
- TCP协议通讯流程(三次握手及四次挥手)
- wamp下Apache2.4.x局域网访问403的解决办法
- vue 3D旋转木马轮播图
- vc++网络安全编程范例(14)-openssl bio编程
- 华为鸿蒙二代支持的手机,关于华为鸿蒙,国产厂商中只有2家表示支持
- String、Path、File、Directroy 常用方法总结
- 寄云PaaS平台荣获“优秀创新项目奖”
- 解决win10分辨率过高导致某些软件显示小的办法
- c语言是结构化 模块化的编程语言,结构化程序设计和模块化结构
- 腾讯求职经历(后附大量面试题)
- windows7操作系统安装步骤(精简版)
- 基于VUE的SVG动画处理(一)
- 百度 谷歌 Twitter,这么多短链接服务(Short Url)到底哪家强?
- Coding中UML建模问题释疑
- 解决Heroku“ name is already taken“问题
- Quartus II 13.1的安装与注册