ML_矩阵分解

一、推荐算法概述
对于推荐系统(Recommend System, RS),从广义上的理解为:为用户(User)推荐相关的商品(Items)。常用的推荐算法主要有:

基于内容的推荐(Content-Based Recommendation)
协同过滤的推荐(Collaborative Filtering Recommendation)
基于关联规则的推荐(Association Rule-Based Recommendation)
基于效用的推荐(Utility-Based Recommendation)
基于知识的推荐(Knowledge-Based Recommendation)
组合推荐(Hybrid Recommendation)
在推荐系统中,最重要的数据是用户对商品的打分数据,数据形式如下所示:
 

 D1D2D3D4
U153-1
U24--1
U311-5
U41--4
U5-154

其中,U1⋯U5表示的是5个不同的用户,D1⋯D4表示的是4个不同的商品,这样便构成了用户-商品矩阵,在该矩阵中,有用户对每一件商品的打分,其中“-”表示的是用户未对该商品进行打分。

在推荐系统中有一类问题是对未打分的商品进行评分的预测。

二、基于矩阵分解的推荐算法
2.1、矩阵分解的一般形式
矩阵分解是指将一个矩阵分解成两个或者多个矩阵的乘积。对于上述的用户-商品矩阵(评分矩阵),记为Rm×n。可以将其分解成两个或者多个矩阵的乘积,假设分解成两个矩阵Pm×k和Qk×n,我们要使得矩阵Pm×k和Qk×n的乘积能够还原原始的矩阵Rm×n:

\dpi{120} \fn_jvn R _{m\times n} \approx P_{m\times k} \times R_{k\times n} = \hat{R}_{m\times n}

其中,矩阵Pm×k表示的是m个用户与k个主题之间的关系,而矩阵Qk×n表示的是k个主题与n个商品之间的关系。

2.2、利用矩阵分解进行预测
在上述的矩阵分解的过程中,将原始的评分矩阵Rm×n分解成两个矩阵Pm×k和Qk×n的乘积:

R _{m\times n} \approx P_{m\times k} \times R_{k\times n} = \hat{R}_{m\times n}
那么接下来的问题是如何求解矩阵Pm×k和Qk×n的每一个元素,可以将这个问题转化成机器学习中的回归问题进行求解。

2.2.1、损失函数
可以使用原始的评分矩阵Rm×n与重新构建的评分矩阵R^m×n之间的误差的平方作为损失函数,即:

{e_{i,j}}^{2} =(r_{i,j}-\hat{r}_{i,j}) ^{2}=(r_{i,j}-\sum_{k=1}^{K}p_{i,k}q_{k,j})^{2}
最终,需要求解所有的非“-”项的损失之和的最小值:

min loss = \sum_{r_{i,j\neq -}}{e_{i,j}}^{2}

2.2.2、损失函数的求解
对于上述的平方损失函数,可以通过梯度下降法求解,梯度下降法的核心步骤是

求解损失函数的负梯度:


根据负梯度的方向更新变量:

通过迭代,直到算法最终收敛。

2.2.3、加入正则项的损失函数即求解方法
通常在求解的过程中,为了能够有较好的泛化能力,会在损失函数中加入正则项,以对参数进行约束,加入L2正则的损失函数为:


利用梯度下降法的求解过程为:

求解损失函数的负梯度:



根据负梯度的方向更新变量:


通过迭代,直到算法最终收敛。

2.2.4、预测
利用上述的过程,我们可以得到矩阵Pm×k和Qk×n,这样便可以为用户i对商品j进行打分:

                                                           

代码实现:

import numpy as np
import random
'''
   mat_data R(m x n )
        d1 d2 d3 dn
u1
u2
u3
um
            P(m x k )
        s1 s2 s3 sk
u1
u2
u3
um
            Q(k x n)
        d1 d2 d3 dn
s1
s2
s3
sk
'''
#原始矩阵,主题数,迭代次数,步长
def SGD(mat_data,k,iterate_times,alpha):
    m = mat_data.shape[0]   #shape[0]是矩阵的行
    n = mat_data.shape[1]   #shape[1]是矩阵的列
    #随机数据初始化
    P = np.random.random((m,k))
    Q = np.random.random((k,n))
    for times in range(iterate_times):
        i = random.randint(0,m-1)
        j = random.randint(0,n-1)
        P[i,:] -= alpha * (np.dot(P[i,:],Q[:,j]) - mat_data[i,j])* Q[:,j]
        Q[:,j] -= alpha *( np.dot(P[i,:],Q[:,j]) - mat_data[i,j] )* P[i,:]
        #打印误差
       # print(abs(np.dot(P[i,:],Q[:,j]) - mat_data[i,j] ))
    return P,Q
'''
--------------------------begin--------------------------------------
'''
data = np.array([
                [0,63,3,7],
                [2,3,0,6],
                [3,5,46,1]
                         ],float)
a = SGD(data,1000,50000,0.001)
#打印P,Q,以及预测mat M
print(a[0])
print(a[1])
print(np.dot(a[0],a[1]))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值