不到40行 Python 代码打造一个简单的推荐系统

什么是推荐系统

维基百科这样解释道:推荐系统属于资讯过滤的一种应用。推荐系统可以将可能受喜爱的资讯或实物(例如:电影、电视节目、音乐、书籍、新闻、图片、网页)推荐给使用者。python

本质上是根据用户的一些行为数据有针对性的推荐用户更可能感兴趣的内容。好比在网易云音乐听歌,听得越多,它就会推荐越多符合你喜爱的音乐。算法

推荐系统是如何工做的呢?有一种思路以下:微信

用户 A 听了 收藏了 a,b,c 三首歌。用户 B 收藏了 a, b 两首歌,这时候推荐系统就把 c 推荐给用户 B。由于算法判断用户 A,B 对音乐的品味有极大可能一致。spa

推荐算法分类

最多见的推荐算法分为基于内容推荐以及协同过滤。协同过滤又能够分为基于用户的协同过滤和基于物品的协同过滤code

基于内容推荐是直接判断所推荐内容自己的相关性,好比文章推荐,算法判断某篇文章和用户历史阅读文章的相关性进行推荐。cdn

基于用户的协同过滤就是文章开头举的例子。blog

基于物品的协同过滤: 假设用户 A,B,C 都收藏了音乐 a,b。而后用户 D 收藏了音乐 a,那么这时候就推荐音乐 b 给他。排序

动手打造本身的推荐系统

这一次咱们要作的是一个简单的电影推荐,虽然离工业应用还差十万八千里,可是很是适合新手一窥推荐系统的内部原理。数据集包含两个文件:ratings.csv 和 movies.csv。图片

# 载入数据
import pandas as pd
import numpy as np
df = pd.read_csv('data/ratings.csv')
df.head()
复制代码

ratings.csv 包含四个维度的数据:string

  • userId:打分用户的 ID
  • movieId: 被打分电影的 ID
  • rating: 用户给电影的打分,处于[1,5]
  • timestamp: 电影被打分的时间

要推荐电影还须要有电影的名字,电影名字保存在 movies.csv 中:

movies = pd.read_csv('data/movies.csv')
movies.head()
复制代码

将 ratings.csv 和 movies.csv 的数据根据 movieId 合并。

df = pd.merge(df, movie_title, on='movieId')
df.head()
复制代码

咱们此次要作的推荐系统的核心思路是:

  1. 根据全部用户评分判断全部电影与用户 a 已观看的某部电影 A 的类似度
  2. 给用户 a 推荐类似度高且评分高的电影

因此咱们要先有全部用户对全部电影的评分的列联表:

movie_matrix = df.pivot_table(index = 'userId', columns = 'title' ,values = 'rating')
movie_matrix.head()
复制代码

假设用户 A 观看的电影是 air_force_one (1997),则计算列联表中全部电影与 air_force_one (1997) 的相关性。

AFO_user_rating = movie_matrix['Air Force One (1997)']
simliar_to_air_force_one = movie_matrix.corrwith(AFO_user_rating)
复制代码

这样咱们就获得了全部电影与 air_force_one (1997)的相关性。

可是,直接对这个相关性进行排序并推荐最相关的电影有一个及其严重的问题:

ratings = pd.DataFrame(df.groupby('title')['rating'].mean())#计算电影平均得分
ratings['number_of_ratings'] = df.groupby('title')['rating'].count()
import matplotlib.pyplot as plt
%matplotlib inline
ratings['number_of_ratings'].hist(bins = 60);
复制代码

上图是电影被评分次数的直方图,能够看到大量的电影评分次数不足10次。评分次数太少的电影很容易就被判断为高相关性。因此咱们要将这部分的评分删掉。

corr_AFO = pd.DataFrame(similar_to_air_force_one, columns = ['Correlation'])
corr_AFO.dropna(inplace = True)
corr_contact = corr_contact.join(ratings['number_of_ratings'],how = 'left',lsuffix='_left', rsuffix='_right')
corr_AFO[corr_AFO['number_of_ratings']>100].sort_values(by = 'Correlation',ascending = False).head()
复制代码

这样咱们就获得了一个与 air_force_one (1997) 高相关的电影列表。可是高相关有可能评分低(几率低),再从列表里挑几部平均得分高的电影推荐就行了。

叮~叮~叮~

上文的数据集和完整代码我放到微信公众号「数据科学与技术」(read_csv) 了,回复 「推荐」就好啦。

PS.掘金应该出一个文件暂存页面,数据科学领域的数据集过重要了😓

相关文章
相关标签/搜索