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

问题描述

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

中:

R=1?2??5????1?2?43????5?3??4???2AliceBobCharlieDanielEricFrank R = ( 1 ? 2 ? ? ? ? ? ? 4 2 ? 4 5 ? ? ? 3 ? ? ? 1 ? 3 ? 5 ? ? ? 2 ) Alice Bob Charlie Daniel Eric Frank

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

SVD矩阵分解

Rm×n=Mm×mΣm×nUTn×n R m × n = M m × m Σ m × n U n × n T

Rm×n=Mm×rΣr×rUTr×n 降 维 : R m × n = M m × r Σ r × r U r × n T

如果 R R 是密集的,我们可以很容易计算MU

  • M M 的列是RRT的特征向量
  • The columns of M M can build back all of the columns of R
  • U U 的列是RTR的特征向量。
  • The columns of U U can build back all of the rows of R
  • Σ Σ 的对角元素来源于 RRTRTR R R T 或 R T R 的特征值的平方根,并且是按从大到小的顺序排列的

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

代替方法

计算RRT RTR R T R 的特征向量并不是计算密集矩阵 R R 的SVD的唯一方法。实际上,我们可以找到矩阵M U U ,如果我们能找到所有满足如下条件的向量pu qi q i puMqiUT p u 组 成 M 的 行 , q i 组 成 U T 的 列 ):

rui=puqi ( r u i ) = ( p u ) ( q i )

由于定义矩阵乘法的定义方式,rui的值是两个向量的点积的结果:向量 pu p u ,它是 M M 的一行,特定于用户u;向量 qi q i ,它是 UT U T 的列,特定于项目 i i

  • 对所有的u和i,rui=puqi
    • 所有的向量 pu p u 是相互正交的,所有的向量 qi q i 也如此。
    • 对所有users和items,找出这种向量 puqi p u 和 q i ,可通过解决下面的优化问题(同时遵循正交约束)来完成:

      minpu,qipupvqiqjruiR(ruipuqi)2 min p u , q i p u ⊥ p v q i ⊥ q j ∑ r u i ∈ R ( r u i − p u ⋅ q i ) 2

      它可被理解为,找到向量 pu p u qi q i 使得与 rui r u i 差总和最小。也就是说,我们试图尽可能将 rui r u i 的值与 puqi p u ⋅ q i 相等。

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

      minpu,qiruiR(ruipuqi)2. min p u , q i ∑ r u i ∈ R ( r u i − p u ⋅ q i ) 2 .

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

      梯度下降一般形式

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

      f(θ)=kfk(θ),

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

      • 随机初始化 θ θ
      • 对于给定的次数,重复下面的步骤:
        • 对于所有k,重复以下步骤:
          • 计算 fkθ ∂ f k ∂ θ
          • 更新 θθαfkθ θ ← θ − α ⋅ ∂ f k ∂ θ ,其中 α α 是学习速率(一个很小的值)。

      推荐系统梯度下降求解:

      • 在我们的情况下,参数θ对应于所有的向量 pu p u qi q i (我们将其表示为( pq p ∗ , q ∗ )),而我们想最小化的函数 f f 表示为

      f(p,q)=ruiR(ruipuqi)2=ruiRfui(pu,qi),

      其中 fui f u i 被定义为: fui(pu,qi)=(ruipuqi)2 f u i ( p u , q i ) = ( r u i − p u ⋅ q i ) 2

      • 向量 pu p u 关于函数 fui f u i 的偏导为:

        fuipu=pu(ruipuqi)2=2qi(ruipuqi) ∂ f u i ∂ p u = ∂ ∂ p u ( r u i − p u ⋅ q i ) 2 = − 2 q i ( r u i − p u ⋅ q i )

      • 向量 qi q i 关于函数 fui f u i 的偏导为:

        fuiqi=qi(ruipuqi)2=2pu(ruipuqi) ∂ f u i ∂ q i = ∂ ∂ q i ( r u i − p u ⋅ q i ) 2 = − 2 p u ( r u i − p u ⋅ q i )

      算法实现

      求解步骤如下:

      1. 随机初始化所有的向量 pu p u qi q i
      2. 对给定的次数(如,迭代数),重复下面的步骤:
        • 对所有已知的评级 rui r u i ,重复下面的步骤:
          • 计算 fuipu ∂ f u i ∂ p u fuiqi ∂ f u i ∂ q i
          • 更新 puqi p u 和 q i : pupu+αqi(ruipuqi p u ← p u + α ⋅ q i ( r u i − p u ⋅ q i ) , qiqi+αpu(ruipuqi q i ← q i + α ⋅ p u ( r u i − p u ⋅ q i )

      核心代码:

      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过程,就可以估计所有的向量 pu p u qi q i 的点积来预测所有的评级:

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

      算法评估

      RMSE=u,i(r^uirui)2. RMSE = ∑ u , i ( r ^ u i − r u i ) 2 .

      参考

      中文参考: http://www.infoq.com/cn/articles/matrix-decomposition-of-recommend-system
      英文原文: http://nicolas-hug.com/blog/

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值