您的位置:首页 > 其它

SVD分解及推荐系统的矩阵分解

2018-04-02 18:02 225 查看
问题描述

SVD矩阵分解

代替方法

梯度下降一般形式

推荐系统梯度下降求解:

算法实现

算法评估

参考

问题描述

在这里,我们将谈论的问题是评级预测问题。我们的数据是评级历史数据,即用户对项目的评级,值区间是[1,5]。我们可以把数据放在一个稀疏矩阵R

中:

R=⎛⎝⎜⎜⎜⎜⎜⎜⎜⎜1?2??5????1?2?43????5?3??4???2⎞⎠⎟⎟⎟⎟⎟⎟⎟⎟AliceBobCharlieDanielEricFrankR=(1?2??????42?45???3???1?3?5???2)AliceBobCharlieDanielEricFrank

矩阵的每一行对应一个给定用户,每一列对应一个给定项目。譬如,在上面的矩阵中,Alice对第一个项目的评级是1,Charlie对第三个项目的评级是4。在我们的问题中,我们将认为项目是电影,(电商领域是商品),在后面会交替使用“项目”和“电影”这两个术语。

SVD矩阵分解

Rm×n=Mm×mΣm×nUTn×nRm×n=Mm×mΣm×nUn×nT

降维:Rm×n=Mm×rΣr×rUTr×n降维:Rm×n=Mm×rΣr×rUr×nT

如果RR是密集的,我们可以很容易计算M和UM和U:

MM的列是RRTRRT的特征向量

The columns of MM can build back all of the columns of RR

UU的列是RTRRTR的特征向量。

The columns of UU can build back all of the rows of RR

ΣΣ的对角元素来源于RRT或RTRRRT或RTR 的特征值的平方根,并且是按从大到小的顺序排列的

但是,RR是稀疏的,矩阵RRTRRT和RTRRTR并不存在,所以它们的特征向量也不存在,而且我们不能把RR分解为MΣUTMΣUT的乘积。但是,有一些办法。曾被用过一段时间的第一个选择是,对RR的缺失内容进行填充,如,行(或列)的平均值。一旦得到密集矩阵,我们就可以用传统算法来计算其SVD。这种方法可行,但结果往往有很高的偏见。我们宁愿用另外一种方法,基于最小化问题。

代替方法

计算RRTRRT和RTRRTR的特征向量并不是计算密集矩阵RR的SVD的唯一方法。实际上,我们可以找到矩阵MM和UU,如果我们能找到所有满足如下条件的向量pupu和qiqi(pu组成M的行,qi组成UT的列pu组成M的行,qi组成UT的列):

⎛⎝⎜rui⎞⎠⎟=⎛⎝⎜pu⎞⎠⎟⎛⎝⎜⎜⎜⎜qi⎞⎠⎟⎟⎟⎟(rui)=(pu)(qi)

由于定义矩阵乘法的定义方式,rui的值是两个向量的点积的结果:向量pupu,它是MM的一行,特定于用户uu;向量qiqi,它是UTUT的列,特定于项目ii

对所有的u和i,rui=pu⋅qirui=pu⋅qi

所有的向量pupu是相互正交的,所有的向量qiqi也如此。

对所有users和items,找出这种向量pu和qipu和qi,可通过解决下面的优化问题(同时遵循正交约束)来完成:

minpu,qipu⊥pvqi⊥qj∑rui∈R(rui−pu⋅qi)2minpu,qipu⊥pvqi⊥qj∑rui∈R(rui−pu⋅qi)2

它可被理解为,找到向量pupu和qiqi使得与ruirui差总和最小。也就是说,我们试图尽可能将ruirui的值与pu⋅qipu⋅qi相等。

那么当R稀疏时,即当矩阵中某些评级缺失时,我们该怎么办? Simon Funk的答案是我们应该不要废弃。我们仍然解决同样的优化问题:

minpu,qi∑rui∈R(rui−pu⋅qi)2.minpu,qi∑rui∈R(rui−pu⋅qi)2.

唯一的区别是,这次,某些评级是缺失的,即RR不完整。请注意,我们并没有将缺少的项目视为零:我们纯粹是忽略它们。此外,我们将会忘记正交性约束,因为即使它们对于解释有用,通常,限制向量也不能帮助我们获得更准确的预测。

梯度下降一般形式

当带参数θθ的函数ff被表示如下时:

f(θ)=∑kfk(θ),f(θ)=∑kfk(θ),

SGD过程通过下列步骤来最小化ff(即,找到θθ使得f(θ)f(θ)尽可能小):

随机初始化θθ

对于给定的次数,重复下面的步骤:

对于所有kk,重复以下步骤:

计算∂fk∂θ∂fk∂θ

更新θ←θ−α⋅∂fk∂θθ←θ−α⋅∂fk∂θ,其中αα是学习速率(一个很小的值)。

推荐系统梯度下降求解:

在我们的情况下,参数θθ对应于所有的向量pupu和qiqi(我们将其表示为(p∗,q∗p∗,q∗)),而我们想最小化的函数ff表示为

f(p∗,q∗)=∑rui∈R(rui−pu⋅qi)2=∑rui∈Rfui(pu,qi),f(p∗,q∗)=∑rui∈R(rui−pu⋅qi)2=∑rui∈Rfui(pu,qi),

其中fuifui被定义为:fui(pu,qi)=(rui−pu⋅qi)2fui(pu,qi)=(rui−pu⋅qi)2

向量pupu关于函数fuifui的偏导为:

∂fui∂pu=∂∂pu(rui−pu⋅qi)2=−2qi(rui−pu⋅qi)∂fui∂pu=∂∂pu(rui−pu⋅qi)2=−2qi(rui−pu⋅qi)

向量qiqi关于函数fuifui的偏导为:

∂fui∂qi=∂∂qi(rui−pu⋅qi)2=−2pu(rui−pu⋅qi)∂fui∂qi=∂∂qi(rui−pu⋅qi)2=−2pu(rui−pu⋅qi)

算法实现

求解步骤如下:

随机初始化所有的向量pupu和qiqi。

对给定的次数(如,迭代数),重复下面的步骤:

对所有已知的评级ruirui,重复下面的步骤:

计算∂fui∂pu∂fui∂pu和∂fui∂qi∂fui∂qi

更新pu和qipu和qi:pu←pu+α⋅qi(rui−pu⋅qi)pu←pu+α⋅qi(rui−pu⋅qi),qi←qi+α⋅pu(rui−pu⋅qi)qi←qi+α⋅pu(rui−pu⋅qi)

核心代码:

def SGD(data):
'''Learn the vectors p_u and q_i with SGD.
data is a dataset containing all ratings + some useful info (e.g. number
of items/users).
u i r_ui
0 0 4.0     #更新p的第0行和q的第0行
0 306 4.0   #更新p的第0行和q的第306行
0 413 1.0
0 581 3.0
0 255 5.0
'''
n_factors = 10  # number of factors
alpha = .01  # learning rate
n_epochs = 10  # number of iteration of the SGD procedure
# Randomly initialize the user and item factors.
p = np.random.normal(0, .1, (data.n_users, n_factors))
q = np.random.normal(0, .1, (data.n_items, n_factors))
# Optimization procedure
for _ in range(n_epochs):
for u, i, r_ui in data.all_ratings():
err = r_ui - np.dot(p[u], q[i])
# Update vectors p_u and q_i
p[u] += alpha * err * q[i]
q[i] += alpha * err * p[u]


一旦我们运行SGD过程,就可以估计所有的向量pupu和qiqi的点积来预测所有的评级:

def estimate(u, i):
'''Estimate rating of user u for item i.'''
return np.dot(p[u], q[i])


算法评估

RMSE=∑u,i(r^ui−rui)2−−−−−−−−−−−−√.RMSE=∑u,i(r^ui−rui)2.

参考

中文参考: http://www.infoq.com/cn/articles/matrix-decomposition-of-recommend-system

英文原文: http://nicolas-hug.com/blog/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: