不到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.掘金應該出一個文件暫存頁面,數據科學領域的數據集過重要了😓

相關文章
相關標籤/搜索