前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >用9行python代码演示推荐系统里的协同过滤算法

用9行python代码演示推荐系统里的协同过滤算法

原创
作者头像
mariolu
修改2024-03-08 11:55:10
修改2024-03-08 11:55:10
59700
代码可运行
举报
运行总次数:0
代码可运行

一、推荐系统快速入门

推荐系统是属于信息过滤领域的一个范畴,目标在预测用户对某个项目(例如产品、电影、歌曲等)的“评分”或“偏好”。

推荐系统通过与用户交互的痕迹来了解用户的兴趣,从而提供个性化信息。与其他机器学习算法非常相似,推荐系统根据用户过去的行为进行预测。具体来说,它在根据经验预测用户对一组项目的偏好。

从数学上讲,推荐任务设置为:

  • 用户集 (U)
  • 要推荐给 用户集(U)的一组项目 (I)
  • 学习一个基于用户过去交互数据的函数,预测项目 I 到 U 的可能性

根据用于推理的数据,推荐系统大致分为两类:

  1. 基于内容的过滤,使用项目属性。
  2. 协同过滤,除了项目属性之外还使用用户行为(交互)。

推荐系统的一些重要应用包括渗透在我们生活里面的方方面面:

  • 购物网站上的产品推荐
  • 流媒体网站的电影和电视节目推荐
  • 新闻网站上的文章推荐

二、什么是协同过滤?

协作过滤通过使用系统从其他用户收集的交互和数据来过滤信息。它基于这样的想法:对某些项目的评估达成一致的人将来可能会再次达成一致。

这个概念很简单:当我们想找一部新电影观看时,我们经常会向朋友寻求推荐。当然,我们更相信那些与我们有相似品味的朋友的推荐。

大多数协同过滤系统应用所谓的基于相似性索引的技术。在基于邻域的方法中,根据用户与活动用户的相似性来选择多个用户。通过计算所选用户评分的加权平均值来推断活跃用户。

协同过滤系统关注用户和项目之间的关系。项目的相似度由对这两个项目进行评分的用户对这些项目的评分的相似度来确定。

协同过滤有两类: 

  • 基于用户,衡量目标用户与其他用户的相似度。
  • 基于项目,衡量目标用户评分或交互的项目与其他项目之间的相似度。

三、9行 Python 代码实现协同过滤 

协作方法通常使用效用矩阵来制定。推荐模型的任务是学习一个函数来预测每个用户的拟合度或相似度。矩阵通常是非常稀疏、就是维度巨大但里面大多数矩阵元素删除了值。

在下面的矩阵中,每行代表一个用户,而列对应不同电影。余弦相似度是查找向量相似度所需的最简单算法。矩阵中,每一行代表一个用户,而每一列对应不同的电影,每个单元格代表用户对该电影的评分。

3.1余弦相似度(p, q) = pq

____

|p|.|q|

比如说我们有以下数据

那么我们用Python描述余弦相似度

代码语言:python
代码运行次数:0
复制
import math

def consine_similarity(v1, v2):
#computer consine_similarity of v1 and v2: (v1 dot v2)/(||v1||*||v2||)
    sumxx, sumxy, sumyy = 0,0,0
    for i in range(len(v1)):
        x = v1[i]; y = v2[i]
        sumxx += x*x
        sumxy += x*y
        sumyy += y*y
    return sumxy/math.sqrt(sumxx*sumyy)
    
#cosine_similarity(joe, beck) =
v1,v2=[4,4,4,3,2],[5,5,2,2,3]
print (v1, v2, consine_similarity(v1,v2))
    

当新用户加入平台时,我们应用最简单的算法来计算行(用户)或列(电影)的余弦或相关相似度,并推荐 k 最近邻居的项目。

有许多方程可以处理相似性度量的问题,其中一些包括:

  • Pearson similarity
  • Jaccard similarity
  • Spearman rank correlation
  • Mean squared differences
  • Proximity–impact–popularity similarity

3.2 再来看一个用9行代码实现协同过滤算法的例子

这里使用了numpy和pandas库

csv数据文件在这里下载。

big-data-tutorial/data/movie_rating.csv at master · marcelcaraciolo/big-data-tutorial (github.com)

movie_rating.csv文件内容如下:

在第1~3行里,导入了numpy和pandas库,读取了csv数据,然后提取了我们用户作为列,电影为行,然后交叉值是用户打出的电影评分。

In[0~2]:

代码语言:python
代码运行次数:0
复制
import numpy as np; import pandas as pd; from pandas import Series, DataFrame
rating = pd.read_csv('movie_rating.csv')
rp = rating.pivot_table(columns=['critic'],index=['title'],values='rating')

Out[0~2]:

critic

Claudia Puig

Gene Seymour

Jack Matthews

Lisa Rose

Mick LaSalle

Toby

title

Just My Luck

3.0

1.5

NaN

3.0

2

NaN

Lady in the Water

NaN

3.0

3.0

2.5

3

NaN

Snakes on a Plane

3.5

3.5

4.0

3.5

4

4.5

Superman Returns

4.0

5.0

5.0

3.5

3

4.0

The Night Listener

4.5

3.0

3.0

3.0

3

NaN

You Me and Dupree

2.5

3.5

3.5

2.5

2

1.0

Pandas 在没有打分的交叉值里填充了NaN。

第4行里在用户里计算出相似度,以Toby 为例,Pandas使用corrwith() 计算出相似度。分数越接近 1 表明用户口味越相似。这里看到Lisa Rose的口味和Toby很相似,并且 和Gene Seymour最不相似。

In [3~4]:

代码语言:python
代码运行次数:0
复制
rating_toby = rp['Toby']
sim_toby = rp.corrwith(rating_toby)

Out[3~4]:

rating_toby如下:

那么其他人和Toby的用户相似度,用rp和rating_toby计算得出

代码语言:javascript
代码运行次数:0
复制
critic
Claudia Puig     0.893405
Gene Seymour     0.381246
Jack Matthews    0.662849
Lisa Rose        0.991241
Mick LaSalle     0.924473
Toby             1.000000

为了给Toby推荐, 计算其他用户给电影的评分。. 这里只算出Toby还没打分过的电影。也就是示例中的“Just My Luck”, "Lady in the Water"和“The Night Listener”,这三个电影Toby未进行打分,为NaN。

In [5~7]:

代码语言:python
代码运行次数:0
复制
rating_c = rating[rating_toby[rating.title].isnull().values & (rating.critic != 'Toby')]
rating_c['similarity'] = rating_c['critic'].map(sim_toby.get)
rating_c['sim_rating'] = rating_c.similarity * rating_c.rating

接下来先得到其他人对这3部的电影打分rating_c。

然后得到别人除了Tody的rating_c['similarity']的相似度矩阵

最后每个人对每部电影的打分推荐因子,由rating_c['sim_rating']= rating_c.similarity * rating_c.rating得出。

这里的rating_c['sim_rating']已经叠加了用户之间的相似度和 用户对物品的打分。

In [8~9]:

最后使用groupb()以title维度的每个推荐分数。 然后除以权重和进行归一化。基于用户的相似的和他们的评分critics来达到推荐给Toby用户的每个电影打分。

代码语言:python
代码运行次数:0
复制
recommendation = rating_c.groupby('title').apply(lambda s: s.sim_rating.sum() / s.similarity.sum())
recommendation.order(ascending=False)

Out[8~9]:

代码语言:python
代码运行次数:0
复制
title
The Night Listener    3.347790
Lady in the Water     2.832550
Just My Luck          2.530981

这里就是所有的9行代码

In[1~9]:

代码语言:python
代码运行次数:0
复制
rating = pd.read_csv('movie_rating.csv')
rp = rating.pivot_table(cols=['critic'],rows=['title'],values='rating')

rating_toby = rp['Toby']
sim_toby = rp.corrwith(rating_toby)

rating_c = rating[rating_toby[rating.title].isnull().values & (rating.critic != 'Toby')]
rating_c['similarity'] = rating_c['critic'].map(sim_toby.get)
rating_c['sim_rating'] = rating_c.similarity * rating_c.rating

recommendation = rating_c.groupby('title').apply(lambda s: s.sim_rating.sum() / s.similarity.sum())
recommendation.order(ascending=False)

Out[1~9]:

代码语言:javascript
代码运行次数:0
复制
title
The Night Listener    3.347790
Lady in the Water     2.832550
Just My Luck          2.530981

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、推荐系统快速入门
  • 二、什么是协同过滤?
  • 三、9行 Python 代码实现协同过滤 
  • 3.1余弦相似度(p, q) = pq
  • 3.2 再来看一个用9行代码实现协同过滤算法的例子
    • In[0~2]:
    • In [3~4]:
    • In [5~7]:
    • In [8~9]:
    • 这里就是所有的9行代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档