在我看來,作爲一位中國人的我們不管做什麼決定都在面臨多種選擇。例如,如果我這個時候想要買一本書,但是我卻不知道我想看什麼書、不知道類型、不知道方向,那麼這個時候打開各種進行軟件搜索可能會出現各種各樣的結果。我可能會浪費大量時間在互聯網上瀏覽各種並在各個希望淘金的站點中進行拖曳。我可能會尋求其他人的建議。
但是,如果有一個網站或應用程序可以根據我之前閱讀的內容向我推薦書,那麼會很好的幫助到我,不用浪費時間在各種網站上自己去找書,我只需登錄網站或者應用程序就好了!它會根據我的口味量身定製的10本書推薦給我
這就是推薦引擎所做的事情,現如今,大多數企業正在利用它的力量。從亞馬遜到網飛(Netflix),從谷歌到Goodreads,毫不誇張的說推薦引擎是機器學習技術中使用最廣泛的應用之一。
在本文中,我們將介紹各種類型的推薦引擎算法以及在Python中創建推薦引擎的基礎知識。我們還將看到這些算法工作背後的數學原理。最後,我們將使用矩陣分解來創建自己的推薦引擎。
1.什麼是推薦引擎?
在買東西的時候,如果對產品有任何疑問的時候,人們通常傾向於購買他們的朋友或信任的人推薦給他們的產品。這在曾經是人們主要的購買方式。但是隨着數字時代的到來,這個圈子已經擴大到包括利用某種推薦引擎的網站。
推薦引擎使用不同的算法過濾數據,並向用戶推薦最相關的物品。它首先記錄了客戶的過去行爲,並在此基礎上推薦了用戶可能購買的產品。
如果是一個全新的用戶訪問了電子商務網站,則該網站將沒有該用戶的任何歷史記錄。那麼在這種情況下,網站如何向用戶推薦產品呢?一種可能的解決方案是推薦網站內最暢銷的產品,即需求量大的產品。另一個可能的解決方案是推薦可以爲企業帶來最大利潤的產品。
如果我們可以根據客戶的需求和興趣向他們推薦一些商品,那麼它將對用戶的體驗產生積極影響並可能會導致用戶的頻繁訪問。因此,當今的企業正在通過研究用戶的過去行爲來構建智能的推薦引擎。
現在,我們對推薦引擎有了一個大體的瞭解,現在讓我們看一下它是怎麼工作的。
2.推薦引擎的工作方式
在深入探討這個主題之前,首先我們先考慮一下如何向用戶推薦商品:
- 我們可以向用戶推薦在所有用戶中最受歡迎的商品
- 我們可以根據用戶的偏好(用戶特性)將其分爲多個部分,並根據其所屬的部分向他們推薦商品
以上的兩種方法都有其缺點。在第一種情況下,每個用戶最受歡迎的商品都是相同的,因此每個人都會看到相同的推薦。在第二種情況下,隨着用戶數量的增加,用戶特性的數量也會增加。因此,將用戶劃分爲不同的部分將是一項非常困難的任務。
這裏的主要問題是我們無法根據用戶的特定興趣來定製建議。就像亞馬遜推薦你購買筆記本電腦,只是因爲它被大多數購物者購買了。但值得慶幸的是,亞馬遜(或任何其他大公司)都不推薦使用上述方法的產品。他們使用一些個性化的方法來幫助他們更準確地推薦產品。
現在,通過執行以下的步驟來重點介紹推薦引擎的工作方式。
2.1數據收集
這是構建推薦引擎的第一步,也是最關鍵的一步。可以通過兩種方式收集數據:顯式和隱式。 顯式數據是有意提供的信息,即來自用戶的輸入,例如電影分級。隱式數據是不是有意提供的信息,而是從可用數據流(例如搜索歷史,點擊次數,訂單歷史記錄等)中收集的信息。
在上圖中,Netflix正在以用戶對不同電影給出的評分的形式明確地收集數據。
在這裏,用戶的訂單歷史記錄是由Amazon記錄的,這是隱式數據收集模式的一個例子。
2.2數據存儲
數據量決定了模型推薦的質量。例如,在電影推薦系統中,用戶對電影的評分越高,對其他用戶的推薦就越好。數據類型在決定必須使用的存儲類型方面起着重要作用。這種類型的存儲可以包括標準SQL數據庫,NoSQL數據庫或某種對象存儲。
2.3過濾數據
在收集和存儲數據之後,我們必須對其進行過濾,以提取出最終推薦所需的相關信息。
有各種各樣的算法可以幫助我們簡化過濾的過程。在下一節中,我們將詳細介紹每種算法。
2.3.1基於內容的過濾
該算法推薦與用戶過去喜歡的產品相似的產品。
例如,如果某人喜歡電影“盜夢空間”,那麼這個算法將推薦給他屬於同一類型的電影。但是,該算法如何理解從哪個類型中挑選電影並推薦呢?
**以Netflix爲例。**他們以向量的形式保存與每個用戶有關的所有信息。該向量包含用戶過去的行爲,即用戶喜歡/不喜歡的電影以及他們給出的評分。這個向量稱爲輪廓向量。與電影有關的所有信息都存儲在另一個稱爲物品向量的向量中。物品向量包含每部電影的詳細信息,例如類型,演員,導演等。
基於內容的過濾算法找到輪廓向量和物品向量之間的角度的餘弦值,即餘弦相似度。假設A是輪廓向量,B是物品向量,則它們之間的相似度可以計算爲:
基於介於-1到1之間的餘弦值,電影以降序排列,推薦使用以下兩種方法之一:
- Top-n方式:推薦前n部電影(此處n可由業務決定)
- 評分表方法:設置閾值並推薦所有超過該閾值的電影
其他可用於計算相似度的方法是:
- 歐幾里德距離:如果在n維空間中繪製,相似的物品將彼此緊鄰。因此,我們可以計算物品之間的距離,並根據該距離向用戶推薦物品。歐氏距離的公式由下式給出:
- 皮爾遜相關性:它告訴我們兩個項目之間有多少相關性。相關性越高,相似性越高。皮爾遜相關性可以使用以下公式計算:
該算法的主要缺點是它僅限於推薦相同類型的項目。絕不會推薦用戶過去從未購買或不喜歡的產品。因此,如果用戶過去僅觀看或喜歡動作電影,則系統將僅推薦動作電影。這是構建引擎的一種非常狹窄的方法。
爲了改進這種類型的系統,我們需要一種算法,該算法不僅可以根據內容來推薦商品,還可以根據用戶的行爲來推薦商品。
2.3.2協同過濾
讓我們通過一個例子來理解這一點。如果A喜歡《星際穿越》,《盜夢空間》和《前目的地》等三部電影,而B人喜歡《盜夢空間》,《前目的地》和《致命魔術》,那麼他們的興趣幾乎相同。我們可以肯定地說,A應該喜歡《致命魔術》,B應該喜歡《星際穿越》。協同過濾算法使用“用戶行爲”來推薦項目。這是業界最常用的算法之一,因爲它不依賴於任何其他信息。協同過濾技術有多種類型,我們將在下面詳細介紹它們。
基於用戶的協同過濾
該算法首先找到用戶之間的相似度得分。然後,根據相似度評分,挑選出最相似的用戶,並推薦這些相似的用戶之前喜歡或購買的產品。
就我們之前的電影例子來說,該算法根據每個用戶先前對不同電影給予的評分來找到每個用戶之間的相似性。通過計算其他用戶對項目i給出的用戶評分的加權總和,可以計算出用戶u對某個項目的預測。
預測Pu,i由下式給出:
公式解讀,
- Pu,i是一個項目的預測
- Rv,i是用戶v對電影i的評級
- Su,v是用戶之間的相似性
現在,我們在配置文件向量中具有用戶的評分,並基於此我們必須預測其他用戶的評分。爲此我們將要採取以下的步驟:
- 爲了進行預測,我們需要用戶u和v之間的相似性。我們可以利用皮爾遜相關性。
- 首先,我們找到兩個用戶都評價過的物品,並根據這些評價來計算用戶之間的相關性。
- 可以使用相似度值來計算預測。該算法首先計算每個用戶之間的相似度,然後基於每個相似度計算預測結果。具有較高相關性的用戶將趨於相似。
- 基於這些預測值,提出建議。讓我們通過一個例子來理解它:
考慮用戶電影評分矩陣:
用戶/電影 | X1 | X2 | X3 | X4 | X5 | 平均用戶評分 |
---|---|---|---|---|---|---|
A | 4 | 1 | – | 4 | – | 3 |
B | – | 4 | – | 2 | 3 | 3 |
C | – | 1 | – | 4 | 4 | 3 |
這裏我們有一個用戶電影分級矩陣。爲了更實際地理解這一點,讓我們在上表中找到用戶(A,C)和(B,C)之間的相似性。由A和C評級的電影是電影x2和x4,由B和C評級的電影是x2,x4和x5。
用戶A和C之間的相關性大於B和C之間的相關性。因此,用戶A和C具有更高的相似性,並且將向用戶C推薦用戶A喜歡的電影,反之亦然。
該算法非常耗時,因爲它涉及爲每個用戶計算相似度,然後爲每個相似度分數計算預測。處理此問題的一種方法是僅選擇幾個用戶(鄰居)而不是全部進行預測,也就是我們不選擇對所有相似性值進行預測,而是僅選擇幾個相似性值。選擇鄰居的方法有很多:
- 選擇一個閾值相似度,然後選擇高於該值的所有用戶
- 隨機選擇用戶
- 以相似度值從大到小的順序排列鄰居,並選擇前N個用戶
- 使用集羣選擇鄰居
當用戶數較少時,此算法很有用。當有大量用戶時,此方法無效,因爲計算所有用戶對之間的相似度將花費大量時間。這導致我們進行物品-物品協同過濾,當用戶數量超過建議的物品數時,這種方法是有效的。
基於物品的協同過濾
在該算法中,我們計算每對項目之間的相似度。
因此,在我們的案例中,我們將發現每個電影對之間的相似性,並以此爲基礎,推薦過去用戶喜歡的相似電影。該算法的工作原理與基於用戶的協同過濾類似,只是有一點點變化–我們計算“項目-鄰居”的加權總和,而不是計算“用戶-鄰居”的加權總和。預測如下:
現在我們將發現項目之間的相似性。
現在,由於我們有了每部電影和評分之間的相似性,因此進行了預測,並根據這些預測推薦了類似的電影。讓我們通過一個例子來理解它。
用戶/電影 | x1 | X2 | X3 | X4 | X5 |
---|---|---|---|---|---|
A | 4 | 1 | 2 | 4 | 4 |
B | 2 | 4 | 4 | 2 | 1 |
C | – | 1 | – | 3 | 4 |
平均物品評分 | 3 | 2 | 3 | 3 | 3 |
這裏的平均物品評分是對特定物品給予的所有評分的平均值(將其與我們在基於用戶的協同過濾中看到的表進行比較)。與我們之前看到的基於用戶的相似度不同,我們查找到的基於項目的相似度。
電影x1和x4之間的相似度大於電影x1和x5之間的相似度。因此,基於這些相似值,如果有任何用戶搜索電影x1,那麼將會向他們推薦電影X4,反之亦然。在進一步實施這些概念之前,我們必須知道一個問題的答案–如果在數據集中添加新用戶或新物品,將會發生什麼?這被稱爲 冷啓動。冷啓動可以有兩種類型:
- 用戶冷啓動
- 物品冷啓動
用戶冷啓動意味着在數據集中引入了一個新用戶。由於沒有該用戶的歷史記錄,因此係統不知道該用戶的首選項。向該用戶推薦物品變得越來越困難。那麼,如何解決這個問題呢?一種基本方法是應用基於流行度的策略,即推薦最受歡迎的物品。這些可以通過最近整體或區域流行的內容來確定。一旦我們瞭解了用戶的喜好,推薦物品就會更加容易。
另一方面,物品冷啓動意味着將新產品投放市場或添加到系統中。用戶行爲是對於確定任何產品的價值的最重要的因素。物品獲得的互動越多,我們的模型就越容易將物品推薦給合適的用戶。我們可以利用基於內容的過濾來解決此問題。系統首先將新產品的內容用於推薦,然後最終用戶對該產品執行操作。
現在,使用Python中的一個案例研究來鞏固對這些概念的理解。準備好你的電腦,因爲這將會很有趣!
3.使用MovieLens數據集的Python案例研究
我們將處理MovieLens數據集,並建立一個模型來向最終用戶推薦電影。這些數據是由明尼蘇達大學的GroupLens研究項目收集的。該數據集包括:
- 從943個用戶對1682個電影中選出的10萬個評分(1-5分)
- 用戶的人口統計信息(年齡,性別,職業等)
首先,我們將導入標準庫並使用Python讀取數據集。你可以通過下方的代碼,幫助你進行入門。你可以在自己的電腦上運行代碼並獲取輸出:
# importing libraries
import pandas as pd
import numpy as np
# 傳遞每個CSV的列名,因爲該文件沒有給出列名,使用Pandas進行讀取他們
#你可以從readme文件中檢查列名
#閱讀用戶文件
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('ml-100k/u.user', sep='|', names=u_cols,encoding='latin-1')
# 閱讀評級文件:
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols,encoding='latin-1')
# 閱讀物品文件:
i_cols = ['movie id', 'movie title' ,'release date','video release date', 'IMDb URL', 'unknown', 'Action', 'Adventure',
'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy',
'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western']
items = pd.read_csv('ml-100k/u.item', sep='|', names=i_cols,
encoding='latin-1')
#加載數據集之後,我們應該查看每個文件的內容 (用戶, 評分, 物品).
#查看用戶文件
print("\nUser Data :")
print("shape : ", users.shape)
print(users.head())
#數據集中有943個用戶,每個用戶有5個特徵,也就是用戶ID,年齡,性別,職業,和編碼
# 評分數據
print("\nRatings Data :")
print("shape : ", ratings.shape)
print(ratings.head())
# 我們有不同的用戶和電影的組合的10萬行數據量的評分,現在最後檢查物品文件
# Item Data
print("\nItem Data :")
print("shape : ", items.shape)
print(items.head())
該數據集包含1682部電影的屬性。有24列,其中最後19列指定特定電影的類型。這些列都是二進制列,即值爲1表示電影屬於該類型,否則爲0。
數據集已由GroupLens分爲訓練集和測試集,其中每個用戶的測試數據具有10個等級,即總計9,430行。我們將把這兩個文件讀入我們的Python中。
#創建列名
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
#讀取訓練集
ratings_train = pd.read_csv('ml-100k/ua.base', sep='\t', names=r_cols, encoding='latin-1')
#讀取測試集
ratings_test = pd.read_csv('ml-100k/ua.test', sep='\t', names=r_cols, encoding='latin-1')
#查看訓練集與測試集
ratings_train.shape, ratings_test.shape
現在是構建我們推薦的引擎的時候了!
4.從頭開始構建協同過濾模型
我們將根據基於用戶相似度和基於物品相似度進行推薦電影。爲此,首先我們需要計算唯一身份用戶和電影的數量。
n_users = ratings.user_id.unique().shape[0]
n_items = ratings.movie_id.unique().shape[0]
現在,我們將創建一個用戶-物品向量,該向量可用於計算用戶和物品之間的相似度。
data_matrix = np.zeros((n_users, n_items))
for line in ratings.itertuples():
data_matrix[line[1]-1, line[2]-1] = line[3]
現在,我們將計算相似度。我們可以使用sklearn中的pairwi se_distance函數來計算餘弦相似度。
from sklearn.metrics.pairwise import pairwise_distances
user_similarity = pairwise_distances(data_matrix, metric='cosine')
item_similarity = pairwise_distances(data_matrix.T, metric='cosine')
這爲我們提供了數組形式的基於物品和基於用戶的相似度。下一步是基於這些相似性進行預測。讓我們定義一個函數來做到這一點。
def predict(ratings, similarity, type='user'):
if type == 'user':
mean_user_rating = ratings.mean(axis=1)
#我們用np.newaxis使得mean_user_rating具有與ratings相同的格式
ratings_diff = (ratings - mean_user_rating[:, np.newaxis])
pred = mean_user_rating[:, np.newaxis] + similarity.dot(ratings_diff) / np.array([np.abs(similarity).sum(axis=1)]).T
elif type == 'item':
pred = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])
return pred
最後,我們將基於用戶相似性和物品相似性進行預測。
user_prediction = predict(data_matrix, user_similarity, type='user')
item_prediction = predict(data_matrix, item_similarity, type='item')
事實證明,我們還有一個可自動生成所有這些推薦的庫。現在讓我們學習如何在Python中使用turicreate創建推薦引擎。要熟悉turicreate並將其安裝在你的計算機上,請上GitHub上搜索turicreate。
5.使用Turicreate建立簡單的受歡迎程度和協作過濾模型
安裝turicreate之後,首先讓我們導入它,並在我們的環境中讀取訓練和測試數據集。由於我們將使用turicreate,因此需要在SFrame中轉換數據集。
import turicreate
train_data = turicreate.SFrame(ratings_train)
test_data = turicreate.Sframe(ratings_test)
我們具有用戶行爲以及用戶和電影的屬性,因此我們可以製作基於內容的內容協同過濾算法。我們將從一個簡單的流行度模型開始,然後構建一個協同過濾模型。
首先,我們將建立一個模型,該模型將根據最受歡迎的選擇來推薦電影,即所有用戶都收到相同推薦的模型。我們將使用turicreate推薦功能的 popularity_recommender函數。
popularity_model = turicreate.popularity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating')
我們使用的各種參數:
- train_data:包含所需訓練數據的SFrame
- user_id:代表每個用戶ID的列名
- item_id:代表要推薦的每個物品的列名(movie_id)
- **目標:**代表用戶給出的分數/等級的列名
現在是預測時間!我們將爲數據集中的前5個用戶推薦前5個物品。
popularity_recomm = popularity_model.recommend(users=[1,2,3,4,5],k=5)
popularity_recomm.print_rows(num_rows=25)
注意,所有用戶的建議都是相同的-1467、1201、1189、1122、814。而且它們的順序相同的!這確認所有推薦電影的平均評分爲5,即所有觀看該電影的用戶都將其評爲最高評分。因此,我們的評分系統可以按預期工作。
建立受歡迎度模型後,我們現在將建立一個協作過濾模型。讓我們訓練商品相似性模型,併爲前5個用戶提出前5個建議。
#訓練模型
item_sim_model = turicreate.item_similarity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating', similarity_type='cosine')
#提出推薦
item_sim_recomm = item_sim_model.recommend(users=[1,2,3,4,5],k=5)
item_sim_recomm.print_rows(num_rows=25)
在這裏,我們可以看到每個用戶的建議(movie_id)是不同的。因此個性化是存在的,即對於不同的用戶,我們有不同的推薦集。
在此模型中,我們沒有每個用戶給出的每部電影的評分。我們必須找到一種方法來預測所有這些缺失的評分。爲此,我們必須找到一組可以定義用戶如何評價電影的特徵。這些稱爲潛在特徵。我們需要找到一種從現有特徵中提取最重要的潛在特徵的方法。下一部分將介紹的矩陣分解是一種這樣的技術,它使用較低維度的密集矩陣並有助於提取重要的潛在特徵。
6.矩陣分解簡介
讓我們用一個例子來了解矩陣分解。考慮由不同用戶給不同電影的用戶電影評級矩陣(1-5)。
這裏的user_id是不同用戶的唯一ID,每部電影也都分配了唯一的ID。評分爲0.0表示用戶尚未對特定電影評分(1是用戶可以給予的最低評分)。我們要預測這些缺失的評分。使用矩陣分解,我們可以找到一些潛在的特徵,這些這些特徵可以確定用戶如何評價電影。我們將矩陣分解爲組成部分,使這些部分的乘積將生成原始矩陣。
假設我們必須找到k個潛在特徵。因此,我們可以將評級矩陣R(MxN)分爲P(MxK)和Q(NxK),以使P x QT(此處QT是Q矩陣的轉置)近似於R矩陣:
公式內容:
- M是用戶總數
- N是電影總數
- K是總潛在特徵
- R是MxN用戶電影評級矩陣
- P是MxK用戶特徵關聯矩陣,表示用戶與特徵之間的關聯
- Q是NxK項特徵相關性矩陣,表示電影和特徵之間的關聯
- Σ是KxK對角特徵權重矩陣,表示特徵的基本權重
通過矩陣分解選擇潛在特徵可消除數據中的噪聲。怎麼樣?好吧,它刪除了那些無法確定用戶如何評價電影的特徵。要獲得用戶puk對一部電影qik的所有潛在特徵k的評分,我們可以計算這兩個向量的點積,並將它們相加,得到基於所有潛在特徵的評分。
這就是矩陣分解爲我們提供未由用戶評級的電影的評級的方式。但是,如何將新數據添加到我們的用戶-電影評分矩陣中呢?也就是說新用戶加入並對電影進行評分,我們如何將這些數據添加到現有矩陣中?
讓我用矩陣分解方法使你更輕鬆的理解。如果有新用戶加入系統,則對角特徵權重矩陣Σ以及項目特徵相關性矩陣Q都將保持不變。唯一的變化將發生在用戶特徵相似度矩陣P中。我們可以應用一些矩陣乘法方法可以做到這一點。
我們有,
讓我們在兩邊都乘以Q。
現在,我們有
所以,
進一步簡化,我們可以得到P矩陣:
這是更新後的用戶特徵相似性矩陣。類似地,如果將新電影添加到系統中,我們可以遵循類似的步驟來獲取更新的物品特徵相關性矩陣Q。
記住,我們將R矩陣分解爲P和Q。但是我們如何確定哪個P和Q矩陣將逼近R矩陣呢?我們可以使用梯度下降算法來做到這一點。此處的目的是實際等級與使用P和Q估算的評分之間的平方誤差最小。該平方誤差由下式給出:
這裏,
- eui是錯誤
- rui是用戶u對電影i的實際評分
- řui是用戶u對電影i的預測評分
我們的目標是確定p和q的值,使得誤差最小化。我們需要更新p和q值,以便獲得這些矩陣的優化值,從而使誤差最小。現在,我們將爲puk和qki定義一個更新規則。梯度下降中的更新規則由要最小化的誤差的梯度定義。
由於現在我們有了梯度,我們可以爲puk和qki應用更新規則。
α是學習速率決定每個更新的大小。可以重複上述的更新,直到將錯誤最小化爲止。完成之後,我們將獲得可用於預測收視率的最佳P和Q矩陣。讓我們快速回顧一下該算法的工作原理,然後我們將構建推薦引擎來預測未評分電影的評分。
以下是矩陣分解如何用於預測收視率的方法:
# for f = 1,2,....,k :
# for rui ε R :
# predict rui
# update puk and qki
因此,基於每個潛在特徵,將使用預測的rui值填充R矩陣中所有缺失的評分。然後使用梯度下降對puk和qki進行更新,並獲得它們的最佳值。可以如下顯示:
現在,我們已經瞭解了該算法的內部工作原理,我們將舉一個例子,看看如何將矩陣分解爲它的組成部分。
考慮一個2 X 3矩陣A 2X3,如下所示:
在這裏,我們有2個用戶和3個電影的相應評分。現在,我們將把這個矩陣分解爲子部分,像這樣:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nO23UsOj-1589942971148)(.\圖片\14.png)]
AAT的特徵值將給我們P矩陣,而ATA的特徵值將給我們Q矩陣。Σ是AAT或ATA的特徵值的平方根。
計算AAT的特徵值。
因此,AAT的特徵值是25、9。類似地,我們可以計算ATA的特徵值。這些值將分別爲25、9、0。現在,我們必須爲AAT和ATA計算相應的特徵向量。
對於λ= 25,我們有:
可以將其簡化爲:
該矩陣中的單位長度向量爲:
同樣,λ= 9我們有:
我們可以將行簡化爲
該矩陣中的單位長度向量爲:
該矩陣的內核中的單位長度向量爲:
同樣,對於λ= 9,我們有:
可以將其減少爲:
該矩陣的內核中的單位長度向量爲:
對於最後一個特徵向量,我們可以找到一個垂直於q1和q2的單位向量。所以,
Σ 2X3矩陣是矩陣特徵值的平方根AAT或 ATA,即,25和9。
最後,我們可以通過公式σpi= Aqi或pi = 1 /σ(Aqi)來計算P 2X2。給出:
因此,A矩陣的分解形式爲:
由於我們擁有P和Q矩陣,因此我們可以使用梯度下降方法來獲得它們的優化版本。讓我們使用矩陣分解來構建推薦引擎。
7.使用矩陣分解構建推薦引擎
我們定義一個函數來預測用戶對所有未由他/她評分的電影的評分。
class MF():
# 初始化用戶電影評級矩陣, no.潛在的特徵,α和β。
def __init__(self, R, K, alpha, beta, iterations):
self.R = R
self.num_users, self.num_items = R.shape
self.K = K
self.alpha = alpha
self.beta = beta
self.iterations = iterations
#初始化用戶特徵和電影矩陣
def train(self):
self.P = np.random.normal(scale=1./self.K, size=(self.num_users, self.K))
self.Q = np.random.normal(scale=1./self.K, size=(self.num_items, self.K))
#初始化偏差項
self.b_u = np.zeros(self.num_users)
self.b_i = np.zeros(self.num_items)
self.b = np.mean(self.R[np.where(self.R != 0)])
#訓練樣本名單
self.samples = [
(i, j, self.R[i, j])
for i in range(self.num_users)
for j in range(self.num_items)
if self.R[i, j] > 0
]
#給定迭代次數的隨機梯度下降
training_process = []
for i in range(self.iterations):
np.random.shuffle(self.samples)
self.sgd()
mse = self.mse()
training_process.append((i, mse))
if (i+1) % 20 == 0:
print("Iteration: %d ; error = %.4f" % (i+1, mse))
return training_process
# 計算總平均平方誤差
def mse(self):
xs, ys = self.R.nonzero()
predicted = self.full_matrix()
error = 0
for x, y in zip(xs, ys):
error += pow(self.R[x, y] - predicted[x, y], 2)
return np.sqrt(error)
# 隨機梯度下降得到優化的P和Q矩陣
def sgd(self):
for i, j, r in self.samples:
prediction = self.get_rating(i, j)
e = (r - prediction)
self.b_u[i] += self.alpha * (e - self.beta * self.b_u[i])
self.b_i[j] += self.alpha * (e - self.beta * self.b_i[j])
self.P[i, :] += self.alpha * (e * self.Q[j, :] - self.beta * self.P[i,:])
self.Q[j, :] += self.alpha * (e * self.P[i, :] - self.beta * self.Q[j,:])
# 用戶 i 和 電影 j的評分
def get_rating(self, i, j):
prediction = self.b + self.b_u[i] + self.b_i[j] + self.P[i, :].dot(self.Q[j, :].T)
return prediction
# 完整的用戶電影評分矩陣
def full_matrix(self):
return mf.b + mf.b_u[:,np.newaxis] + mf.b_i[np.newaxis:,] + mf.P.dot(mf.Q.T)
現在我們有了一個可以預測評分的函數。此函數的輸入是:
- R –用戶電影評分矩陣
- K –潛在特徵數
- alpha –隨機梯度下降的學習率
- beta –偏差的正則化參數
- iterations–執行隨機梯度下降的迭代次數
我們必須將用戶項目評分轉換爲矩陣形式。可以使用python中的Pivot函數來完成。
R= np.array(ratings.pivot(index = 'user_id', columns ='movie_id', values = 'rating').fillna(0))
fillna(0)將使用0填充所有缺失的評分。現在我們有了R矩陣。我們可以初始化潛在特徵的數量,但是這些特徵的數量必須小於或等於原始特徵的數量。
現在讓我們預測所有缺失的評分。讓我們假設K = 20,alpha = 0.001,beta = 0.01和iterations = 100。
mf = MF(R, K=20, alpha=0.001, beta=0.01, iterations=100)
training_process = mf.train()
print()
print("P x Q:")
print(mf.full_matrix())
print()
這將爲我們提供與每20次迭代相對應的誤差值,最後是得到完整的用戶電影評分矩陣。輸出看起來像這樣:
我們已經創建了推薦引擎。在下一節中,我們將重點介紹如何評估推薦引擎。
8.推薦引擎的評估指標
爲了評估推薦引擎,我們可以使用以下指標
8.1召回(Recall)
- 用戶喜歡的商品中有多少是被推薦的
- 它由下式給出:
-
- 這裏tp代表推薦給用戶他/她的喜歡的數量,tp + fn代表用戶喜歡的數量總和
- 如果用戶喜歡5個項目,推薦引擎決定推薦3個項目,則召回率爲0.6
- 召回次數越大,建議就越好
8.2精度(Precision):
-
在所有推薦項目中,用戶實際喜歡的有多少?
-
它由下式給出:
-
- 這裏tp代表推薦給用戶他/她喜歡的項目數量,tp + fp代表推薦給用戶的項目總數
- 如果向用戶推薦了5個項目,而他最喜歡4個項目,則精度爲0.8
- 精度越高,建議越好
- 但是請考慮一下這種情況:如果我們僅簡單的推薦所有項目,它們肯定會涵蓋用戶喜歡的項目。因此,我們有100%的召回率!但是請考慮一下精度。如果我們建議說1000個項目,而用戶只喜歡其中的10個項目,則精度爲0.1%。這真的很低。因此,我們的目標應該是最大限度地提高準確性和召回率。
8.3 均方根誤差(RMSE):
-
它測量預測分數中的誤差:
-
- 在這裏,“Predicted”是模型預測的評分,而“Actual”是原始評分
- 如果用戶給電影評分爲5,而我們預測的評分爲4,則RMSE爲1
- RMSE值越小,建議越好
上面的指標告訴我們我們的建議有多準確,但是它們不關注建議的順序,即它們不關注首先推薦的產品以及之後推薦的產品。我們需要一些指標,也應考慮推薦產品的順序。因此,讓我們看一些排名指標:
8.4平均倒數排名(Mean Reciprocal Rank):
-
評估建議列表
-
- 假設我們向用戶推薦了3部電影,按照給定的順序爲A,B,C,但用戶只喜歡電影C。由於電影C的順序爲3,那麼順序的倒數爲1/3
- 平均倒數排名越大,建議越好
8.5 K點映射:截止k點平均精度(MAP at k )
-
Precision和Recall並不在乎建議中的順序
-
截止點k的精度是僅考慮從等級1到k級建議的子集所計算得出的精度
-
- 假設我們提出了三個建議[0,1,1]。此處0表示推薦不正確,而1表示推薦正確。那麼在k處的精度將爲[0,1/2,2/3],平均精度將爲(1/3)*(0 + 1/2 + 2/3)= 0.38
- 所以平均精度越大,建議的精度就越高
8.6歸一化折現累積增益(NDCG)
- MAP和NDCG之間的主要區別在於MAP假設某個項目是你感興趣的(或不感興趣的),而NDCG則給出了相關性得分
- 讓我們以一個例子來理解它:假設從A到J的10部電影中,我們可以推薦前五部電影,即A,B,C,D和E,而我們不能推薦其他五部電影,即F, G,H,I和J。推薦爲[A,B,C,D]。因此,在這種情況下,NDCG將爲1,因爲推薦產品與用戶相關
- NDCG值越高,建議越好
9.我們還有什麼可以嘗試的?
到目前爲止,我們已經瞭解了什麼是推薦引擎,它的不同類型及其工作方式。基於內容的過濾和基於物品的過濾算法都有其優點和缺點。
在某些領域,生成有用的內容描述可能非常困難。如果用戶的先前行爲沒有爲此提供相關證據,則基於內容的過濾模型將不會選擇項目。必須使用其他技術,以便系統可以在用戶已經表現出興趣的範圍之外提出建議。
基於物品的過濾模型沒有這些缺點。因爲不需要描述所建議的項目,所以系統可以處理任何類型的信息。此外,它可以推薦用戶以前不感興趣的產品。但是,如果沒有基於用戶評分的預測,則基於物品的過濾無法爲新項目提供建議。即使用戶開始對該商品進行評分,該商品也需要花費一些時間才能獲得足夠的評分,以便做出準確的推薦。
結合了基於內容的過濾和基於物品的過濾的系統可能會從內容的表示形式以及用戶之間的相似性中受益。結合基於物品的協作過濾和基於內容的過濾的一種方法是基於基於內容的推薦和基於物品的推薦的加權平均值進行預測。這樣做的各種方法是:
-
合併項目分數
- 在這種方法中,我們結合了從兩種過濾方法獲得的評級。最簡單的方法是取評分的平均值
- 假設一種方法建議電影的評分爲4,而另一種方法建議同一電影的評分爲5。因此最終的建議將是娶兩個分數的平均值,即4.5
- 我們也可以爲不同的方法分配不同的權重
-
組合物品等級:
- 假設基於物品的協同過濾推薦了5部電影A,B,C,D和E按以下順序進行推薦:A,B,C,D,E,而基於內容的過濾按以下順序推薦了它們:B,D,A,C,E
- 那麼電影的推薦排名爲:
基於物品的協同過濾
電影 | 排名 |
---|---|
A | 1 |
B | 0.8 |
C | 0.6 |
D | 0.4 |
E | 0.2 |
基於內容的過濾:
電影 | 排名 |
---|---|
B | 1 |
D | 0.8 |
A | 0.6 |
C | 0.4 |
E | 0.2 |
因此,混合推薦引擎將合併這些排名,並根據合併後的排名做出最終推薦。合併排名爲:
電影 | 新排名 |
---|---|
A | 1 + 0.6 = 1.6 |
B | 0.8 + 1 = 1.8 |
C | 0.6 + 0.4 = 1 |
D | 0.4 + 0.8 = 1.2 |
E | 0.2 + 0.2 = 0.4 |
推薦將根據這些排名進行。因此,最終建議將如下所示:B,A,D,C,E。
通過這種方式,可以將兩種或更多種技術組合起來以構建混合推薦引擎並提高它們的總體推薦準確性和能力。
結束語
這是一篇有關推薦引擎的非常全面的文章。本教程應該足夠好,可以幫助你開始學習推薦引擎這個主題。我們不僅介紹了基本的推薦技術,還介紹瞭如何實施當今行業中可用的一些更先進的技術。
我們還介紹了與每種技術相關的一些關鍵事實。作爲想學習如何創建推薦引擎的人,我建議你學習本教程中討論的技術,然後在模型中實現它們。
原文鏈接:https://www.analyticsvidhya.com/blog/2018/06/comprehensive-guide-recommendation-engine-python/?utm_source=blog&utm_medium=comprehensive-guide-k-means-cluster