基于python的系统构建_利用python构建一个简单的推荐系统
摘要: 快利用python構(gòu)建一個屬于你自己的推薦系統(tǒng)吧,手把手教學(xué),夠簡單夠酷炫。
本文將利用python構(gòu)建一個簡單的推薦系統(tǒng),在此之前讀者需要對pandas和numpy等數(shù)據(jù)分析包有所了解。
什么是推薦系統(tǒng)?
推薦系統(tǒng)的目的是通過發(fā)現(xiàn)數(shù)據(jù)集中的模式,為用戶提供與之最為相關(guān)的信息。當(dāng)你訪問Netflix的時候,它也會為你推薦電影。音樂軟件如Spotify及Deezer也使用推薦系統(tǒng)進行音樂推薦。
下圖說明了推薦系統(tǒng)是如何在電子商務(wù)網(wǎng)站的上下文中工作的。
兩名用戶都在某電商網(wǎng)站購買了A、B兩種產(chǎn)品。當(dāng)他們產(chǎn)生購買這個動作的時候,兩名用戶之間的相似度便被計算了出來。其中一名用戶除了購買了產(chǎn)品A和B,還購買了C產(chǎn)品,此時推薦系統(tǒng)會根據(jù)兩名用戶之間的相似度會為另一名用戶推薦項目C。
推薦系統(tǒng)的主要分類
目前,主流的推薦系統(tǒng)包括基于內(nèi)容的推薦以及協(xié)同過濾推薦。協(xié)同過濾簡單來說就是根據(jù)用戶對物品或者信息的偏好,發(fā)現(xiàn)物品或者內(nèi)容本身的相關(guān)性,或者是發(fā)現(xiàn)用戶的相關(guān)性,然后再基于這些關(guān)聯(lián)性進行推薦。
舉個簡單的例子,如果要向個用戶推薦一部電影,那么一定是基于他/她的朋友對這部電影的喜愛。基于協(xié)同過濾的推薦又可以分為兩類:啟發(fā)式推薦算法(Memory-based algorithms)及基于模型的推薦算法(Model-based algorithms)。啟發(fā)式推薦算法易于實現(xiàn),并且推薦結(jié)果的可解釋性強。啟發(fā)式推薦算法又可以分為兩類:
基于用戶的協(xié)同過濾(User-based collaborative filtering):主要考慮的是用戶和用戶之間的相似度,只要找出相似用戶喜歡的物品,并預(yù)測目標用戶對對應(yīng)物品的評分,就可以找到評分最高的若干個物品推薦給用戶。舉個例子,Derrick和Dennis擁有相似的電影喜好,當(dāng)新電影上映后,Derick對其表示喜歡,那么就能將這部電影推薦給Dennis。
基于項目的協(xié)同過濾(Item-based collaborative filtering):主要考慮的是物品和物品之間的相似度,只有找到了目標用戶對某些物品的評分,那么就可以對相似度高的類似物品進行預(yù)測,將評分最高的若干個相似物品推薦給用戶。舉個例子,如果用戶A、B、C給書籍X,Y的評分都是5分,當(dāng)用戶D想要買Y書籍的時候,系統(tǒng)會為他推薦X書籍,因為基于用戶A、B、C的評分,系統(tǒng)會認為喜歡Y書籍的人在很大程度上會喜歡X書籍。
基于模型的推薦算法利用矩陣分解,有效的緩解了數(shù)據(jù)稀疏性的問題。矩陣分解是一種降低維度的方法,對特征進行提取,提高推薦準確度。基于模型的方法包括決策樹、基于規(guī)則的模型、貝葉斯方法和潛在因素模型。
基于內(nèi)容的推薦系統(tǒng)會使用到元數(shù)據(jù),例如流派、制作人、演員、音樂家等來推薦電影或音樂。如果有人看過并喜歡范·迪塞爾主演的《速度與激情》,那么系統(tǒng)很有可能將他主演的另一部電影《無限戰(zhàn)爭》推薦給這些用戶。同樣,你也可以從某些藝術(shù)家那里得到音樂推薦。基于內(nèi)容的推薦的思想是:如果你喜歡某樣?xùn)|西,你很可能會喜歡與之相似的東西。
數(shù)據(jù)集
我們將使用到Dataquest的數(shù)據(jù)資源中找到更多用于各種數(shù)據(jù)科學(xué)任務(wù)的數(shù)據(jù)集。
推薦系統(tǒng)構(gòu)建
我們將使用movielens構(gòu)建一個基于項目相似度的推薦系統(tǒng),首先導(dǎo)入pandas和numpy。
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
接下來利用pandas中的read_csv()對數(shù)據(jù)進行加載。數(shù)據(jù)集中的數(shù)據(jù)以tab進行分隔,我們需要設(shè)置sep = t來指定字符的分隔符號,然后通過names參數(shù)傳入列名。
df = pd.read_csv('u.data', sep='\t',names=['user_id','item_id','rating','titmestamp'])
接下來,檢查正在處理的數(shù)據(jù)。
df.head()
相比只知道電影的ID,能看到它們的標題更為方便。接下來,下載電影的標題并將它們整合到數(shù)據(jù)集中。
movie_titles = pd.read_csv('Movie_Titles')
movie_titles.head()
因為item_id列是相同的,我們便可以在此列上對數(shù)據(jù)進行合并。
df = pd.merge(df, movie_titles, on='item_id')
df.head()
每列釋義如下:
User_id:用戶ID
Item_id:電影ID
Rating:用戶給電影的評分,介于1到5分之間
Timestamp:對電影進行評分的時間點
Title:電影標題
使用description或info命令,可以得到數(shù)據(jù)集的簡要描述,以幫助我們更好的理解數(shù)據(jù)集。
df.describe()
通過上一步,可以知道電影的平均分為3.52,最高為5分。
接下來構(gòu)建一個包含每部電影的平均評分和被評分次數(shù)的dataframe,用來計算電影間的相關(guān)性。相關(guān)性是一種統(tǒng)計度量,用來表示兩個或多個變量在一起波動的程度,電影之間的相關(guān)系數(shù)越高,越相似。
在本例中,我們將使用皮爾遜相關(guān)系數(shù),它的變化范圍為-1到1。當(dāng)相關(guān)系數(shù)為1時,為完全正相關(guān);當(dāng)相關(guān)系數(shù)為-1時,為完全負相關(guān);相關(guān)系數(shù)越接近于0,相關(guān)度越弱。利用pandas 中的groupby功能創(chuàng)建dataframe,按標題列對數(shù)據(jù)集進行分組,并計算每部電影的平均分。
ratings = pd.DataFrame(df.groupby('title')['rating'].mean())
ratings.head()
接下來計算每部電影被評分的次數(shù),觀察它與電影平均評分之間的關(guān)系。一部5分的電影很可能只有一個用戶評分。從統(tǒng)計學(xué)上來說,把它視為5分電影是不合理的。
因此,在構(gòu)建推薦系統(tǒng)時,我們需要為評分次數(shù)設(shè)置一個閾值。使用pandas中的 groupby功能創(chuàng)建number_of_ratings列,按title列進行分組,然后使用count函數(shù)計算每部電影的被評分次數(shù)。之后,使用head()函數(shù)查看新的dataframe。
ratings['number_of_ratings'] = df.groupby('title')['rating'].count()
ratings.head()
利用pandas中的繪圖功能繪制直方圖,可視化評分分布。
import matplotlib.pyplot as plt
%matplotlib inline
ratings['rating'].hist(bins=50)
從中可以看出,多數(shù)電影的分值在2.5到4分之間。接下來將以同樣的方式對number_of_ratings進行可視化。
ratings['number_of_ratings'].hist(bins=60)
從直方圖中可以清楚地看出大多數(shù)電影都只有較少的評分,那些評分次數(shù)多的電影都擁有較高的知名度。
接下來探索電影評分和被評分次數(shù)之間的關(guān)系。使用seaborn繪制散點圖,通過jointplot()函數(shù)實現(xiàn)。
import seaborn as sns
sns.jointplot(x='rating', y='number_of_ratings', data=ratings)
從圖中可以看出電影的平均評分和被評分次數(shù)之間呈正相關(guān)關(guān)系。圖表顯示,一部電影的評分越高,平均分也就越高。在為每部電影的評分設(shè)置閾值時,這一點尤其重要。
接下來構(gòu)建基于項目的推薦系統(tǒng)。我們需要將數(shù)據(jù)集轉(zhuǎn)換為一個矩陣,以電影標題為列,以user_id為索引,以評分為值。之后會得到一個dataframe,其中列是movie標題,行是user_id。每列代表所有用戶對所有電影的評分。若評分為NaN(Not a Number),則表示用戶沒有對某一部電影進行評分。矩陣被用來計算電影之間的相關(guān)性。使用pandas中的 pivot_table創(chuàng)建電影矩陣。
movie_matrix = df.pivot_table(index='user_id', columns='title', values='rating')
movie_matrix.head()
接下來,使用pandas中的 sort_values工具,設(shè)置升序為false,以便從評分最高的電影中進行選擇,然后使用head()函數(shù)查看分數(shù)前10的電影。
ratings.sort_values('number_of_ratings', ascending=False).head(10)
假設(shè)某用戶看過《空軍一號》和《超時空接觸》,我們想根據(jù)觀看歷史向該用戶推薦電影。通過計算這兩個電影和數(shù)據(jù)集中其他電影的之間的相關(guān)性,尋找與之最為相似的電影,為用戶進行推薦。首先,用movie_matrix中的電影評分創(chuàng)建一個dataframe。
AFO_user_rating = movie_matrix['Air Force One (1997)']
contact_user_rating = movie_matrix['Contact (1997)']
Dataframe中包含user_id和對應(yīng)用戶給這兩個電影的評分。利用如下代碼進行查看。
AFO_user_rating.head()
contact_user_rating.head()
使用pandas中的corwith功能計算兩個dataframe對象的行或列的兩兩相關(guān)關(guān)系,從而得出每部電影與《空軍一號》電影之間的相關(guān)性。
similar_to_air_force_one=movie_matrix.corrwith(AFO_user_rating)
可以看到,《空軍一號》與《直到有你》之間的相關(guān)性是0.867,表明這兩部電影有很強的相似性。
similar_to_air_force_one.head()
接下來,計算《超時空接觸》和其他電影之間的相關(guān)性。程序與上面相同。
similar_to_contact = movie_matrix.corrwith(contact_user_rating)
通過計算,我們發(fā)現(xiàn)《超時空接觸》和《直到有你》之間的相關(guān)性更強,為0.904。
similar_to_contact.head()
由于只有部分用戶對部分電影進行了評分,導(dǎo)致矩陣中有許多缺失的值。為了使結(jié)果看起來更有吸引力,我們將刪除null值并將correlation results轉(zhuǎn)化為dataframe。
corr_contact = pd.DataFrame(similar_to_contact, columns=['Correlation'])
corr_contact.dropna(inplace=True)
corr_contact.head()
corr_AFO = pd.DataFrame(similar_to_air_force_one, columns=['correlation'])
corr_AFO.dropna(inplace=True)
corr_AFO.head()
通過上述步驟,計算出了與《超時空接觸》和《空軍一號》最為相似的電影。然而,有些電影被評價的次數(shù)很低,最終可能僅僅因為一兩個人給了5分而被推薦。設(shè)置閾值可解決這個問題。從之前的直方圖中我們看到評分次數(shù)從100急劇下降,于是我們將閾值設(shè)為100,不過你可以根據(jù)自己的需求進行調(diào)整。接下來,利用number_of_ratings列將兩個dataframe連接起來。
corr_AFO = corr_AFO.join(ratings['number_of_ratings'])
corr_contact = corr_contact.join(ratings['number_of_ratings'])
corr_AFO .head()
corr_contact.head()
獲取并查看前10部最為相關(guān)的電影。
corr_AFO[corr_AFO['number_of_ratings'] > 100].sort_values(by='correlation', ascending=False).head(10)
由于閾值不同,結(jié)果也會有所不同。在設(shè)置閾值后,與《空軍一號》最相似的電影是《獵殺紅色十月》,相關(guān)系數(shù)為0.554。
接下來獲取并查看與《超時空接觸》最為相關(guān)的前10部電影。
corr_contact[corr_contact['number_of_ratings'] > 100].sort_values(by='Correlation', ascending=False).head(10)
《超時空接觸》最相似的電影是《費城》,相關(guān)系數(shù)為0.446,被評分次數(shù)為137。根據(jù)此結(jié)果,我們可以向喜歡《超時空接觸》的用戶推薦列表中的電影。
改進
本文所構(gòu)建的推薦系統(tǒng)可以通過基于記憶的協(xié)同過濾方法進行改進。我們可以將數(shù)據(jù)集劃分為訓(xùn)練集和測試集,使用諸如余弦相似度之類的方法來計算電影之間的相似度。還可以通過建立基于模型的協(xié)同過濾系統(tǒng),更好地處理可伸縮性和稀疏性問題。同時也可以利用如均方根誤差(RMSE)之類的方法對模型進行評估。除此之外,當(dāng)所處理的數(shù)據(jù)量十分龐大時,還可以結(jié)合深度學(xué)習(xí)構(gòu)建推薦系統(tǒng)。自動編碼器和受限的Boltzmann機器也常用于構(gòu)建高級推薦系統(tǒng)。
本文作者:【方向】
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的基于python的系统构建_利用python构建一个简单的推荐系统的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring boot controll
- 下一篇: 耳鸣是怎么回事如何治疗?