在推荐系统中使用矩阵分解

Posted

技术标签:

【中文标题】在推荐系统中使用矩阵分解【英文标题】:Using matrix factorization for a recommender system 【发布时间】:2017-03-16 20:52:39 【问题描述】:

我正在使用 C# 6.0 中基于项目的协作过滤器为餐馆开发推荐系统。我想设置我的算法以尽可能好地执行,因此我对预测用户尚未评论的餐厅评分的不同方法进行了一些研究。

我将从我所做的研究开始

首先,我想使用用户之间的 pearson 相关性来设置基于用户的协作过滤器,以便能够查看哪些用户可以很好地组合在一起。 这样做的主要问题是能够计算这种相关性所需的数据量。首先,您需要在同一家餐厅的每 2 位用户获得 4 条评论。但我的数据将非常稀疏。 2 个用户不可能评论完全相同的 4 家餐厅。我想通过扩大匹配项来解决这个问题(即不匹配同一餐厅的用户,而是同一类型的餐厅),但这给我带来了一个问题,即很难确定我将在相关性中使用哪些评论,因为用户可以在“快餐”类型的餐厅留下 3 条评论。以下哪一项最适合其他用户对快餐店的评论?

经过更多研究,我得出结论,基于项目的协同过滤器优于基于用户的协同过滤器。但是,我又遇到了数据稀疏问题。在我的测试中,我成功地计算了用户尚未评论的餐厅评分的预测,但是当我在稀疏数据集上使用该算法时,结果还不够好。 (大多数情况下,两家餐厅之间不可能有相似之处,因为没有 2 位用户对同一家餐厅进行评分)。 经过更多研究后,我发现使用矩阵分解方法可以很好地处理稀疏数据。

现在是我的问题

我一直在互联网上寻找有关使用此方法的教程,但我没有任何推荐系统经验,我对代数的了解也有限。我理解方法的正确性。您有一个矩阵,其中一侧是用户,另一侧是餐馆。每个单元格都是用户对餐厅的评分。 矩阵分解方法创建了两个矩阵,一个是用户和餐厅类型之间的权重,另一个是餐厅和这些类型之间的权重。

我只是想不通的是如何计算餐厅类型与餐厅/用户之间的权重(如果我正确理解矩阵分解)。我找到了几十个计算这些数字的公式,但我不知道如何分解它们并将它们应用到我的应用程序中。

我将举例说明数据在我的应用程序中的外观: 在该表中,U1 代表用户,R1 代表餐厅。 每家餐厅都有自己的标签(餐厅类型)。 IE。 R1 有标签“意大利”,R2 有“快餐”等。

   |  R1  |  R2  |  R3  |  R4  |
U1 |  3   |  1   |  2   |  -   |
U2 |  -   |  3   |  2   |  2   |
U3 |  5   |  4   |  -   |  4   |
U4 |  -   |  -   |  5   |  -   |

有没有人可以为我指明正确的方向或解释我应该如何在我的数据上使用这种方法?任何帮助将不胜感激!

【问题讨论】:

不知何故,这种方法对我来说听起来很可疑...“不是在同一家餐厅匹配用户,而是在同一类型的餐厅”听起来好像用户正在评价他的首选食物种类。但情况可能并非如此,用户正在评价 一家餐厅在提供预期食物方面的表现如何,如果你用 McD 代替一家体面的汉堡餐厅,则结果替换可能不会胜过漂亮的Random.Next 调用(我认为您想预测得比这更好?)。 正确,这就是为什么当我弄清楚如何实现它时,我决定转向基于项目的协同过滤器或可能的矩阵分解 一般的想法是用每个餐厅类型的评级来代替每家餐厅的缺失评级。第一个矩阵平均餐厅评分,第二个矩阵突出显示同一类型餐厅内部的差异。例如,如果餐厅 A 和 B 都是意大利餐厅,并且唯一的现有用户给他们评分 1 和 3,则第一个矩阵可以包含 2,第二个矩阵可以包含 0,5 和 1,5(这里我们使用单元格的乘法)。如果有 2 个用户,第二个矩阵会以某种方式平均餐厅类型值,以便整体平均值保持不变。 【参考方案1】:

矩阵分解假设“潜在因素”(例如用户对意大利食物的偏好和食物的意大利度)受矩阵中的评分影响。

因此,整个问题类型转换为矩阵重建问题,存在许多不同的解决方案。一个简单的(可能是缓慢的)解决方案是(除了 ALS 和矩阵重建的一些其他可能性之外)使用梯度下降算法逼近矩阵。推荐这篇短文ieee article about recommender systems。

提取潜在因素是一个不同的问题。

所以 GDM 的实现可能如下所示:

public void learnGDM()
//traverse learnSet
for(int repeat = 0; repeat < this.steps; repeat++)
    for (int i = 0; i < this.learnSet.length; i++)
        for (int j = 0; j < this.learnSet[0].length; j++)
            if(this.learnSet[i][j] > 0.0d)
                double Rij = this.learnSet[i][j];

                for(int f = 0 ; f <= latentFactors; f++)
                    double error = Rij - dotProduct(Q.getRow(i), P.getRow(j));/*estimated_Rij;*/
                    //ieee computer 1.pdf
                    double qif = Q.get(i, f);
                    double pif = P.get(j, f);
                    double Qvalue = qif + gradientGamma * (error * pif - gradientLambda * qif);
                    double Pvalue = pif + gradientGamma * (error * qif - gradientLambda * pif);
                    Q.set(i,f, Qvalue);
                    P.set(j, f, Pvalue);
                
            
        
    
    //check global error
    if(checkGlobalError() < 0.001d)
        System.out.println("took" + repeat + "steps");
        break;
    

learnset 是一个二维数组,其中包含 IEEE 文章中的 Ratingmatrix。 GDM 算法每次迭代都会稍微改变评级向量 P 和 Q,以便它们接近评级矩阵中的评级。然后可以通过 P 和 Q 的点积计算“未给出”评级。未给出评级的最高估计将是推荐。

所以这就是开始。有很多优化和其他算法或 GDM 的修改版本也可以并行运行。

一些不错的读物:

recommender systems in the Encyclopedia of Machine Learning

presentation on matrix factorization

recommender systems

【讨论】:

以上是关于在推荐系统中使用矩阵分解的主要内容,如果未能解决你的问题,请参考以下文章

基于矩阵分解原理的推荐系统

推荐系统基础:使用PyTorch进行矩阵分解进行动漫的推荐

原理篇 | 推荐系统之矩阵分解模型

推荐系统中矩阵分解算法-funkSVD和ALS

推荐系统之矩阵分解(MF)

python机器学习:推荐系统实现(以矩阵分解来协同过滤)