首页 > 编程语言 >推荐算法——基于矩阵分解的推荐算法

推荐算法——基于矩阵分解的推荐算法

时间:2023-06-14 19:35:03浏览次数:44  
标签:推荐 矩阵 算法 error print qk pi data


一、推荐算法概述

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

  • 基于内容的推荐(Content-Based Recommendation)
  • 协同过滤的推荐(Collaborative Filtering Recommendation)
  • 基于关联规则的推荐(Association Rule-Based Recommendation)
  • 基于效用的推荐(Utility-Based Recommendation)
  • 基于知识的推荐(Knowledge-Based Recommendation)
  • 组合推荐(Hybrid Recommendation)

在推荐系统中,最重要的数据是用户对商品的打分数据,数据形式如下所示:

推荐算法——基于矩阵分解的推荐算法_损失函数

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

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

二、基于矩阵分解的推荐算法

2.1、矩阵分解的一般形式

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



Rm×n≈Pm×k×Qk×n=R^m×n

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

2.2、利用矩阵分解进行预测

在上述的矩阵分解的过程中,将原始的评分矩阵Rm×n分解成两个矩阵Pm×k和Qk×n的乘积:



Rm×n≈Pm×k×Qk×n=R^m×n

那么接下来的问题是如何求解矩阵Pm×k和Qk×n的每一个元素,可以将这个问题转化成机器学习中的回归问题进行求解。

2.2.1、损失函数

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



e2i,j=(ri,j−r^i,j)2=(ri,j−∑k=1Kpi,kqk,j)2

最终,需要求解所有的非“-”项的损失之和的最小值:



minloss=∑ri,j≠−e2i,j

2.2.2、损失函数的求解

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

  • 求解损失函数的负梯度:



∂∂pi,ke2i,j=−2(ri,j−∑k=1Kpi,kqk,j)qk,j=−2ei,jqk,j



∂∂qk,je2i,j=−2(ri,j−∑k=1Kpi,kqk,j)pi,k=−2ei,jpi,k

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



pi,k′=pi,k−α∂∂pi,ke2i,j=pi,k+2αei,jqk,j



qk,j′=qk,j−α∂∂qk,je2i,j=qk,j+2αei,jpi,k

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

2.2.3、加入正则项的损失函数即求解方法

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



E2i,j=(ri,j−∑k=1Kpi,kqk,j)2+β2∑k=1K(p2i,k+q2k,j)

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

  • 求解损失函数的负梯度:



∂∂pi,kE2i,j=−2(ri,j−∑k=1Kpi,kqk,j)qk,j+βpi,k=−2ei,jqk,j+βpi,k



∂∂qk,jE2i,j=−2(ri,j−∑k=1Kpi,kqk,j)pi,k+βqk,j=−2ei,jpi,k+βqk,j

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



pi,k′=pi,k−α(∂∂pi,ke2i,j+βpi,k)=pi,k+α(2ei,jqk,j−βpi,k)



qk,j′=qk,j−α(∂∂qk,je2i,j+βqk,j)=qk,j+α(2ei,jpi,k−βqk,j)

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

2.2.4、预测

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



∑k=1Kpi,kqk,j

2.3、程序实现

对于上述的评分矩阵,通过矩阵分解的方法对其未打分项进行预测,最终的结果为:

推荐算法——基于矩阵分解的推荐算法_基于矩阵分解的推荐_02

程序代码如下:

#!/bin/python
'''
Date:20160411
@author: zhaozhiyong
'''
from numpy import *

def load_data(path):
    f = open(path)
    data = []
    for line in f.readlines():
        arr = []
        lines = line.strip().split("\t")
        for x in lines:
            if x != "-":
                arr.append(float(x))
            else:
                arr.append(float(0))
        #print arr
        data.append(arr)
    #print data
    return data

def gradAscent(data, K):
    dataMat = mat(data)
    print dataMat
    m, n = shape(dataMat)
    p = mat(random.random((m, K)))
    q = mat(random.random((K, n)))

    alpha = 0.0002
    beta = 0.02
    maxCycles = 10000

    for step in xrange(maxCycles):
        for i in xrange(m):
            for j in xrange(n):
                if dataMat[i,j] > 0:
                    #print dataMat[i,j]
                    error = dataMat[i,j]
                    for k in xrange(K):
                        error = error - p[i,k]*q[k,j]
                    for k in xrange(K):
                        p[i,k] = p[i,k] + alpha * (2 * error * q[k,j] - beta * p[i,k])
                        q[k,j] = q[k,j] + alpha * (2 * error * p[i,k] - beta * q[k,j])

        loss = 0.0
        for i in xrange(m):
            for j in xrange(n):
                if dataMat[i,j] > 0:
                    error = 0.0
                    for k in xrange(K):
                        error = error + p[i,k]*q[k,j]
                    loss = (dataMat[i,j] - error) * (dataMat[i,j] - error)
                    for k in xrange(K):
                        loss = loss + beta * (p[i,k] * p[i,k] + q[k,j] * q[k,j]) / 2

        if loss < 0.001:
            break
        #print step
        if step % 1000 == 0:
            print loss

    return p, q


if __name__ == "__main__":
    dataMatrix = load_data("./data")

    p, q = gradAscent(dataMatrix, 5)
    '''
    p = mat(ones((4,10)))
    print p
    q = mat(ones((10,5)))
    '''
    result = p * q
    #print p
    #print q

    print result

其中,利用梯度下降法进行矩阵分解的过程中的收敛曲线如下所示:

推荐算法——基于矩阵分解的推荐算法_推荐_03

'''
Date:20160411
@author: zhaozhiyong
'''

from pylab import *
from numpy import *

data = []

f = open("result")
for line in f.readlines():
    lines = line.strip()
    data.append(lines)

n = len(data)
x = range(n)
plot(x, data, color='r',linewidth=3)
plt.title('Convergence curve')
plt.xlabel('generation')
plt.ylabel('loss')
show()

参考文献


标签:推荐,矩阵,算法,error,print,qk,pi,data
From: https://blog.51cto.com/u_16161414/6480201

相关文章

  • 推荐系统中的常用算法——基于Graph Embedding的GES和EGES
    1.概述相比较于基于CollaborativeFilter算法,基于基础GraphEmbedding模型可以根据用户的行为序列学习出item的embedding,利用item对应的Embedding可以方便计算item与item之间的相似度,并在实践中被证明是卓有成效的方法,在基于基础GraphEmbedding模型,主要包括item2vec,node2vec,deepw......
  • 文本分类fastText算法
    1.概述在深度学习遍地开花的今天,浅层的网络结构甚至是传统的机器学习算法被关注得越来越少,但是在实际的工作中,这一类算法依然得到广泛的应用,或者直接作为解决方案,或者作为该问题的baseline,fastText就是这样的一个文本分类工具。fastText是2016年由facebook开源的用于文本分类的工......
  • 机器学习算法实现解析——libFM之libFM的训练过程概述
    本节主要介绍的是libFM源码分析的第四部分——libFM的训练。FM模型的训练是FM模型的核心的部分。4.1、libFM中训练过程的实现在FM模型的训练过程中,libFM源码中共提供了四种训练的方法,分别为:StochasticGradientDescent(SGD),AdaptiveSGD(ASGD),AlternatingLeastSquares(ALS)和MarkovCh......
  • 挑战数据结构和算法面试题——二叉搜索树的后序遍历
    分析:根据二叉查找树的定义,二叉查找树或者是一棵空二叉树,或者是具有一下特性的二叉树:若它的左子树不为空,则左子树上的所有结点的值均小于根节点的值;若它的右子树不为空,则右子树上的所有结点的值均小于根节点的值;它的左右子树又分别是二叉查找树。结合二叉树的后序遍历,则初始序列的最......
  • 【数据结构和算法面试题】左旋转字符串
    问题分析:本题是常见的旋转字符串的问题,解决的方法是两步旋转的方法:方法:voiddo_reverse(char*p_start,char*p_end){ if(NULL==p_start||NULL==p_end||p_start>p_end)return; chartmp; while(p_start<p_end){ tmp=*p_start; *p_start=*p_end; *p_end......
  • 代码随想录算法训练营第七天| 344.反转字符串 、 541. 反转字符串II、 剑指Offer 05.
     344.反转字符串代码:1voidreverseString(vector<char>&s){23inti=0;4intj=s.size()-1;5while(i<j)6{7charmid=s[i];8s[i]=s[j];9s[j]=mid;1011i++;12......
  • 【数据结构与算法面试题】子数组的最大和
    题目来源“数据结构与算法面试题80道”。问题分析:在数组的每一个位置处保存当前的最大值,当前的最大值组成为:解决方案:intget_max_subarray(int*a,intlength,bool&is_array_ok){ if(NULL==a||length<=0){ is_array_ok=false; return0; } int*p_h_a=(int*......
  • 简单易学的机器学习算法——K-Means++算法
    一、K-Means算法存在的问题由于K-Means算法的简单且易于实现,因此K-Means算法得到了很多的应用,但是从K-Means算法的过程中发现,K-Means算法中的聚类中心的个数k需要事先指定,这一点对于一些未知数据存在很大的局限性。其次,在利用K-Means算法进行聚类之前,需要初始化k个聚类中心,在上述的......
  • 传奇三端互通手游服务器租用推荐,扬州高防BGP服务器140.210.20.x
    传奇三端互通手游热度在至今是只增不减的,越来越多的GM开始研究传奇三端互通,今天我就和你简单分享下传奇三端互通的引擎和大概开服成本,再详细分享下传奇三端互通手游服务器的配置要求,希望可以帮助到你!传奇三端互通即PC、安卓、IOS三端账号数据的互通,一个账号不管在什么设备都能同步,......
  • 数据结构和算法——二叉排序树
    一、二叉排序树对于无序的序列“62,58,88,47,73,99,35,51,93,29,37,49,56,36,48,50”,是否存在一种高效的查找方案,使得能够快速判断在序列中是否存在指定的数值?二叉排序树是一种简单,高效的数据结构。二叉排序树,又称为二叉查找树。二叉排序树或者是一棵空树,或者是具有以下性质的二叉树:若其左子树不为......