【火爐煉AI】機器學(xué)習(xí)033-構(gòu)建電影推薦系統(tǒng)
(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
電影推薦系統(tǒng)內(nèi)部最關(guān)鍵的部件是推薦引擎腊满,和汽車的發(fā)動機一樣,推薦引擎的作用是產(chǎn)生數(shù)據(jù)動力排惨,提供數(shù)據(jù)計算方案涩堤。從本質(zhì)上說,推薦引擎時一個能預(yù)測用戶興趣點的模型故俐。對于不同的具體項目要求想鹰,推薦引擎也是不一樣的,本文主要介紹專門用于電影推薦系統(tǒng)的推薦引擎構(gòu)建方法药版。
推薦引擎非常重要辑舷,比如在電商網(wǎng)站中,經(jīng)常有龐大的商品目錄槽片,而用戶不太可能查找所有的相關(guān)內(nèi)容何缓,這時候就需要推薦引擎來構(gòu)建合適的推薦系統(tǒng),將用戶可能感興趣的商品推薦到用戶頁面还栓。我們經(jīng)常在購物中看到碌廓,你點擊了筆記本電腦的頁面,系統(tǒng)會給你推薦鼠標剩盒,鍵盤等商品谷婆,其內(nèi)部就是使用了推薦引擎。
1. 尋找數(shù)據(jù)集中的相似用戶
推薦引擎的一個非常重要的任務(wù)是尋找相似的用戶,這樣纪挎,為一位用戶生成的推薦信息也可以推送給與之相似的其他用戶期贫。
下面用代碼來查找與特定用戶相似的其他用戶,用到了上一篇文章中的Pearson 相關(guān)系數(shù)計算函數(shù)廷区。下面代碼的思路是:首先判斷user是否存在dataset中唯灵,然后計算user對所有其他user的相關(guān)系數(shù),放置到一個list中隙轻,然后再對這個list進行逆序排列埠帕,取最前面的K個用戶,即可找到與user最相似的K個用戶玖绿。
def find_similar_users(dataset, user, user_num=3):
if user not in dataset: # 首先保證user在dataset中
raise TypeError('User {} not in dataset!'.format(user))
# 對于所有用戶敛瓷,計算其與user的相似度,此處使用Pearson相關(guān)性
scores=np.array([[other_user,pearson_score(dataset,user,other_user)] for
other_user in dataset if other_user!=user])
# 相關(guān)性都存放在scores這個二維矩陣中斑匪,故而可以通過排序來尋找相似用戶
scores_sorted=np.argsort(scores[:,1])[::-1] # 先排序取坐標呐籽,再逆序
# 獲取最前面的user_num個相似用戶
top_users=scores_sorted[:user_num]
return scores[top_users] # 返回這些user的信息
通過導(dǎo)入movie_ratings數(shù)據(jù)后,計算與John Carson最相似的4個用戶蚀瘸,如下:
# 使用電影數(shù)據(jù)來尋找相似用戶
import json
with open("E:\PyProjects\DataSet\FireAI\movie_ratings.json",'r') as file:
dataset=json.loads(file.read())
user='John Carson'
similar_users=find_similar_users(dataset, user, 4)
print('Users similar to {}---->>>'.format(user))
print('User\t\t\tSimilarity Score\n')
for item in similar_users:
print('{}\t\t{}'.format(item[0],round(float(item[1]),3)))
-------------------------------------輸---------出--------------------------------
Users similar to John Carson---->>>
User Similarity Score
Michael Henry 0.991
Alex Roberts 0.747
Melissa Jones 0.594
Jillian Hobart 0.567
--------------------------------------------完-------------------------------------
2. 創(chuàng)建電影推薦引擎
假設(shè)我們現(xiàn)在有多個用戶對某幾部電影的評價分數(shù)狡蝶,那么怎么構(gòu)建一個電影推薦引擎?給那些已經(jīng)看過一部分電影的用戶推薦其他沒有看過的但是很相關(guān)的電影贮勃?
這些電影評分數(shù)據(jù)都存放在movie_ratings.json文件中贪惹,這個文件的第一個層是用戶名,第二層是電影名稱和該用戶給該電影的評分寂嘉。給用戶A推薦電影的內(nèi)在邏輯是奏瞬,先找出與用戶A相似度比較高的多個用戶,然后找出這些相似用戶已經(jīng)評分過但是用戶A沒有評分的電影集合泉孩,這些電影表示用戶A沒有看過但是其他相似用戶看過硼端,我們推薦的電影就從這個電影集合中選取,那么怎么選取了寓搬?需要構(gòu)建一個選取標準珍昨,此時我們可以計算電影推薦分數(shù),該分數(shù)用相似度和電影評價分數(shù)相乘得到句喷×偷洌可以認為,相似度越高的用戶脏嚷,其看過的電影越推薦,這些用戶評分越高的電影瞒御,表示質(zhì)量越高父叙,越要推薦給用戶A.
基于以上邏輯,編寫的代碼如下:
# 創(chuàng)建電影推薦引擎
def get_recommendations(dataset,user):
if user not in dataset: # 首先保證user在dataset中
raise TypeError('User {} not in dataset!'.format(user))
total_scores={} # 存放的key為電影名稱,value為對該電影的評價乘以相似度
similarity_sums={} # 存放的key為電影名稱趾唱,value為相似度
for other_user in dataset:
if other_user ==user: continue # 確保是其他用戶而非自身
similarity_score=pearson_score(dataset,user, other_user)
# print('other user: ', other_user, 'similarity: ', similarity_score)
if similarity_score<=0: continue # 如果相似度太小則忽略
# 找到還未被該用戶評分,但是卻被other_user評分過的電影
# 這部分電影表示相似的other_ser已經(jīng)看過但是user沒有看過的電影涌乳,
# 推薦的電影肯定來自于這部分
user_not_rating_movies=[]
for movie in dataset[other_user]: # other_user評分過的電影
# if movie not in dataset[user] or dataset[user][movie]==0:
if movie not in dataset[user]:
# 但是user沒有評分過,或者user評分為0(是不是系統(tǒng)認為沒有評分那評分就是0))
user_not_rating_movies.append(movie)
# print(user_not_rating_movies)
# 計算這些user沒有評分過的電影的推薦分數(shù)甜癞,
# 推薦分數(shù)此處用該電影的評價乘以相似度表示
for movie in user_not_rating_movies:
recommend_score=dataset[other_user][movie]*similarity_score
total_scores.update({movie: recommend_score})
similarity_sums.update({movie: similarity_score})
# print('other user: ', other_user, 'total_scores: ', total_scores)
# 判斷total_scores夕晓,如果推薦的總數(shù)為0,表示所有電影都被user評價過悠咱,則不推薦
if len(total_scores) ==0: return [[0,'No Recommendations']]
# 計算每個電影的推薦等級
movie_ranks=np.array([[rec_score/similarity_sums[movie],movie] for
movie, rec_score in total_scores.items()])
# 對第一列進行逆序排列
movie_ranks_desc=movie_ranks[np.argsort(movie_ranks[:,0])[::-1]]
# print(movie_ranks_desc)
return movie_ranks_desc
最后計算一下幾個用戶的推薦的電影列表蒸辆,如下:
import json
with open("E:\PyProjects\DataSet\FireAI\movie_ratings.json",'r') as file:
dataset=json.loads(file.read())
user='John Carson'
movie_ranks=get_recommendations(dataset,user)
print('Recommended movies to {}---->>>'.format(user))
for idx, recommend in enumerate(movie_ranks):
print('{}: {}-->recommend score: {}'.format(idx, recommend[1], recommend[0]))
user='Michael Henry'
movie_ranks=get_recommendations(dataset,user)
print('Recommended movies to {}---->>>'.format(user))
for idx, recommend in enumerate(movie_ranks):
print('{}: {}-->recommend score: {}'.format(idx, recommend[1], recommend[0]))
-------------------------------------輸---------出--------------------------------
Recommended movies to John Carson---->>>
0: No Recommendations-->recommend score: 0
Recommended movies to Michael Henry---->>>
0: Jerry Maguire-->recommend score: 3.0
1: Inception-->recommend score: 3.0
2: Anger Management-->recommend score: 2.0
--------------------------------------------完-------------------------------------
########################小**********結(jié)###############################
1,構(gòu)建電影推薦系統(tǒng)一般有幾個步驟:先找出相似用戶析既,然后找出相似用戶看過的電影而用戶A沒有看過的電影躬贡,最后對這些電影建立一種推薦分數(shù),其分數(shù)越高的越值得推薦眼坏,最后對這些分數(shù)逆序排列拂玻,即可得到推薦列表。
2宰译,關(guān)鍵是要搞清楚推薦邏輯檐蚜,并建立推薦算法,這些算法可能會隨實際應(yīng)用場景不同而不同沿侈。
#################################################################
注:本部分代碼已經(jīng)全部上傳到(我的github)上闯第,歡迎下載。
參考資料:
1, Python機器學(xué)習(xí)經(jīng)典實例肋坚,Prateek Joshi著乡括,陶俊杰,陳小莉譯