基于用户的协同过滤推荐-实现电影推荐

1.协同过滤

  协同过滤(Collaborative Filtering)字面上的解释就是在别人的帮助下来过滤筛选,协同过滤一般是在海量的用户中发现一小部分和你品味比较相近的,在协同过滤中,这些用户称为邻居,然后根据他们喜欢的东西组织成一个排序的目录来推荐给你。问题的重点就是怎样去寻找和你比较相似的用户,怎么将那些邻居的喜好组织成一个排序的目录给你,要实现一个协同过滤的系统,需要以下几个步骤:

  1.收集用户的爱好

  2.找到相似的用户或者物品

  3.计算推荐

  在收集用户的喜欢方面,一般的方式有评分,投票,转发,保存书签,点击连接等等 ,有了用户的喜好之后,就可以通过这些共同的喜好来计算用户之间的相似度了。

2.相似度计算

  相似度的计算一般是基于向量的,可以将一个用户对所有的物品的偏好作为一个向量来计算用户之间的相似度,或者将所有用户对于某一个物品的偏好作为一个向量计算物品之间的相似度,相似度的计算有下列几种方式:

  计算欧几里得距离:

                                  

  利用欧几里得距离计算相似度时,将相似度定义如下:

                                  

  皮尔逊相关系数:

                              

   其中sx,sy表示x和y的标准差。

   Cosine相似度:

                              

   Tanimoto系数,也称作Jaccard系数:

                          

3.计算推荐

  要计算推荐的话必须先要找到和你最相似的用户,这里我们用邻居表示与你最为相似的用户。相似用户的计算可能有很多,在实际中我们会给出一个数字K表示和你最为相似的用户。在计算相似度的时候,理论上要计算你与所有用户的相似度,但是当数据量比较大的时候,这样做是很费时间的 ,数据集中可能有很多用户和你是没有关系的,在计算是完全是没有必要的,所以需要物品到用户的反查表,也就是没一件物品对应的用户信息,有了这个表,就可以过滤掉很多和你没有关系的用户,减少计算量。

  计算出了所有的邻居之后,是不是要将你所有邻居的所有商品推荐给你呢,当然不是了。假设每一个商品的权重为1,计算得到A用户和你的相似度为0.2,B用户和你的相似度为0.7,那么可以将AB用户的所有商品乘以他们对应的相似度大小,得到每一个物品的推荐度大小,比方说A中的商品有a,b,c,B中的商品有c,d,那么a商品的推荐程度就是

0.2,b商品的推荐程度就是0.2.c对应的推荐程度就是1*0.2+1*0.7=0.9,d的推荐度就是0.7,所以在推荐的时候,优先把c推荐给你,其次是d。

  总结来说,推荐的过程就是先计算用户之间的相似度,根据相似度的高低选取前K个用户,在这K个用户中计算没一件物品的推荐程度。

4.实验过程

  针对上面的过程,我们将在MovieLens(http://movielens.org)数据集上进行实验,在实验中,我们主要利用到的数据集中的两个文件u.data和u.item,其中u.item中记录的是电影的相关信息,u.data中主要是用户对电影的评分信息,评分的范围是1-5,文件的每一列分别表示用户ID,电影ID,评分,时间戳。实验主要参考这里


 

import math
from texttable import Texttable
 
def calcSimlaryCosDist(user1, user2):
    sum_x = 0.0
    sum_y = 0.0
    sum_xy = 0.0
    avg_x = 0.0
    avg_y = 0.0
    for 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)
 
    for key1 in user1:
        for key2 in user2:
            if key1[0] == key2[0]:
                sum_xy += (key1[1] - avg_x) * (key2[1] - avg_y)
                sum_y += (key2[1] - avg_y) * (key2[1] - avg_y)
        sum_x += (key1[1] - avg_x) * (key1[1] - avg_x)
 
    if sum_xy == 0.0:
        return 0
    sx_sy = math.sqrt(sum_x * sum_y)
    return sum_xy / sx_sy
 
def readFile(file_name):
    f=open(file_name,"r",encoding='utf-8')
    line=[]
    line=f.readlines()
    f.close()
    return line
 
#读取电影信息,返回电影的字典,key值为电影ID,value值为电影信息
def getMoviesList(file_name):
    lines=readFile(file_name)
    movie_info={}
    for movie in lines:
        arr=movie.split("|")
        movie_info[int(arr[0])]=arr[1:]
    return movie_info
#将rating文件中的信息转化为数组格式
#返回用户ID,电影ID,评分,时间戳的格式
def getRatingInformation(ratings):
    r=[]
    for line in ratings:
        rate=line.split('\t')
        r.append([int(rate[0]),int(rate[1]),int(rate[2])])
    return r
#生成用户评分的数据结构
#输入:[[2,1,5],[2,4,2]...],用户2对电影1的评分是5分
#输出:用户打分字典和电影与值打分关联用户的字典
#rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
def createUserRankDic(rates):
    user_rate_dict={}
    item_to_user={}
    for i in rates:
        user_rank=(i[1],i[2])
        #用户和电影评分之间的字典
        if i[0] in user_rate_dict:
            user_rate_dict[i[0]].append(user_rank)
        else:
            user_rate_dict[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_dict,item_to_user
 
#计算与制定的邻居之间最为相近的邻居
#输入:指定的用户ID,用户对电影的评分表,电影对应的用户表
#输出:与制定用户最为相邻的邻居列表
#    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
#    2.电影字典:dic[电影id]=[用户id1,用户id2...]
def calcNearestNeighbor(userid,user_dict,item_dict):
    neighbors=[]
    for item in user_dict[userid]:
        #在每一部电影与之相关的用户中查找邻居
        for neighbor in item_dict[item[0]]:
            if neighbor!=userid and neighbor not in neighbors:
                neighbors.append(neighbor)
    #计算相似度并输出
    neighbors_dist=[]
    for neighbor in neighbors:
        dist=calcSimlaryCosDist(user_dict[userid],user_dict[neighbor])
        neighbors_dist.append([dist,neighbor])
    neighbors_dist.sort(reverse=True)
    return neighbors_dist
 
def recommendationByUserFC(file_name,userid,k=5):
    test_contents=readFile(file_name)   #读取文件
    test_rates=getRatingInformation(test_contents)  #得到用户电影评分之间关系的标准格式
    # 格式化成字典数据
    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    test_dict,test_item_to_user=createUserRankDic(test_rates)
    #计算与userid最为相近的前k个用户,返回数组的格式为[[相似度,用户id]...]
    neighbors=calcNearestNeighbor(userid,test_dict,test_item_to_user)[:k]
    #计算邻居的每一部电影与被推荐用户之间的相似度大小
    recommend_dict={}
    for neighbor in neighbors:
        neighbor_user_id=neighbor[1]                       #邻居用户的ID
        movies=test_dict[neighbor_user_id]                 #邻居用户对电影的评分列表
        #计算每一部电影对用户的推荐程度大小
        for movie in movies:
            if movie[0] not in recommend_dict:
                recommend_dict[movie[0]]=neighbor[0]
            else:
                recommend_dict[movie[0]]+=neighbor[0]
    #建立推荐的列表
    recommend_list=[]
    for key in recommend_dict:
        recommend_list.append([recommend_dict[key],key])          #将字典转化为list,其中元素的第一项为推荐程度大小,第二项为电影的ID
    recommend_list.sort(reverse=True)                             #根据推荐的程度大小进行排序
    user_movies=[i[0] for i in test_dict[userid]]                 #userid用户评分过的所有电影
    return [i[1] for i in recommend_list], user_movies, test_item_to_user, neighbors
 
if __name__=='__main__':
    movies=getMoviesList('u.item')     #获取电影的列表
    recommend_list, user_movie, items_movie, neighbors = recommendationByUserFC('u.data',1,80)
    neighbors_id=[i[1] for i in neighbors]     #所有邻居的ID
    table = Texttable()
    table.set_deco(Texttable.HEADER)
    table.set_cols_dtype(['t',  # text
                          't',  # float (decimal)
                          't'])  # automatic
    table.set_cols_align(["l", "l", "l"])
    rows = []
    rows.append([u"movie name", u"release", u"from userid"])
    #输出前20个推荐项
    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[:3]])
    table.add_rows(rows)
    print (table.draw())

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
项目完整可用,配合压缩包内数据库可直接运行使用。 eclipse+mysql5.7+jdk1.8 功能:推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜好程度。参考特征的选取可能是从项目本身的信息中提取的,或是基于用户所在的社会或社团环境。 根据如何抽取参考特征,我们可以将推荐引擎分为以下四大类: • 基于内容的推荐引擎:它将计算得到并推荐用户一些与该用户已选择过的项目相似的内容。例如,当你在网上购书时,你总是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。 • 基于协同过滤推荐引擎:它将推荐用户一些与该用户品味相似的其他用户喜欢的内容。例如,当你在网上买衣服时,基于协同过滤推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣品位,并找到与你品味相似的一些用户,将他们浏览和购买的衣服推荐给你。 • 基于关联规则的推荐引擎:它将推荐用户一些采用关联规则发现算法计算出的内容。关联规则的发现算法有很多,如 Apriori、AprioriTid、DHP、FP-tree 等。 • 混合推荐引擎:结合以上各种,得到一个更加全面的推荐效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值