基于矩阵分解的协同过滤推荐

Traditional SVD

通常SVD矩阵分解指的是SVD奇异值分解,我们姑且将其命名为Traditional SVD(传统并经典着)其公式如下:
M m × n = U m × k Σ k × k V k × n T M_{m \times n} = U_{m \times k} \Sigma_{k \times k} V^T_{k \times n} Mm×n​=Um×k​Σk×k​Vk×nT​

Traditional SVD分解的形式为3个矩阵相乘,中间矩阵为奇异值矩阵。如果想运用SVD分解的话,有一个前提是要求矩阵是稠密的,即矩阵里的元素要非空,否则就不能运用SVD分解

很显然我们的数据其实绝大多数情况下都是稀疏的,因此如果要使用Traditional SVD,一般的做法是先用均值或者其他统计学方法来填充矩阵,然后再运用Traditional SVD分解降维,但这样做明显对数据的原始性造成一定影响

FunkSVD(LFM)

刚才提到的Traditional SVD首先需要填充矩阵,然后再进行分解降维,同时存在计算复杂度高的问题,因为要分解成3个矩阵,所以后来提出了Funk SVD的方法,它不在将矩阵分解为3个矩阵,而是分解为2个用户-隐含特征,项目-隐含特征的矩阵,Funk SVD也被称为最原始的LFM模型,其公式如下:
R m × n = P m × k Q k × n R_{m \times n} = P_{m \times k} Q_{k \times n} Rm×n​=Pm×k​Qk×n​

原理解析

LFM(latent factor model)隐语义模型核心思想是通过隐含特征联系用户和物品,如下图:

  • P矩阵是User-LF矩阵,即用户和隐含特征的矩阵
  • Q矩阵是LF-Item矩阵,即隐含特征和物品的矩阵
  • R矩阵是User-Item矩阵,由P*Q得来
  • 能处理稀疏评分矩阵

利用矩阵分解技术,将原始User-Item的评分矩阵(稠密/稀疏)分解为P和Q矩阵,然后利用 P ∗ Q P*Q P∗Q还原出User-Item评分矩阵 R R R。整个过程相当于降维处理,其中:

  • 矩阵值 P 11 P_{11} P11​表示用户1对隐含特征1的权重值
  • 矩阵值 Q 11 Q_{11} Q11​表示隐含特征1在物品1上的权重值
  • 矩阵值 R 11 R_{11} R11​就表示预测的用户1对物品1的评分, R 11 = P 1 , k ⃗ ⋅ Q k , 1 ⃗ R_{11}=\vec{P_{1,k}}\cdot \vec{Q_{k,1}} R11​=P1,k​ ​⋅Qk,1​ ​

利用LFM预测用户对物品的评分, k k k表示隐含特征数量: r ^ u i = p u k ⃗ ⋅ q i k ⃗ = ∑ k = 1 k p u k q i k \begin{split} \hat {r}_{ui} &=\vec {p_{uk}}\cdot \vec {q_{ik}} \\&={\sum_{k=1}}^k p_{uk}q_{ik} \end{split} r^ui​​=puk​ ​⋅qik​ ​=k=1∑​kpuk​qik​​

因此最终,我们的目标也就是要求出P矩阵和Q矩阵及其当中的每一个值,然后再对用户-物品的评分进行预测

损失函数

同样对于评分预测我们利用平方差来构建损失函数:
C o s t = ∑ u , i ∈ R ( r u i − r ^ u i ) 2 = ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) 2 \begin{split} Cost &= \sum_{u,i\in R} (r_{ui}-\hat{r}_{ui})^2 \\&=\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})^2 \end{split} Cost​=u,i∈R∑​(rui​−r^ui​)2=u,i∈R∑​(rui​−k=1∑​kpuk​qik​)2​
加入L2正则化:
C o s t = ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U p u k 2 + ∑ I q i k 2 ) Cost = \sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2) Cost=u,i∈R∑​(rui​−k=1∑​kpuk​qik​)2+λ(U∑​puk​2+I∑​qik​2)
对损失函数求偏导:
∂ ∂ p u k C o s t = ∂ ∂ p u k [ ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) ( − q i k ) + 2 λ p u k ∂ ∂ q i k C o s t = ∂ ∂ q i k [ ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) ( − p u k ) + 2 λ q i k \begin{split} \cfrac {\partial}{\partial p_{uk}}Cost &= \cfrac {\partial}{\partial p_{uk}}[\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})(-q_{ik}) + 2\lambda p_{uk} \\\\ \cfrac {\partial}{\partial q_{ik}}Cost &= \cfrac {\partial}{\partial q_{ik}}[\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})(-p_{uk}) + 2\lambda q_{ik} \end{split} ∂puk​∂​Cost∂qik​∂​Cost​=∂puk​∂​[u,i∈R∑​(rui​−k=1∑​kpuk​qik​)2+λ(U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−k=1∑​kpuk​qik​)(−qik​)+2λpuk​=∂qik​∂​[u,i∈R∑​(rui​−k=1∑​kpuk​qik​)2+λ(U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−k=1∑​kpuk​qik​)(−puk​)+2λqik​​

随机梯度下降法优化

梯度下降更新参数 p u k p_{uk} puk​:
p u k : = p u k − α ∂ ∂ p u k C o s t : = p u k − α [ 2 ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) ( − q i k ) + 2 λ p u k ] : = p u k + α [ ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) q i k − λ p u k ] \begin{split} p_{uk}&:=p_{uk} - \alpha\cfrac {\partial}{\partial p_{uk}}Cost \\&:=p_{uk}-\alpha [2\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})(-q_{ik}) + 2\lambda p_{uk}] \\&:=p_{uk}+\alpha [\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})q_{ik} - \lambda p_{uk}] \end{split} puk​​:=puk​−α∂puk​∂​Cost:=puk​−α[2u,i∈R∑​(rui​−k=1∑​kpuk​qik​)(−qik​)+2λpuk​]:=puk​+α[u,i∈R∑​(rui​−k=1∑​kpuk​qik​)qik​−λpuk​]​
同理:
q i k : = q i k + α [ ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) p u k − λ q i k ] \begin{split} q_{ik}&:=q_{ik} + \alpha[\sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})p_{uk} - \lambda q_{ik}] \end{split} qik​​:=qik​+α[u,i∈R∑​(rui​−k=1∑​kpuk​qik​)puk​−λqik​]​
随机梯度下降: 向量乘法 每一个分量相乘 求和
p u k : = p u k + α [ ( r u i − ∑ k = 1 k p u k q i k ) q i k − λ 1 p u k ] q i k : = q i k + α [ ( r u i − ∑ k = 1 k p u k q i k ) p u k − λ 2 q i k ] \begin{split} &p_{uk}:=p_{uk}+\alpha [(r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})q_{ik} - \lambda_1 p_{uk}] \\&q_{ik}:=q_{ik} + \alpha[(r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})p_{uk} - \lambda_2 q_{ik}] \end{split} ​puk​:=puk​+α[(rui​−k=1∑​kpuk​qik​)qik​−λ1​puk​]qik​:=qik​+α[(rui​−k=1∑​kpuk​qik​)puk​−λ2​qik​]​
由于P矩阵和Q矩阵是两个不同的矩阵,通常分别采取不同的正则参数,如 λ 1 \lambda_1 λ1​和 λ 2 \lambda_2 λ2​

算法实现

class LFM(object):def __init__(self, alpha, reg_p, reg_q, number_LatentFactors=10, number_epochs=10, columns=["uid", "iid", "rating"]):self.alpha = alpha    # 学习率self.reg_p = reg_p    # P矩阵正则self.reg_q = reg_q    # Q矩阵正则self.number_LatentFactors = number_LatentFactors  # 隐式类别数量self.number_epochs = number_epochs    # 最大迭代次数self.columns = columnsdef fit(self, dataset):self.dataset = pd.DataFrame(dataset)self.users_ratings = dataset.groupby(self.columns[0]).agg([list])[[self.columns[1], self.columns[2]]]self.items_ratings = dataset.groupby(self.columns[1]).agg([list])[[self.columns[0], self.columns[2]]]self.globalMean = self.dataset[self.columns[2]].mean()self.P, self.Q = self.sgd()def _init_matrix(self):# User-LFP = dict(zip(self.users_ratings.index,np.random.rand(len(self.users_ratings), self.number_LatentFactors).astype(np.float32)))# Item-LFQ = dict(zip(self.items_ratings.index,np.random.rand(len(self.items_ratings), self.number_LatentFactors).astype(np.float32)))return P, Qdef sgd(self):P, Q = self._init_matrix()for i in range(self.number_epochs):print("iter%d"%i)error_list = []for uid, iid, r_ui in self.dataset.itertuples(index=False):v_pu = P[uid]  # 用户向量v_qi = Q[iid]  # 物品向量err = np.float32(r_ui - np.dot(v_pu, v_qi))v_pu += self.alpha * (err * v_qi - self.reg_p * v_pu)v_qi += self.alpha * (err * v_pu - self.reg_q * v_qi)P[uid] = v_pu Q[iid] = v_qierror_list.append(err ** 2)print(np.sqrt(np.mean(error_list)))return P, Qdef predict(self, uid, iid):# 如果uid或iid不在,我们使用全剧平均分作为预测结果返回if uid not in self.users_ratings.index or iid not in self.items_ratings.index:return self.globalMeanp_u = self.P[uid]q_i = self.Q[iid]return np.dot(p_u, q_i)

BiasSVD

在Funk SVD提出来之后,出现了很多变形版本,其中一个相对成功的方法是BiasSVD,顾名思义,即带有偏置项的SVD分解,其实就是前面提到的Funk SVD矩阵分解基础上加上了偏置项

原理解析

利用BiasSvd预测用户对物品的评分, k k k表示隐含特征数量:
r ^ u i = μ + b u + b i + p u k ⃗ ⋅ q k i ⃗ = μ + b u + b i + ∑ k = 1 k p u k q i k \begin{split} \hat {r}_{ui} &=\mu + b_u + b_i + \vec {p_{uk}}\cdot \vec {q_{ki}} \\&=\mu + b_u + b_i + {\sum_{k=1}}^k p_{uk}q_{ik} \end{split} r^ui​​=μ+bu​+bi​+puk​ ​⋅qki​ ​=μ+bu​+bi​+k=1∑​kpuk​qik​​

损失函数

同样对于评分预测我们利用平方差来构建损失函数:
C o s t = ∑ u , i ∈ R ( r u i − r ^ u i ) 2 = ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 \begin{split} Cost &= \sum_{u,i\in R} (r_{ui}-\hat{r}_{ui})^2 \\&=\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i -{\sum_{k=1}}^k p_{uk}q_{ik})^2 \end{split} Cost​=u,i∈R∑​(rui​−r^ui​)2=u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2​
加入L2正则化:
C o s t = ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U b u 2 + ∑ I b i 2 + ∑ U p u k 2 + ∑ I q i k 2 ) Cost = \sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{b_u}^2+\sum_I{b_i}^2+\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2) Cost=u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2+λ(U∑​bu​2+I∑​bi​2+U∑​puk​2+I∑​qik​2)
对损失函数求偏导:
∂ ∂ p u k C o s t = ∂ ∂ p u k [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U b u 2 + ∑ I b i 2 + ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) ( − q i k ) + 2 λ p u k ∂ ∂ q i k C o s t = ∂ ∂ q i k [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U b u 2 + ∑ I b i 2 + ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) ( − p u k ) + 2 λ q i k \begin{split} \cfrac {\partial}{\partial p_{uk}}Cost &= \cfrac {\partial}{\partial p_{uk}}[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{b_u}^2+\sum_I{b_i}^2+\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})(-q_{ik}) + 2\lambda p_{uk} \\\\ \cfrac {\partial}{\partial q_{ik}}Cost &= \cfrac {\partial}{\partial q_{ik}}[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{b_u}^2+\sum_I{b_i}^2+\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})(-p_{uk}) + 2\lambda q_{ik} \end{split} ∂puk​∂​Cost∂qik​∂​Cost​=∂puk​∂​[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2+λ(U∑​bu​2+I∑​bi​2+U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)(−qik​)+2λpuk​=∂qik​∂​[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2+λ(U∑​bu​2+I∑​bi​2+U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)(−puk​)+2λqik​​
∂ ∂ b u C o s t = ∂ ∂ b u [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U b u 2 + ∑ I b i 2 + ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) ( − 1 ) + 2 λ b u ∂ ∂ b i C o s t = ∂ ∂ b i [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U b u 2 + ∑ I b i 2 + ∑ U p u k 2 + ∑ I q i k 2 ) ] = 2 ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) ( − 1 ) + 2 λ b i \begin{split} \cfrac {\partial}{\partial b_u}Cost &= \cfrac {\partial}{\partial b_u}[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{b_u}^2+\sum_I{b_i}^2+\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})(-1) + 2\lambda b_u \\\\ \cfrac {\partial}{\partial b_i}Cost &= \cfrac {\partial}{\partial b_i}[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{b_u}^2+\sum_I{b_i}^2+\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2)] \\&=2\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})(-1) + 2\lambda b_i \end{split} ∂bu​∂​Cost∂bi​∂​Cost​=∂bu​∂​[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2+λ(U∑​bu​2+I∑​bi​2+U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)(−1)+2λbu​=∂bi​∂​[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)2+λ(U∑​bu​2+I∑​bi​2+U∑​puk​2+I∑​qik​2)]=2u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)(−1)+2λbi​​

随机梯度下降法优化

梯度下降更新参数 p u k p_{uk} puk​:
p u k : = p u k − α ∂ ∂ p u k C o s t : = p u k − α [ 2 ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) ( − q i k ) + 2 λ p u k ] : = p u k + α [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) q i k − λ p u k ] \begin{split} p_{uk}&:=p_{uk} - \alpha\cfrac {\partial}{\partial p_{uk}}Cost \\&:=p_{uk}-\alpha [2\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})(-q_{ik}) + 2\lambda p_{uk}] \\&:=p_{uk}+\alpha [\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})q_{ik} - \lambda p_{uk}] \end{split} puk​​:=puk​−α∂puk​∂​Cost:=puk​−α[2u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)(−qik​)+2λpuk​]:=puk​+α[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)qik​−λpuk​]​
同理:
q i k : = q i k + α [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) p u k − λ q i k ] \begin{split} q_{ik}&:=q_{ik} + \alpha[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})p_{uk} - \lambda q_{ik}] \end{split} qik​​:=qik​+α[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)puk​−λqik​]​
b u : = b u + α [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) − λ b u ] b_u:=b_u + \alpha[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik}) - \lambda b_u] bu​:=bu​+α[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)−λbu​]
b i : = b i + α [ ∑ u , i ∈ R ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) − λ b i ] b_i:=b_i + \alpha[\sum_{u,i\in R} (r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik}) - \lambda b_i] bi​:=bi​+α[u,i∈R∑​(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)−λbi​]

随机梯度下降:
p u k : = p u k + α [ ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) q i k − λ 1 p u k ] q i k : = q i k + α [ ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) p u k − λ 2 q i k ] \begin{split} &p_{uk}:=p_{uk}+\alpha [(r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})q_{ik} - \lambda_1 p_{uk}] \\&q_{ik}:=q_{ik} + \alpha[(r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik})p_{uk} - \lambda_2 q_{ik}] \end{split} ​puk​:=puk​+α[(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)qik​−λ1​puk​]qik​:=qik​+α[(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)puk​−λ2​qik​]​
b u : = b u + α [ ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) − λ 3 b u ] b_u:=b_u + \alpha[(r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik}) - \lambda_3 b_u] bu​:=bu​+α[(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)−λ3​bu​]
b i : = b i + α [ ( r u i − μ − b u − b i − ∑ k = 1 k p u k q i k ) − λ 4 b i ] b_i:=b_i + \alpha[(r_{ui}-\mu - b_u - b_i-{\sum_{k=1}}^k p_{uk}q_{ik}) - \lambda_4 b_i] bi​:=bi​+α[(rui​−μ−bu​−bi​−k=1∑​kpuk​qik​)−λ4​bi​]

由于P矩阵和Q矩阵是两个不同的矩阵,通常分别采取不同的正则参数,如 λ 1 \lambda_1 λ1​和 λ 2 \lambda_2 λ2​

算法实现

class BiasSvd(object):def __init__(self, alpha, reg_p, reg_q, reg_bu, reg_bi, number_LatentFactors=10, number_epochs=10, columns=["uid", "iid", "rating"]):self.alpha = alpha self.reg_p = reg_pself.reg_q = reg_qself.reg_bu = reg_buself.reg_bi = reg_biself.number_LatentFactors = number_LatentFactors  self.number_epochs = number_epochsself.columns = columnsdef fit(self, dataset):self.dataset = pd.DataFrame(dataset)self.users_ratings = dataset.groupby(self.columns[0]).agg([list])[[self.columns[1], self.columns[2]]]self.items_ratings = dataset.groupby(self.columns[1]).agg([list])[[self.columns[0], self.columns[2]]]self.globalMean = self.dataset[self.columns[2]].mean()self.P, self.Q, self.bu, self.bi = self.sgd()def _init_matrix(self):# User-LFP = dict(zip(self.users_ratings.index,np.random.rand(len(self.users_ratings), self.number_LatentFactors).astype(np.float32)))# Item-LFQ = dict(zip(self.items_ratings.index,np.random.rand(len(self.items_ratings), self.number_LatentFactors).astype(np.float32)))return P, Qdef sgd(self):P, Q = self._init_matrix()# 初始化bu、bi的值,全部设为0bu = dict(zip(self.users_ratings.index, np.zeros(len(self.users_ratings))))bi = dict(zip(self.items_ratings.index, np.zeros(len(self.items_ratings))))for i in range(self.number_epochs):print("iter%d"%i)error_list = []for uid, iid, r_ui in self.dataset.itertuples(index=False):v_pu = P[uid]v_qi = Q[iid]err = np.float32(r_ui - self.globalMean - bu[uid] - bi[iid] - np.dot(v_pu, v_qi))v_pu += self.alpha * (err * v_qi - self.reg_p * v_pu)v_qi += self.alpha * (err * v_pu - self.reg_q * v_qi)P[uid] = v_pu Q[iid] = v_qibu[uid] += self.alpha * (err - self.reg_bu * bu[uid])bi[iid] += self.alpha * (err - self.reg_bi * bi[iid])error_list.append(err ** 2)print(np.sqrt(np.mean(error_list)))return P, Q, bu, bidef predict(self, uid, iid):if uid not in self.users_ratings.index or iid not in self.items_ratings.index:return self.globalMeanp_u = self.P[uid]q_i = self.Q[iid]return self.globalMean + self.bu[uid] + self.bi[iid] + np.dot(p_u, q_i)

SVD++

人们后来又提出了改进的BiasSVD,被称为SVD++,该算法是在BiasSVD的基础上添加了用户的隐式反馈信息

显示反馈指的用户的评分这样的行为,隐式反馈指用户的浏览记录、购买记录、收听记录等

SVD++是基于这样的假设:在BiasSVD基础上,认为用户对于项目的历史浏览记录、购买记录、收听记录等可以从侧面反映用户的偏好

基于矩阵分解的协同过滤推荐相关推荐

  1. 机器学习(37)之矩阵分解在协同过滤推荐中的应用

    微信公众号 关键字全网搜索最新排名 [机器学习算法]:排名第一 [机器学习]:排名第一 [Python]:排名第三 [算法]:排名第四 前言 在协同过滤推荐算法总结(机器学习(36)之协同过滤典型算法 ...

  2. 基于矩阵分解的协同过滤算法

    基于矩阵分解的协同过滤算法 基于矩阵分解的CF算法实现(一):LFM LFM原理解析 损失函数 随机梯度下降法优化 基于矩阵分解的CF算法实现(二):BiasSvd BiasSvd 损失函数 随机梯度 ...

  3. SVD++:推荐系统的基于矩阵分解的协同过滤算法的提高

    1.背景知识 在讲SVD++之前,我还是想先回到基于物品相似的协同过滤算法.这个算法基本思想是找出一个用户有过正反馈的物品的相似的物品来给其作为推荐.其公式为: 其中 rui 表示预测用户u对物品i的 ...

  4. 基于云模型的协同过滤推荐算法代码实现(附源代码)

    基于云模型的协同过滤推荐算法代码实现(附源代码) 一.云模型介绍 针对传统推荐系统数据稀疏.相似性计算方法导致共同评分用户少的问题,提出利用云模型概念与定量数值转换的优势,研究云模型(百度百科查看概念 ...

  5. 基于KMeans聚类的协同过滤推荐算法推荐原理、过程、代码实现 Canopy聚类算法 KMeans+Canopy聚类算法 聚类算法程序实现 KMEans聚类算法代码java

    基于KMeans聚类的协同过滤推荐算法可运用于基于用户和基于项目的协同过滤推荐算法中,作为降低数据稀疏度和提高推荐准确率的方法之一,一个协同过滤推荐过程可实现多次KMeans聚类. 一.基于KMean ...

  6. 推荐系统笔记:基于非负矩阵分解的协同过滤

    1 非负矩阵分解 非负矩阵分解 (NMF) 可用于非负的评级矩阵. 这种方法的主要优势不一定是准确性,而是它在理解用户-项目交互方面提供的高度可解释性. 与其他形式的矩阵分解的主要区别在于因子 U 和 ...

  7. 个性化试题推荐系统 协同过滤推荐算法在在线考试系统中的运用 基于用户/项目的协同过滤推荐算法 混合协同过滤推荐算法 协同过滤混合推荐算法

    个性化试题推荐系统 协同过滤推荐算法在在线考试系统中的运用 一.项目开发技术及功能介绍 1.SSH开发框架(spring+struts+hibernate) 2.js.jquery.bootstrap ...

  8. 基于音乐/电影/图书的协同过滤推荐算法代码实现(基于用户推荐、基于项目推荐、基于SlopeOne算法推荐、基于SVD算法推荐、混合加权推荐)

    基于音乐/电影/图书的协同过滤推荐算法代码实现(基于用户推荐.基于项目推荐.基于SlopeOne算法推荐.基于SVD算法推荐.加权混合推荐) 一.开发工具及使用技术 MyEclipse10.jdk1. ...

  9. 基于Mahout实现协同过滤推荐算法的电影推荐系统

    1 Mahout介绍 Apache Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更 ...

最新文章

  1. 服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼
  2. C++编程优化——让你的代码飞起来
  3. pemicro识别不了驱动_usb驱动无法识别如何解决,手把手教你如何解决usb驱动问题...
  4. sass和less的优缺点
  5. sulin Python3.6爬虫+Djiago2.0+Mysql --实例demo
  6. [HNOI2019]校园旅行
  7. 《Python程序设计》——1.2 程序开发周期
  8. WPE(Winsock Packet Editor)
  9. 小米MIX4最新渲染图曝光;苹果首款OLED iPad将于2023年问世;格力将引进鸿蒙操作系统|极客头条...
  10. [转载] python indices_Python numpy.indices() 使用实例
  11. solr6.6 solrJ索引富文本(word/pdf)文件
  12. JAVA邮件发送的授权码_java实现邮件发送
  13. Android 代码管理技巧
  14. 《Using OpenRefine》翻译~17
  15. 【笔记】运营如何追求极致--混沌大学(抖音分享)
  16. js经纬度打开腾讯地图
  17. 7039s芯片(F4plus、M3 4K、M6 4K、F5PLUS、A1-4K)开机不进主界面的解决办法
  18. 《炬丰科技-半导体工艺》 高频磷化铟芯片晶圆级背面加工
  19. 罗马音平假名中文可复制_如何快速有效地学习日语五十音?
  20. 【数据库MySQL】2021最新官网下载及查看MySQL版本步骤教程

热门文章

  1. 如何把e01挂载到系统上?
  2. 一种简单的贝塞尔插值算法
  3. 取对数的作用(机器学习的推导公式经常取对数)
  4. 自学SQL网题解(6-12课题解)
  5. windows远程登录应用
  6. 【Python实战】 ---- 爬虫 爬取LOL英雄皮肤图片
  7. 第三章:fog(恐惧感 fear,责任感obligation,罪恶感guilty)
  8. 滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(7月29日)...
  9. Win10下安转Elasticsearch6.8.6与配置安全策略-开启密码账号访问
  10. 神经网络书籍pdf微盘下载,神经网络书籍推荐知乎