简单的豆瓣电影推荐系统demo
簡單的豆瓣電影推薦系統demo
- 前言
- 背景介紹
- 開發部分介紹
- 數據獲取與存儲
- 界面設計
- 算法原理
- 推薦算法與冷啟動簡述
- 基于物品的協同過濾(ItemCF)
- 功能展現
- 界面
- 算法
- 小結
- 參考
推薦畢設前的小項目demo,主要內容是ItemCF+簡單的系統開發
前言
本次實驗學習如何利用python、MySQL作為開發環境(主要調用pymysql、request、json、numpy、pandas等python庫),通過爬取豆瓣電影數據,實現了一個基于基于用戶協同過濾的簡單推薦系統demo,筆者主要行文思路如下圖:
背景介紹
如果說互聯網的目標是連接一切,哪推薦系統的功能與作用就是建立起更加有效率的連接,推薦系統可以連接用戶與內容與服務,可以為企業、政府等組織節省大量的成本,同時將有用的內容精準的投放到個性用戶里,大大節省用戶的時間成本。
開發部分介紹
數據獲取與存儲
本次實驗數據獲取源選取自豆瓣電影,主要通過python中resquest庫對數據進行爬取與處理,再通過pymysql庫實現對數據的存儲(此處未將數據全部導入SQL不作E-R圖展示),最終爬取數據構成如下圖
界面設計
界面設計主要通過python中PyQT5庫進行實現,實現了初始的用戶登錄、用戶注冊與電影檢索等初始功能,同時再結合推薦算法,可以實現推薦系統中對初始用戶的冷啟動、老用戶個性化推薦功能。初始界面如下圖所示:
算法原理
推薦算法與冷啟動簡述
推薦算法的初衷想法就是希望把商品、內容精準的推送到用戶手中,使得商品得到精準的流量,幫助用戶省去選擇和尋找信息的時間成本。
從電影的推薦系統角度看推薦算法,推薦系統主要需要解決的問題是推薦系統的冷啟動、推薦系統怎樣基于用戶的興趣推薦出準確的內容與信息?
對于推薦系統的冷系統的冷啟動問題,主流解決思想有基于用戶的冷啟動、基于物品的冷啟動、基于非個性化的推薦,本次實驗只考慮新用戶注冊的情況,不考慮新物品進入系統的情況,故解決的是用戶的冷啟動問題,解決思想是根據新用戶登入其自定義的個性標簽(感興趣的電影類型)定義出一大致的粗粒度的個性化用戶畫像,再根據這個畫像做出一個個性化推薦的左端界面,右端界面為基于物品的熱度的熱門電影推薦。
完成用戶的“冷啟動”后,系統得到足夠支撐推薦算法的用戶行為數據,基于相關的推薦算法,可以對用戶做出更加精確的推薦。結合筆者所查文獻與資料,
常用推薦算法主要有:基于用戶的協同過濾推薦、基于物品的協同過濾推薦、隱語義模型的推薦、基于圖的推薦。結合所抓取數據的構成與體量,采用基于用戶的協同過濾算法做系統的主要的推薦算法。
基于物品的協同過濾(ItemCF)
基于物品的協同過濾算法是目前業界應用做多的算法,如:亞馬遜、YouTube其推薦算法基礎都是該算法。基于物品的協同過濾在解決物品數量一定,但用戶數量巨大的應用場景上很有優勢,與本次實驗解決問題類型相近故選用(豆瓣網站的電影數量是一定的,但是用戶數量巨大。)在本次實驗中ItemCF算法的實現思想主要為以下兩個步驟:
1.計算物品間的相似度:
從物品上出發,可以定義物品的相似度計算公式為:wij=∣N(i)∩N(j)∣∣N(i)∣w_{i j}=\frac{|N(i) \cap N(j)|}{|N(i)|}wij?=∣N(i)∣∣N(i)∩N(j)∣?
其中分母|N(i)|是喜歡物品i的用戶數,分子∣N(i)∩N(j)∣{|N(i) \cap N(j)|}∣N(i)∩N(j)∣是既喜歡物品i同時也喜歡物品j的用戶數量。不難看出,公式的定義是喜歡物品i的用戶同時也喜歡物品j的用戶比例,該公式一定程度上可以反映物品i、j的相似程度,但是對于j是熱門物品的情況,其很多人都喜歡j,j的體量本身就很大,那么上述公式的計算結果 將接近于1,這對對于致力于挖掘長尾信息的推薦來說顯然是一個不好的特性。因此,在此基礎上加入對物品j權重的懲罰,得到改進的相似度計算公式為:
計算物品相似度的算法部分實現思路為:
(1)建立用戶-物品倒排表(對每個用戶建立一個其喜歡的物品的列表);
(2)對于每個用戶,將其的物品列表兩兩在共現矩陣中加1;
(3)將各用戶的共現矩陣相加得到總的共現矩陣C;
(4)將C矩陣歸一化即得到物品之間的余弦相似矩陣W。
形象的實現思路如圖:
2.根據物品相似度和用戶的歷史行為生成個性化的推薦列表:
在計算得到物品間的相似度后,再同如下公式計算得到用戶u對物品j的興趣:puj?=∑i=N(u)∩s(j,K)wjiruip_{\text {uj }}=\sum_{i=N(u) \cap s(j, K)} w_{j i} r_{u i} puj??=i=N(u)∩s(j,K)∑?wji?rui?
其中N(u)是用戶喜歡的物品的集合,S(j,K)是和物品j最相似的K個物品集合,s(j,K)是與物品j最相似的K個物品的集合,wij是物品i與物品j的相似度,rui是用戶u對物品j的興趣。(在隱反饋數據集中,如果用戶u對i有過行為,即可令rui=1),不難看出,該公式的含義為:和用戶歷史上感興趣的物品越相似的物品,越有可能在用戶的推薦列表中排名越高。
生成個性化用戶推薦列表的算法部分實現思想如下:
(1)計算用戶u對各個物品的興趣得分;
(2)按照用戶u對各物品的興趣得分按從大到小排序后生成推薦列表。
形象化的實現思路如圖:
python實現:
import pandas as pd import numpy as np import random from sklearn.metrics.pairwise import cosine_similarity # 計算余弦相似度# 用戶ID映射 usersMap = dict(enumerate(list(user_df['user_id'].unique()))) # 電影id與其對應索引的映射關系 usersMap = dict(zip(usersMap.values(), usersMap.keys())) # 鍵值互換# 電影ID映射 moviesMap_raw = dict(enumerate(list(movies_df['dataID']))) # 電影id與其對應索引的映射關系 moviesMap = dict(zip(moviesMap_raw.values(), moviesMap_raw.keys())) # 鍵值互換n_users = user_df.user_id.unique().shape[0] # 用戶總數 n_movies = movies_df.Movie_ID.unique().shape[0] # 電影總數data_matrix = np.zeros((n_users, n_movies)) # 用戶-物品矩陣雛形# 構造用戶-物品矩陣 for line in user_df.itertuples():try:data_matrix[usersMap[str(line[1])], moviesMap[line[2]]] = line[3]except:pass# 電影余弦相似度矩陣 item_similarity = cosine_similarity(data_matrix.T) # 轉置之后計算的才是電影的相似度def rec_hot_movies():"""@功能: 獲取熱門推薦電影@參數: 無@返回: 熱門推薦電影列表"""hot_movies = []hot_movies_raw = movies_df[movies_df.date >= 2019]hot_movies_raw = hot_movies_raw[hot_movies_raw.rate >= 8.7]hot_movies_raw = hot_movies_raw.iloc[:,[1,2,3,4,5,6,7,9]]for i in list(hot_movies_raw):temp = []for j in range(len(list(hot_movies_raw.name.unique()))):temp.append(hot_movies_raw['{}'.format(i)].values.tolist()[j])hot_movies.append(temp)hot_rec_movies = [] # 存儲熱門推薦電影for k in range(len(hot_movies[0])):temp_rec_movies = []for l in range(len(hot_movies)):temp_rec_movies.append(hot_movies[l][k])hot_rec_movies.append(temp_rec_movies)return hot_rec_moviesdef Recommend(movie_id, k): # movie_id:電影名關鍵詞,k:為最相似的k部電影"""@功能: 獲得推薦電影列表@參數: 電影ID、每部電影選取最相似的數目@返回: 推薦電影列表"""movie_list = [] # 存儲結果try:# 過濾電影數據集,搜索找到對應的電影的idmovieid = list(movies_df[movies_df['dataID'] == movie_id].Movie_ID)[0]# 獲取該電影的余弦相似度數組movie_similarity = item_similarity[movieid]# 返回前k個最高相似度的索引位置movie_similarity_index = np.argsort(-movie_similarity)[1:k+1] # argsort函數是將數組元素從小到大排列,返回對應的索引數組for i in movie_similarity_index:rec_movies = [] # 每部推薦的電影rec_movies.append(list(movies_df[movies_df.Movie_ID == (i)].name)[0]) # 電影名rec_movies.append(list(movies_df[movies_df.Movie_ID == (i)].actors)[0]) # 主演if pd.isna(list(movies_df[movies_df.Movie_ID == (i)].style2)[0]) and pd.isna(list(movies_df[movies_df.Movie_ID == (i)].style3)[0]):style = list(movies_df[movies_df.Movie_ID == (i)].style1)[0]elif pd.isna(list(movies_df[movies_df.Movie_ID == (i)].style3)[0]):style = list(movies_df[movies_df.Movie_ID == (i)].style1)[0] + ' ' + list(movies_df[movies_df.Movie_ID == (i)].style2)[0]else:style = list(movies_df[movies_df.Movie_ID == (i)].style1)[0] + ' ' + list(movies_df[movies_df.Movie_ID == (i)].style2)[0] + ' ' + list(movies_df[movies_df.Movie_ID == (i)].style3)[0]rec_movies.append(style) # 電影類型rec_movies.append(list(movies_df[movies_df.Movie_ID == (i)].rate)[0]) # 電影評分rec_movies.append(list(movies_df[movies_df.Movie_ID == (i)].url)[0]) # 電影鏈接movie_list.append(rec_movies) # 列表中的元素為列表,存儲相關信息except:passreturn movie_listdef find_user_like(user_id):user_seen_movies = user_df[user_df['user_id'] == '{}'.format(user_id)].movie_id # 用戶看過的電影的IDuserlike_movies = [] # 儲存用戶比較喜歡的電影IDfor i in list(user_seen_movies):if list(user_df[user_df['movie_id'] == i].rating)[0] >=4:userlike_movies.append(list(user_df[user_df['movie_id'] == i].movie_id)[0]) # 找出用戶比較喜歡的電影的IDuser_like_movies = [] # 儲存用戶喜歡的隨機5部try:for i in range(5):user_like_movies.append(random.choice(userlike_movies))rec = []for each in user_like_movies:rec.extend(Recommend(each,7))except:return Nonereturn rec# 代碼實現參考開發者許繼元功能展現
界面
用戶的登錄與注冊
界面檢索
算法
推薦系統的冷啟動:
基于用戶行為數據與ItemCF算法的推薦:
通過對推薦系統中的電影進行打分形成行為數據后生成的推薦如圖:
小結
本次實驗通過python與MySQL實現推薦系統開發部分、ItemCF算法與基于用戶的冷啟動實現了對新老用戶的個性化推薦、最終算法實現+簡答系統開發實現了一個簡單的推薦demo。通過本次實驗,筆者學習到了推薦算法與簡單的推薦系統開發知識,基本完成了一個簡單推薦的從算法到簡單開發的流程,但在的界面的美觀設計、算法的多樣性實現用戶的個性化推薦、實際業務契合度等方面仍有待提高,有待未來進一步研究解決。同時感謝開發er許繼元github項目的資料幫助,沒有這個項目提供的收獲,筆者可能無法短時間內完成這個demo,感謝幫助!
參考
[1]項亮.《推薦系統實踐》.人民郵電出版社,2012.6
[2]許繼元.DoubanMovieRecommendationSystem.github,2020.5
總結
以上是生活随笔為你收集整理的简单的豆瓣电影推荐系统demo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 引路蜂地图API:Gis.Navigat
- 下一篇: 谁控制了我们的浏览器?