在協同過濾推薦演算法總結中,我們講到了用矩陣分解做協同過濾是廣泛使用的方法,這裡就對矩陣分解在協同過濾推薦演算法中的應用做一個總結。(過年前最後一篇!祝大家新年快樂!明年的目標是寫120篇機器學習,深度學習和NLP相關的文章)
1. 矩陣分解用於推薦演算法要解決的問題
在推薦系統中,我們常常遇到的問題是這樣的,我們有很多使用者和物品,也有少部分使用者對少部分物品的評分,我們希望預測目標使用者對其他未評分物品的評分,進而將評分高的物品推薦給目標使用者。比如下面的使用者物品評分表:
使用者\物品 | 物品1 | 物品2 | 物品3 | 物品4 | 物品5 | 物品6 | 物品7 |
使用者1 | 3 | 5 | 1 | ||||
使用者2 | 2 | 4 | |||||
使用者3 | 4 | ||||||
使用者4 | 2 | 1 | |||||
使用者5 | 1 | 4 |
對於每個使用者,我們希望較準確的預測出使用者對未評分物品的評分。對於這個問題我們有很多解決方法,本文我們關注於用矩陣分解的方法來做。如果將m個使用者和n個物品對應的評分看做一個矩陣$M$,我們希望通過矩陣分解來解決這個問題。
2. 傳統的奇異值分解SVD用於推薦
說道矩陣分解,我們首先想到的就是奇異值分解SVD。在奇異值分解(SVD)原理與在降維中的應用中,我們對SVD原理做了總結。如果大家對SVD不熟悉的話,可以翻看該文。
此時可以將這個使用者物品對應的$m \times n$矩陣$M$進行SVD分解,並通過選擇部分較大的一些奇異值來同時進行降維,也就是說矩陣$M$此時分解為:$$M_{m \times n}=U_{m \times k}\Sigma_{k \times k}V_{k \times n}^T $$
其中k是矩陣$M$中較大的部分奇異值的個數,一般會遠遠的小於使用者數和物品樹。如果我們要預測第i個使用者對第j個物品的評分$m_{ij}$,則只需要計算$u_i^T\Sigma v_j$即可。通過這種方法,我們可以將評分表裡面所有沒有評分的位置得到一個預測評分。通過找到最高的若干個評分對應的物品推薦給使用者。
可以看出這種方法簡單直接,似乎很有吸引力。但是有一個很大的問題我們忽略了,就是SVD分解要求矩陣是稠密的,也就是說矩陣的所有位置不能有空白。有空白時我們的$M$是沒法直接去SVD分解的。大家會說,如果這個矩陣是稠密的,那不就是說我們都已經找到所有使用者物品的評分了嘛,那還要SVD幹嘛! 的確,這是一個問題,傳統SVD採用的方法是對評分矩陣中的缺失值進行簡單的補全,比如用全域性平均值或者用使用者物品平均值補全,得到補全後的矩陣。接著可以用SVD分解並降維。
雖然有了上面的補全策略,我們的傳統SVD在推薦演算法上還是較難使用。因為我們的使用者數和物品一般都是超級大,隨便就成千上萬了。這麼大一個矩陣做SVD分解是非常耗時的。那麼有沒有簡化版的矩陣分解可以用呢?我們下面來看看實際可以用於推薦系統的矩陣分解。
3. FunkSVD演算法用於推薦
FunkSVD是在傳統SVD面臨計算效率問題時提出來的,既然將一個矩陣做SVD分解成3個矩陣很耗時,同時還面臨稀疏的問題,那麼我們能不能避開稀疏問題,同時只分解成兩個矩陣呢?也就是說,現在期望我們的矩陣$M$這樣進行分解:$$M_{m \times n}=P_{m \times k}^TQ_{k \times n}$$
我們知道SVD分解已經很成熟了,但是FunkSVD如何將矩陣$M$分解為$P$和$Q$呢?這裡採用了線性迴歸的思想。我們的目標是讓使用者的評分和用矩陣乘積得到的評分殘差儘可能的小,也就是說,可以用均方差作為損失函式,來尋找最終的$P$和$Q$。
對於某一個使用者評分$m_{ij}$,如果用FunkSVD進行矩陣分解,則對應的表示為$q_j^Tp_i$,採用均方差做為損失函式,則我們期望$(m_{ij}-q_j^Tp_i)^2$儘可能的小,如果考慮所有的物品和樣本的組合,則我們期望最小化下式:$$\sum\limits_{i,j}(m_{ij}-q_j^Tp_i)^2$$
只要我們能夠最小化上面的式子,並求出極值所對應的$p_i, q_j$,則我們最終可以得到矩陣$P$和$Q$,那麼對於任意矩陣$M$任意一個空白評分的位置,我們可以通過$q_j^Tp_i$計算預測評分。很漂亮的方法!
當然,在實際應用中,我們為了防止過擬合,會加入一個L2的正則化項,因此正式的FunkSVD的優化目標函式$J(p,q)$是這樣的:$$\underbrace{arg\;min}_{p_i,q_j}\;\sum\limits_{i,j}(m_{ij}-q_j^Tp_i)^2 + \lambda(||p_i||_2^2 + ||q_j||_2^2 ) $$
其中$\lambda$為正則化係數,需要調參。對於這個優化問題,我們一般通過梯度下降法來進行優化得到結果。
將上式分別對$p_i, q_j$求導我們得到:$$\frac{\partial J}{\partial p_i} = -2(m_{ij}-q_j^Tp_i)q_j + 2\lambda p_i$$$$\frac{\partial J}{\partial q_j} = -2(m_{ij}-q_j^Tp_i)p_i + 2\lambda q_j$$
則在梯度下降法迭代時,$p_i, q_j$的迭代公式為: $$p_i = p_i + \alpha((m_{ij}-q_j^Tp_i)q_j - \lambda p_i)$$$$q_j =q_j + \alpha((m_{ij}-q_j^Tp_i)p_i - \lambda q_j)$$
通過迭代我們最終可以得到$P$和$Q$,進而用於推薦。FunkSVD演算法雖然思想很簡單,但是在實際應用中效果非常好,這真是驗證了大道至簡。
4. BiasSVD演算法用於推薦
在FunkSVD演算法火爆之後,出現了很多FunkSVD的改進版演算法。其中BiasSVD算是改進的比較成功的一種演算法。BiasSVD假設評分系統包括三部分的偏置因素:一些和使用者物品無關的評分因素,使用者有一些和物品無關的評分因素,稱為使用者偏置項。而物品也有一些和使用者無關的評分因素,稱為物品偏置項。這其實很好理解。比如一個垃圾山寨貨評分不可能高,自帶這種爛屬性的物品由於這個因素會直接導致使用者評分低,與使用者無關。
假設評分系統平均分為$\mu$,第i個使用者的使用者偏置項為$b_i$,而第j個物品的物品偏置項為$b_j$,則加入了偏置項以後的優化目標函式$J(p,q)$是這樣的$$\underbrace{arg\;min}_{p_i,q_j}\;\sum\limits_{i,j}(m_{ij}-\mu-b_i-b_j-q_j^Tp_i)^2 + \lambda(||p_i||_2^2 + ||q_j||_2^2 + ||b_i||_2^2 + ||b_j||_2^2) $$
這個優化目標也可以採用梯度下降法求解。和FunkSVD不同的是,此時我們多了兩個偏執項$b_i,b_j$,,$p_i, q_j$的迭代公式和FunkSVD類似,只是每一步的梯度導數稍有不同而已,這裡就不給出了。而$b_i,b_j$一般可以初始設定為0,然後參與迭代。這裡給出$b_i,b_j$的迭代方法$$b_i = b_i + \alpha(m_{ij}-\mu-b_i-b_j-q_j^Tp_i -\lambda b_i)$$$$b_j = b_j + \alpha(m_{ij}-\mu-b_i-b_j-q_j^Tp_i -\lambda b_j)$$
通過迭代我們最終可以得到$P$和$Q$,進而用於推薦。BiasSVD增加了一些額外因素的考慮,因此在某些場景會比FunkSVD表現好。
5. SVD++演算法用於推薦
SVD++演算法在BiasSVD演算法上進一步做了增強,這裡它增加考慮使用者的隱式反饋。好吧,一個簡單漂亮的FunkSVD硬是被越改越複雜。
對於某一個使用者i,它提供了隱式反饋的物品集合定義為$N(i)$, 這個使用者對某個物品j對應的隱式反饋修正的評分值為$c_{ij}$, 那麼該使用者所有的評分修正值為$\sum\limits_{s \in N(i)}c_{sj}$。一般我們將它表示為用$q_j^Ty_s$形式,則加入了隱式反饋項以後的優化目標函式$J(p,q)$是這樣的:$$\underbrace{arg\;min}_{p_i,q_j}\;\sum\limits_{i,j}(m_{ij}-\mu-b_i-b_j-q_j^Tp_i - q_j^T|N(i)|^{-1/2}\sum\limits_{s \in N(i)}y_{s})^2+ \lambda(||p_i||_2^2 + ||q_j||_2^2 + ||b_i||_2^2 + ||b_j||_2^2 + \sum\limits_{s \in N(i)}||y_{s}||_2^2) $$
其中,引入$|N(i)|^{-1/2}$是為了消除不同|N(i)|個數引起的差異。式子夠長的,不過需要考慮使用者的隱式反饋時,使用SVD++還是不錯的選擇。
6. 矩陣分解推薦方法小結
FunkSVD將矩陣分解用於推薦方法推到了新的高度,在實際應用中使用也是非常廣泛。當然矩陣分解方法也在不停的進步,目前張量分解和分解機方法是矩陣分解推薦方法今後的一個趨勢。
對於矩陣分解用於推薦方法本身來說,它容易程式設計實現,實現複雜度低,預測效果也好,同時還能保持擴充套件性。這些都是它寶貴的優點。當然,矩陣分解方法有時候解釋性還是沒有基於概率的邏輯迴歸之類的推薦演算法好,不過這也不影響它的流形程度。小的推薦系統用矩陣分解應該是一個不錯的選擇。大型的話,則矩陣分解比起現在的深度學習的一些方法不佔優勢。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com)