基于協同過濾算法的推薦系統

推薦系統有著廣泛的應用,電影推薦,商品推薦等都用到推薦系統。本文介紹協同過濾算法的基本原理,進而理解推薦系統的實現原理。

推薦系統的描述

我們以電影推薦系統來看一下怎么樣以機器學習的角度來描述推薦系統。我們記 $n_u$ 為用戶的數量,$n_m$ 為電影的數量,$r(i,j) = 1$ 表示用戶 j 對電影 i 進行過了評價,$y^{(i,j)}$ 就是它的分數。$r(i,j) = 0$ 表示用戶還沒觀看過這個電影,也沒評分過。我們假設用戶看過電影后,一定會給電影一個評分,如果沒有給,默認評分為零。這樣,我們的電影推薦系統的任務,就是根據用戶的評分,預測出那些用戶還未觀看的電影的評分,從而把那些用戶可能會給出較高評分的電影推薦給用戶。

基于內容的推薦算法

我們依然以電影推薦系統為例,我們假設 $\theta^{(j)}$ 表示用戶 j 的參數,$x^{(i)}$ 為電影 i 的特征向量 (比如愛情電影,動作電影,好吧,如你所愿,可能還有愛情動作片)。這樣,用戶 j 對電影 i 的預測評分為 $(\theta{(j)})T (x^{(i)})$。

接下來的目標,是怎么樣獲得用戶 j 的參數 $\theta^{(j)}$?這個實際上是個線性回歸問題,即我們利用用戶對現有電影的所有的評分學習出其參數 $\theta{(j)}$。根據線性回歸算法的成本公式,我們的目標是求解線性回歸算法的成本函數的最小值時,$\theta{(j)}$ 的值。假設 $m^{(j)}$ 是用戶 j 評價過的電影的總數。n 為電影的特征數。

用戶 j 的成本函數

這里的 $\theta^{(j)} \in R^{n+1}$。累加器部分是指用戶所有己評分的電影進行累加。

求解 $\theta^{(j)}$ 的過程就是最小化成本函數的過程。在數學上,我們可以稍微改造一下,得到基于內容的推薦算法的目標函數

求解用戶 j 的參數 $\theta^{(j)}$

求下面這個成本函數的最小值,就得到了用戶 j 的參數 $\theta^{(j)}$

用戶 j 的成本函數

求解所有用戶的參數 $\theta^{(1)}, \theta^{(2)}, ... , \theta^{(n_u)}$

疊加所有的用戶,求下面成本函數的最小值,就得到了所有用戶的參數。

疊加所有用戶的成本函數

根據線性回歸算法介紹過的內容,針對針對 $k=0$,我們不取正則項。則其參數迭代公式為:

參數迭代公式1

根據線性回歸算法介紹過的內容,針對 $k \ne 0$,包含正則項的迭代公式。其參數迭代公式為:

參數迭代公式2

其中 $\alpha$ 是學習率。

協同過濾算法 (Collaborative Filtering)

基于內容的推薦算法需要對推薦對象提取特征,構成特征向量。我們還是拿電影推薦系統為例,需要對電影進行特征提取,如愛情片,動作片,然后對所有的電影進行特征采集,即針對每個電影寫出其愛情成分是多少分,動作成分是多少分。這在工程上工作量非常大。

換一個方法,我們可以在用戶注冊的時候,讓用戶告訴我們他的偏好,比如用戶喜歡哪些類型的電影。即我們通過調查問卷,事先知道了用戶 j 的參數 $\theta^{(j)}$。再根據用戶的對看過的電影的評分數據,去推斷出電影屬于哪種類型,即電影的特征向量 $x^{(i)}$。針對用戶 j 沒有看過的電影 i ,根據 $(\theta{(j)})T (x^{(i)})$ 預測出用戶可能的評分,根據預測出來的評分高低,去決定是否向用戶推薦這部電影。

怎么樣從數學上描述這個過程呢?

計算電影 i 的特征向量 $x^{(i)}$

選取合適的 $x^{(i)}$ ,以便讓下面的公式值最小。這是求解電影 i 的特征向量 $x^{(i)}$ 的過程。

求解電影 i 的特征的成本函數

求解所有電影的特征 $x^{(1)}, x^{(2)}, ... , x^{(n_m)}$

選取合適的 $x^{(1)}, x^{(2)}, ... , x^{(n_m)}$ ,以便讓下面的公式值最小。

求解所有電影的特征的成本函數

協同過濾算法

實際工程應用上,事先知道用戶 j 的參數 $\theta^{(j)}$ 也是件很難的事。我們從之前的內容知道,有了所有的用戶參數 $\theta^{(j)}$,我們就可以估算出電影的特征向量 $x^{(i)}$。或者如果有了電影的特征向量 $x^{(i)}$,我們可以算出用戶的偏好參數 $\theta^{(j)}$。這看起來象是個雞生蛋和蛋生雞的問題。

實際上,協同過濾算法就是為了解決這個問題的。

  1. 先隨機估算出用戶參數 $\theta^{(j)}$
  2. 利用估算出來的 $\theta^{(j)}$ 和用戶看過的電影的評分數據,估算出特征向量 $x^{(i)}$
  3. 利用估算出來的特征向量 $x^{(i)}$,反向估算出用戶偏好參數 $\theta^{(j)}$
  4. 重復步驟 2 ,直到用戶參數 $\theta^{(j)}$ 和特征向量 $x^{(i)}$ 收斂到一個合適的值

這就是協同過濾算法的核心步驟。協同過濾的一個重要的效應是,當用戶對某個電影進行評分時,會幫助算法學習電影的特征,這有利于系統向所有用戶推薦合適的電影,同時也讓算法更好地學習到用戶的偏好。這樣所有用戶不停地使用系統的過程中,無形中在協同過濾,幫助系統學習出更好的參數,從而更準確地推薦出用戶喜歡的電影。

協同過濾算法的實現

上一節描述的協同過濾算法需要不停地計算 $\theta^{(j)}$ 和 $x^{(i)}$,這樣算法的效率實際上是比較低的。從數學角度,一個更高效的算法是把計算 $\theta^{(j)}$ 和 $x^{(i)}$ 的兩個成本函數合并起來,得到以 $\theta^{(j)}$ 和 $x^{(i)}$ 為參數的總成本函數,最小化這個成本函數,就可以同時求出 $\theta^{(j)}$ 和 $x^{(i)}$ 的值。

總成本函數為:

總成本函數

累加器 $\sum_{(i,j):r(i,j)=1}$ 表示針對每個用戶評價過的所有的電影進行累加。后兩項分別是 $\theta^{(j)}$ 的正則項和 $x^{(i)}$ 的正則項。需要注意的是,總成本函數里 $\theta^{(j)}$ 和 $x^{(i)}$ 都是 n 維向量,即不包含偏置向量 $x_0$。

這樣我們可以更新協同過濾算法的實現步驟:

  • 用較小的隨機數來初始化 $x^{(1)}, x^{(2)}m, ... ,x^{(n_m)}, \theta^{(1)}, \theta^{(2)}, ... , \theta^{(n_u)}$。為什么要用較小的隨機數來初始化,而不全用零呢?這是因為我們需要讓這些變量具有不同的初始值,以便不會讓兩個變量變成同一個特征。
  • 最小化成本函數 $J(x^{(1)}, x^{(2)}m, ... ,x^{(n_m)}, \theta^{(1)}, \theta^{(2)}, ... , \theta^{(n_u)})$ ,可以使用梯度下降或其他的優化過的高級算法。其參數迭代公式為
參數迭代公式
  • 學習出參數后,針對一個用戶 j 的參數為 $\theta^{(j)}$ ,針對這個用戶沒有看過的電影,學習到的特征為 $x^{(i)}$,那么可以預測到這個用戶對這個電影的評分將是 $(\theta{(j)})T x^{(i)}$。

需要特別注意的是,此處我們沒有加偏置變量 $x_0$,也不存在 $\theta_0$。

協同過濾算法的向量化實現

低秩矩陣分解 (Low Rank Matrix Factorization)

使用協同過濾算法算出所有用戶的參數 $\theta^{(j)}$ 和所有電影的特征 $x^{(i)}$ 之后,我們可以針對某個用戶 j 對電影 i 的評分做出預測,預測公式為 $(\theta{(j)})T x^{(i)}$ 。如果我們想要一次性計算所有用戶對所有電影的評分,我們可以寫成下面的矩陣:

預測所有用戶的評分的矩陣

這是個 $n_m \times n_u$ 的矩陣,其中 $n_m$ 是電影個數,$n_u$ 是用戶數。我們把所有的電影特征 $x^{(i)}$ 寫成一個 $n_m \times n$ 的矩陣,其中 n 是電影的特征個數。

電影特征矩陣

再把所有的用戶參數 $\theta^{(j)}$ 寫成一個 $n_u \times n$ 的矩陣:

用戶參數矩陣

利用矩陣相乘的法則,公式 $Y = X \Theta^T$ 就可以一次性算出所有用戶對所有電影的評分。其中 $X \in R^{n_m \times n}, \Theta^T \in R^{n \times n_u}$,其內積 $Y \in R^{n_m \times n_u}$。

計算量問題

針對大型的電影網站,電影數量是非常龐大的,用戶量可能更龐大。對這樣一個大的矩陣進行運算,其計算量將大的驚人的。從協同過濾算法的核心原則來看,系統需要經常計算這個矩陣,最壞的情況是每當有用戶對一個新電影進行評分時就需要計算一次。詳細討論這個問題已經超出本文的范圍,但可以簡單談一些策略:

  • 選擇合適的計算周期
    我們不一定在每次用戶提交一個新的電影評分數據時就計算,而是一天甚至幾天計算一次。這樣的結果就是,只要數據庫的讀寫分離做得好,即使我們用很有限的硬件資源,也可以完成預期的計算目標。因為我們的計算時效性要求不強,每次計算完,更新參數后,我們的推薦系統就變得更準確一點了。
  • 使用分布式計算
  • 使用量子計算機
    量子計算機的運算速度上比目前的計算機要提高 N 個數量級。

推薦相似的電影

我們還是以電影為例,假設我們已經通過協同過濾算法學習到了所有的電影特征 $x^{(i)}$。假設這個時候用戶在瀏覽電影 i ,我們要推薦 5 部相似的電影給用戶。怎么樣找到這 5 部相似的電影呢?

我們可以遍歷所有的電影,通過公式 $| x^{(i)} - x^{(k)} |$ 找出和正在瀏覽的電影“距離最小”,即相似度最高的 5 部電影。

均值歸一化 Mean Normalization

假設現在有個新用戶 j 沒有對任何電影進行打分。那么根據協同過濾算法的成本函數:

成本函數

第一部分將為 0 ,因為對用戶 j ,沒有 $r(i,j)=1$ 的項。第二部分將為一個固定值,因為已經學習好了電影的特征,所以 $x_k^{(i)}$ 將是常量,所以針對新用戶 j 問題將簡化為最小化 $\frac{\lambda}{2} \sum_{j=1}^{n_u} \sum_{k=1}^n (\theta_k{(j)})2$ ,這個計算結果將使 $\theta^{(j)}$ 為全 0 。

這樣的話,這個用戶對所有電影的評分將預測為 0 ,我們也就沒有什么他喜歡的電影推薦給他了。

怎么樣解決這個問題呢?

簡單地講,如果一個新用戶沒有評分過任何電影,我們可以預測這個用戶對新電影的評分為這個電影的評分的平均值。用數學的語言來描述就是,我們需要先對電影評分數據進行均值歸一處理。

假設我們有所有的電影評分矩陣 $Y \in R^{n_m \times n_u}$,對其按行求平均值,得到 $\mu \in R^{n_m}$。然后我們計算 $Y - \mu$ 作為我們協同過濾算法的訓練數據集。這樣訓練出來 $\theta^{(j)}$ 和 $x^{(i)}$ 之后,針對新用戶 j 對電影 i 的預測評分公式將變成 $(\theta{(j)})T x^{(i)} + \mu_i$。

還有一種情況是如果有一部新的電影,所有人都沒有評分過,那么這個電影的特征值將全為 0 。我們也可以用均值歸一法來處理,但這樣處理是否合理需要從業務層面去理解。比如一部新電影,所有人都沒看過,也沒評分過,我們就不應該推薦給任何人。從業務層面,一個新電影可能會有專門的展示區域,比如“新片速遞”。

總結

協同推薦算法就像魔術一樣,解決了雞生蛋和蛋生雞的問題,從無到有構建了用戶的偏好和電影的特征。當然,這里沒有魔術,協同過濾算法的關鍵輸入是用戶不斷提交的評分數據。用戶不斷地使用系統,使用過程中不斷地完善推薦系統。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容