根據(一)所描述的model-based 方法, 在實際大規模數據建模中也用因子分解來近似原先的評分矩陣R。而本篇文章所要介紹的即是交替最小二乘法(Alternating Least Squares),經過評分矩陣R,user-item 找到近似的k維矩陣S(上文提到的) ,最終R(m×n)能夠用兩個矩陣來表示U(m×k),I(k×n),這樣子,對於R(i,j)的值能夠用U(i,:).*I(:,j)來近似 ,即U中i行 與 I中的j列 點乘的和 , 雖然評分矩陣R是稀疏的,可是他的兩個因子矩陣倒是稠密的,U稱爲用戶因子矩陣,I稱爲物品因子矩陣,U和I 矩陣難以直接解釋其中隱含的特徵。 算法
而後介紹ALS算法, 即求出U 和 I (相應的爲P和Q ) , 用平方損失函數求最小值,其中λ旁邊的爲L2 正則項app
能夠看到咱們要求的P 和 Q 都是未知的,是個非凸優化問題,不容易找到全局最優解,而ALS算法用的技巧就是先固定一個變量P,而後求另外一個Q,接着固定Q,再求解P,這樣子就變成一個凸優化問題,這樣不斷重複上面過程,直到收斂,就求解出P 和 Q 了,迭代公式由 2008年的一篇論文給出ide
其中npi 表示 用戶i評分過的物品數,nqj就表示物品j被多少用戶評分過。函數
具體實現優化
for epoch in range(n_epochs): # Fix Q and estimate P for i, Ii in enumerate(I): nui = np.count_nonzero(Ii) # Number of items user i has rated if (nui == 0): nui = 1 # Be aware of zero counts! # Least squares solution Ai = np.dot(Q, np.dot(np.diag(Ii), Q.T)) + lmbda * nui * E Vi = np.dot(Q, np.dot(np.diag(Ii), R[i].T)) P[:,i] = np.linalg.solve(Ai,Vi) # Fix P and estimate Q for j, Ij in enumerate(I.T): nmj = np.count_nonzero(Ij) # Number of users that rated item j if (nmj == 0): nmj = 1 # Be aware of zero counts! # Least squares solution Aj = np.dot(P, np.dot(np.diag(Ij), P.T)) + lmbda * nmj * E Vj = np.dot(P, np.dot(np.diag(Ij), R[:,j])) Q[:,j] = np.linalg.solve(Aj,Vj)