当前位置:   article > 正文

矩阵分解之知识点记录_大矩阵拆成2小矩阵

大矩阵拆成2小矩阵

1.问题引入

如果给出如图1所示的一个用户对物品的评分表如何预测用户未打分的部分?

图1 用户对不同物品的评分表

可以使用矩阵分解来完成。

矩阵分解的一个作用就是能用来预测如1所示的未知评分,那么如何进行矩阵分解?

我们知道一个矩阵能表示成两个矩阵的乘积的形式即R(m,n)=P(m,k)*Q(k,n),那么对于一个特定的矩阵R我们就可以找到两个矩阵P,Q让P(m,k)*Q(k,n)≈R(m,n)。这样对于如图1所示的矩阵我们就可以预测出用户未打分的物品的分值是多少。k是一个用户自定义的值可以通过交叉验证的方法获得最佳k值。

2.算法原理

如何进行矩阵分解也即如何求解矩阵P与Q的每一项。

可以用如下方法:

1.首先令即预测矩阵R的第i行j列项等于分解矩阵p的第i行乘以矩阵q的第j列。

2.构造损失函数,令原始的矩阵R1与预测的矩阵R之间的误差的平方作为损失函数如果R1(i,j)已知则R1(i,j)的误差的平方和为那么这个误差肯定是越小越好,即要找到对应的Pik和Qkj使得误差最小。可以使用梯度下降的方法求相应的Pik和Qkj。

3.利用梯度下降法求解对应的Pik和Qkj。

先求导

求解对应的Pik和Qkj,因为是求最小值所以应沿梯度的负方向,即新值=旧值+步长*该点的梯度。

Pik和Qk的初值是随机生成的,因为只要迭代次数足够多最终总能找到最小值点,和初值无关。

4.按照梯度下降的方法一直求解一定次数或者两次求得的p或q的差值小于某个给定值后停止迭代。得出对应的分解之后的两个矩阵的每一项,即可得出预测分数。

为了防止模型过拟合,可以增加正则化项即上述求解步骤变为:

1.令和上述第一步的意义相同。

2.为了使模型有更好的泛化能力,在损失函数中增加正则化项即 

 

3.对损失函数求导

沿梯度负方向更新变量

4.按照梯度下降的方法一直求解一定次数或者两次求解的p或q的差值小于某个给定值后停止迭代。得出对应的分解之后的两个矩阵的每一项,即可得出预测分数。

 3.python代码实现

  1. # !/usr/bin/env python
  2. # encoding: utf-8
  3. __author__ = 'Scarlett'
  4. #矩阵分解在打分预估系统中得到了成熟的发展和应用
  5. # from pylab import *
  6. import matplotlib.pyplot as plt
  7. from math import pow
  8. import numpy
  9. def matrix_factorization(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
  10. Q=Q.T # .T操作表示矩阵的转置
  11. result=[]
  12. for step in range(steps): #梯度下降的次数
  13. for i in range(len(R)): #i代表矩阵的每一行
  14. for j in range(len(R[i])): #j代表矩阵的每一列
  15. if R[i][j]>0: #如果原始矩阵的这一项有评分,则梯度下降更新其p矩阵的i行数据和q矩阵的j列数据
  16. eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) # .dot(P,Q) 表示矩阵内积,即p矩阵的第i行和q矩阵的第j列项对应乘积之和
  17. for k in range(K):
  18. P[i][k]=P[i][k]+alpha*(2*eij*Q[k][j]-beta*P[i][k])
  19. Q[k][j]=Q[k][j]+alpha*(2*eij*P[i][k]-beta*Q[k][j])
  20. #每进行一个step对p和q矩阵中相应的项更新一次
  21. eR=numpy.dot(P,Q)
  22. e=0
  23. #计算每次更新后损失函数的值
  24. for i in range(len(R)):
  25. for j in range(len(R[i])):
  26. if R[i][j]>0:
  27. e=e+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
  28. for k in range(K):
  29. e=e+(beta/2)*(pow(P[i][k],2)+pow(Q[k][j],2)) #正则化项的值
  30. result.append(e) #将每一次更新后损失函数的值添加到列表result中
  31. if e<0.001: #如果本次损失函数的值足够小则结束循环
  32. break
  33. return P,Q.T,result
  34. if __name__ == '__main__':
  35. R=[
  36. [5,3,0,1],
  37. [4,0,0,1],
  38. [1,1,0,5],
  39. [1,0,0,4],
  40. [0,1,5,4]
  41. ]
  42. R=numpy.array(R)
  43. N=len(R)
  44. M=len(R[0])
  45. K=2
  46. P=numpy.random.rand(N,K) #随机生成一个 N行 K列的矩阵
  47. Q=numpy.random.rand(M,K) #随机生成一个 M行 K列的矩阵
  48. nP,nQ,result=matrix_factorization(R,P,Q,K)
  49. print("原始的评分矩阵R为:\n",R)
  50. R_MF=numpy.dot(nP,nQ.T)
  51. print("经过MF算法填充0处评分值后的评分矩阵R_MF为:\n",R_MF)
  52. #-------------损失函数的收敛曲线图---------------
  53. n=len(result)
  54. x=range(n)
  55. plt.plot(x,result,color='r',linewidth=3)
  56. plt.title("Convergence curve")
  57. plt.xlabel("generation")
  58. plt.ylabel("loss")
  59. plt.show()

结果:

手工推导

 参考文章地址:推荐系统之矩阵分解及其Python代码实现 - CuriousZero - 博客园有如下R(5,4)的打分矩阵:(“-”表示用户没有打分) 其中打分矩阵R(n,m)是n行和m列,n表示user个数,m行表示item个数 那么,如何根据目前的矩阵R(5,4)如何对未打分的商品进行评分https://www.cnblogs.com/shenxiaolin/p/8637794.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/176655
推荐阅读
相关标签
  

闽ICP备14008679号