【机器学习】使用 Python 构建电影推荐系统
本文將余弦相似度與 KNN、Seaborn、Scikit-learn 和 Pandas 結合使用,創建一個使用用戶評分數據的電影推薦系統。
在日常數據挖掘工作中,除了會涉及到使用Python處理分類或預測任務,有時候還會涉及推薦系統相關任務。
推薦系統用于各個領域,常見的例子包括視頻和音樂服務的播放列表生成器、在線商店的產品推薦器或社交媒體平臺的內容推薦器。在這個項目中,我們創建一個電影推薦器。
協同過濾通過收集許多用戶的偏好或品味信息,對用戶的興趣進行自動預測(過濾)。到目前為止,推薦系統已經發展很長一段時間了,它們的模型基于各種技術,如加權平均、相關性、機器學習、深度學習等等。
自 1995 年以來,Movielens 20M dataset 擁有超過 2000 萬個電影評級和標記活動。在本文中,我們將從movie.csv & rating.csv文件中檢索信息。使用Python庫:Pandas, Seaborn, Scikit-learn和SciPy,使用k-近鄰算法中的余弦相似度訓練模型。
以下是該項目的核心步驟:
導入和合并數據集并創建 Pandas DataFrame
添加必要的特征來分析數據
使用 Seaborn 可視化數據并分析數據
通過設置閾值過濾無效數據
創建一個以用戶為索引、以電影為列的數據透視表
創建 KNN 模型并輸出與每部電影相似的 5 個推薦
導入數據
導入和合并數據集并創建 Pandas DataFrame
MovieLens 20M 數據集自 1995 年以來超過 2000 萬的電影評級和標記活動。數據集獲取:在公眾號:『機器學習研習院』后臺回復:movies
#?usecols?允許選擇自己選擇的特征,并通過dtype設定對應類型 movies_df=pd.read_csv('movies.csv',?usecols=['movieId','title'],?dtype={'movieId':'int32','title':'str'}) movies_df.head()ratings_df=pd.read_csv('ratings.csv',usecols=['userId',?'movieId',?'rating','timestamp'],dtype={'userId':?'int32',?'movieId':?'int32',?'rating':?'float32'}) ratings_df.head()檢查是否存在任何空值以及兩個數據中的條目數。
#?檢查缺失值 movies_df.isnull().sum()movieId 0 title 0 dtype: int64ratings_df.isnull().sum()userId 0 movieId 0 rating 0 timestamp 0 dtype: int64print("Movies:",movies_df.shape) print("Ratings:",ratings_df.shape)Movies: (9742, 2) Ratings: (100836, 4)合并列上的數據幀 'movieId'
#?movies_df.info() #?ratings_df.info() movies_merged_df=movies_df.merge(ratings_df,?on='movieId') movies_merged_df.head()現在已經成功合并了導入的數據集。
添加衍生特征
添加必要的特征來分析數據。
通過按電影標題對用戶評分進行分組來創建'Average Rating' & 'Rating Count'列。
movies_average_rating=movies_merged_df.groupby('title')['rating']\.mean().sort_values(ascending=False)\.reset_index().rename(columns={'rating':'Average?Rating'}) movies_average_rating.head()movies_rating_count=movies_merged_df.groupby('title')['rating']\.count().sort_values(ascending=True)\.reset_index().rename(columns={'rating':'Rating?Count'})?#ascending=False movies_rating_count_avg=movies_rating_count.merge(movies_average_rating,?on='title') movies_rating_count_avg.head()目前已經創建了 2 個新的衍生特征。
數據可視化
使用 Seaborn 可視化數據:
經過分析發現,許多電影在近 10 萬用戶評分的數據集上都有完美的 5 星平均評分。這表明存在異常值,我們需要通過可視化進一步確認。
多部電影的評分比較單一,建議設置一個評分門檻值,以便產生有價值的推薦。
使用 seaborn & matplotlib 可視化數據,以便更好地觀察和分析數據。
將新創建的特征繪制直方圖,并查看它們的分布。設置 bin 大小為80,該值的設置需要具體分析,并合理設置。
#?導入可視化庫 import?seaborn?as?sns import?matplotlib.pyplot?as?plt sns.set(font_scale?=?1) plt.rcParams["axes.grid"]?=?False plt.style.use('dark_background') %matplotlib?inline#?繪制圖形 plt.figure(figsize=(12,4)) plt.hist(movies_rating_count_avg['Rating?Count'],bins=80,color='tab:purple') plt.ylabel('Ratings?Count(Scaled)',?fontsize=16) plt.savefig('ratingcounthist.jpg')plt.figure(figsize=(12,4)) plt.hist(movies_rating_count_avg['Average?Rating'],bins=80,color='tab:purple') plt.ylabel('Average?Rating',fontsize=16) plt.savefig('avgratinghist.jpg')圖1 Average Rating直方圖圖2 Rating Count的直方圖現在創建一個joinplot二維圖表,將這兩個特征一起可視化。
plot=sns.jointplot(x='Average?Rating',y='Rating?Count',data=movies_rating_count_avg,alpha=0.5,?color='tab:pink') plot.savefig('joinplot.jpg')Average Rating和Rating Count的二維圖分析
圖1證實了,大部分電影的評分都是較低的。除了設置閾值之外,我們還可以在這個用例中使用一些更高百分比的分位數。
直方圖 2 展示了“Average Rating”的分布函數。
數據清洗
運用describe()函數得到數據集的描述統計值,如分位數和標準差等。
pd.set_option('display.float_format',?lambda?x:?'%.3f'?%?x) print(rating_with_RatingCount['Rating?Count'].describe())count 100836.000 mean 58.759 std 61.965 min 1.000 25% 13.000 50% 39.000 75% 84.000 max 329.000 Name: Rating Count, dtype: float64設置閾值并篩選出高于閾值的數據。
popularity_threshold?=?50 popular_movies=?rating_with_RatingCount[rating_with_RatingCount['Rating?Count']>=popularity_threshold] popular_movies.head() #?popular_movies.shape至此已經通過過濾掉了評論低于閾值的電影來清洗數據。
創建數據透視表
創建一個以用戶為索引、以電影為列的數據透視表
為了稍后將數據加載到模型中,需要創建一個數據透視表。并設置'title'作為索引,'userId'為列,'rating'為值。
import?os movie_features_df=popular_movies.pivot_table(index='title',columns='userId',values='rating').fillna(0) movie_features_df.head() movie_features_df.to_excel('output.xlsx')接下來將創建的數據透視表加載到模型。
建立 kNN 模型
建立 kNN 模型并輸出與每部電影相似的 5 個推薦
使用scipy.sparse模塊中的csr_matrix方法,將數據透視表轉換為用于擬合模型的數組矩陣。
from?scipy.sparse?import?csr_matrix movie_features_df_matrix?=?csr_matrix(movie_features_df.values)最后,使用之前生成的矩陣數據,來訓練來自sklearn中的NearestNeighbors算法。并設置參數:metric = 'cosine', algorithm = 'brute'
from?sklearn.neighbors?import?NearestNeighbors model_knn?=?NearestNeighbors(metric?=?'cosine',algorithm?=?'brute') model_knn.fit(movie_features_df_matrix)現在向模型傳遞一個索引,根據'kneighbors'算法要求,需要將數據轉換為單行數組,并設置n_neighbors的值。
query_index?=?np.random.choice(movie_features_df.shape[0]) distances,?indices?=?model_knn.kneighbors(movie_features_df.iloc[query_index,:].values.reshape(1,?-1),n_neighbors?=?6)最后在 query_index 中輸出出電影推薦。
for?i?in?range(0,?len(distances.flatten())):if?i?==?0:print('Recommendations?for?{0}:\n'.format(movie_features_df.index[query_index]))else:print('{0}:?{1},?with?distance?of?{2}:'.format(i,?movie_features_df.index[indices.flatten()[i]],distances.flatten()[i]))Recommendations?for?Harry?Potter?and?the?Order?of?the?Phoenix?(2007):1:?Harry?Potter?and?the?Half-Blood?Prince?(2009),?with?distance?of?0.2346513867378235: 2:?Harry?Potter?and?the?Order?of?the?Phoenix?(2007),?with?distance?of?0.3396233320236206: 3:?Harry?Potter?and?the?Goblet?of?Fire?(2005),?with?distance?of?0.4170845150947571: 4:?Harry?Potter?and?the?Prisoner?of?Azkaban?(2004),?with?distance?of?0.4499547481536865: 5:?Harry?Potter?and?the?Chamber?of?Secrets?(2002),?with?distance?of?0.4506162405014038:至此我們已經能夠成功構建了一個僅基于用戶評分的推薦引擎。
總結
以下是我們構建電影推薦系統的步驟摘要:
導入和合并數據集并創建 Pandas DataFrame
為了更好分析數據創建衍生變量
使用 Seaborn 可視化數據
通過設置閾值來清洗數據
創建了一個以用戶為索引、以電影為列的數據透視表
建立一個 kNN 模型,并輸出 5 個與每部電影最相似的推薦
寫在最后
以下是可以擴展項目的一些方法:
這個數據集不是很大,可以在項目中的包含數據集中的其他文件來擴展這個項目的范圍。
可以利用' ratings.csv' 中時間戳,分析評級在一段時間內的變化情況,并且可以在解析我們的模型時,根據時間戳對評級進行加權。
該模型的性能遠優于加權平均或相關模型,但仍有提升的空間,如使用高級 ML 算法甚至 DL 模型。
總結
以上是生活随笔為你收集整理的【机器学习】使用 Python 构建电影推荐系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JSON转List
- 下一篇: 【机器学习】模型又线上线下不一致怎么办?