人工智能绪论:矩阵分解

利用矩阵分解实现推荐算法

相关案例介绍

​ 矩阵中,描述了5个用户(U1,U2,U3,U4 ,U5)对4个物品(D1,D2,D3,D4)的评分(1-5分),- 表示没有评分,现在目的是把没有评分的 给预测出来,然后按预测的分数高低,给用户进行推荐。

矩阵R可以近似表示为P与Q的乘积:R(m,n)≈ P(m,K)*Q(K,n)

所以评估的矩阵可以由下式计算:

实现方法

1.计算重新构建的矩阵每个元素的值,列出表达式

2. 构建损失函数

用原始矩阵元素和新矩阵元素差的平方作为损失函数,因此每段元素差的平方表达式为:

最后的损失函数是所有已知项损失之和:

3.利用梯度下降获得p,q分量

根据梯度下降公式:

 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeEm2YyZ-1582644298839)(../images/%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E5%85%AC%E5%BC%8F.png)]

 向负梯度方向更新变量:

 不停迭代直至到达终止条件

为了防止过拟合,需要加入正则化项

只需把损失值改为下式即可

梯度下降公式更新为:
 

代码流程解析

1.遍历原矩阵R中的所有非0元素,同时计算出每一项的损失值e(i,j)

2.根据梯度下降更新P, Q矩阵中的所有元素

3.根据损失函数计算总量即所有E^2_i,j之和

4.判断是否达到临界条件,如第3步结果小于目标条件值,终止迭代过程

5.循环进行此过程直至达到目标次数

完整代码推导

1.构建原矩阵R,及P,Q矩阵,设置k的值

P = numpy.random.rand(N, K) 为生成一个任何元素不大于1的N行K列的矩阵

   R = [
       [5, 3, 0, 1],
       [4, 0, 0, 1],
       [1, 1, 0, 5],
       [0, 1, 5, 4],
       ]
    R = numpy.array(R)
    N = len(R)
    M = len(R[0])
    K = 2
    P = numpy.random.rand(N, K)  # 得到随机分配的P和Q矩阵
    Q = numpy.random.rand(K, M)

 2.设置步长即a,b的值用于构造损失函数和进行梯度下降,即a代表α,b代表β

这里的a, b设置如下:

   a = 0.0002
   b = 0.02

3. 开始进行迭代,并在每次迭代中遍历整个R矩阵

    for step in range(5000):       # 迭代次数
        for i in range(len(R)):
            for j in range(len(R[i])):

求每组元素损失值的表达式为

eij = R[i][j]-numpy.dot(P[i, :], Q[:, j]

P,Q矩阵的元素进行更改

for k in range(K):                        
    P[i][k] = P[i][k]+a*(2*eij*Q[k][j]-b*P[i][k])
    Q[k][j] = Q[k][j]+a*(2*eij*P[i][k]-b*Q[k][j])

对应上述梯度下降公式

    for step in range(5000):       # 迭代次数
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j] != 0:
                    eij = R[i][j]-numpy.dot(P[i, :], Q[:, j])  # 真实值减去预测值
                    for k in range(K):                         # 对P和Q矩阵里的变量进行更新
                        P[i][k] = P[i][k]+a*(2*eij*Q[k][j]-b*P[i][k])
                        Q[k][j] = Q[k][j]+a*(2*eij*P[i][k]-b*Q[k][j])

4. 计算损失函数(新旧矩阵元素差的平方和)

前半部分

loss = loss+pow(R[i][j]-numpy.dot(P[i, :], Q[:, j]), 2)

后半部分

loss = loss+(b/2)*(pow(R[i][k], 2)+pow(Q[k][j], 2))

最后 判断是否达到终止条件:

        if loss < 0.0001:
            break

完整函数 

    result = []                    # 一个空列表
    a = 0.0002
    b = 0.02
    for step in range(5000):       # 迭代次数
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j] != 0:
                    eij = R[i][j]-numpy.dot(P[i, :], Q[:, j])  # 真实值减去预测值
                    for k in range(K):                         # 对P和Q矩阵里的变量进行更新
                        P[i][k] = P[i][k]+a*(2*eij*Q[k][j]-b*P[i][k])
                        Q[k][j] = Q[k][j]+a*(2*eij*P[i][k]-b*Q[k][j])
        loss = 0
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j] != 0:        # 计算损失函数
                    loss = loss+pow(R[i][j]-numpy.dot(P[i, :], Q[:, j]), 2)
                    for k in range(K):  # 贝塔部分
                        loss = loss+(b/2)*(pow(R[i][k], 2)+pow(Q[k][j], 2))
        result.append(loss)             # 损失函数值插入到列表中
        if loss < 0.0001:
            break

最后在代码末尾计算P,Q矩阵之积即可得到新矩阵

MR = numpy.dot(P1, Q1) 

源代码


import matplotlib.pyplot as plt    
from math import pow
import numpy   #引用numpy库,用于对矩阵的处理
def matrix_factorization(R,P,Q,K):
    result=[]        #一个空列表
    a=0.0002
    b=0.02
    for step in range(5000):        #迭代次数
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]!=0:
                    eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) #真实值减去预测值
                    for k in range(K):          #对P和Q矩阵里的变量进行更新
                        P[i][k]=P[i][k]+a*(2*eij*Q[k][j]-b*P[i][k])
                        Q[k][j]=Q[k][j]+a*(2*eij*P[i][k]-b*Q[k][j])
        loss=0
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]!=0:          #计算损失函数
                    loss=loss+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
                    for k in range(K):  #贝塔部分
                        loss=loss+(b/2)*(pow(R[i][k],2)+pow(Q[k][j],2))
        result.append(loss)         #将损失函数值插入到列表中
        if loss<0.001:
            break
    return P,Q,result
if __name__ == '__main__':
    R=[
       [5,3,0,1],
       [4,0,0,1],
       [1,1,0,5],
       [0,1,5,4],
       ]
    R=numpy.array(R)
    N=len(R)
    M=len(R[0])
    K=2
    P=numpy.random.rand(N,K)  #得到随机分配的P和Q矩阵
    Q=numpy.random.rand(K,M)
    print("原始矩阵为:\n",R)
    P1,Q1,LOSS= matrix_factorization(R,P,Q,K)
    MR=numpy.dot(P1,Q1)      #P1,Q1两个相乘
    print("经过矩阵分解得到的矩阵:\n",MR)
    #绘制损失函数图
    n=len(LOSS)
    x=range(n)
    plt.plot(x,LOSS,color='r',linewidth=3)
    plt.title("Convergence curve")
    plt.xlabel("generation")
    plt.ylabel("loss")
    plt.show()

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值