矩阵分解如何帮助为新用户填写稀疏效用/评级矩阵?

时间:2016-06-04 18:00:06

标签: python matrix scikit-learn recommendation-engine yelp

这是我第一次尝试机器学习。我正在使用yelp数据集编写一个非常简单的推荐引擎。它是用python编写的,使用pandas和numpy库进行(数据处理)。我已经把数据缩小到餐馆(数百万),然后只有拉斯维加斯的餐馆(数千),然后只有3.5星或更高的餐厅,超过50评论(数百)。此外,我将用户缩小到仅审核了至少20%餐厅的用户。最后,我到达了一个由1800家餐厅拥有100名用户的评级矩阵。

然而,我觉得提供(相对)有用的建议仍然很少。目标是使用基于项目项协作的过滤计算向量距离使用余弦相似性。

我一直在阅读有关处理稀疏矩阵的问题,而且共识似乎是使用矩阵分解。然而,似乎这些读数中的大多数处理当前用户并使用矩阵分解作为推动当前用户推荐的算法,同时解决作为副产品的稀疏性问题。我的理解在这里是否正确?我正在寻找的是一种方法,首先解决稀疏性问题,然后使用余弦向量距离来指导推荐。

如果分解实际上是要走的路:我应该使用什么sklearn.decomposition方法,即PCA,SVD,NMF?

[[ 3, 0, 0, ..., 0, 0, 0],
[ 0, 0, 0, ..., 0, 0, 0],
[ 0, 0, 0, ..., 0, 4, 3],
...
[ 1, 0, 0, ..., 0, 0, 0],
[ 0, 0, 0, ..., 0, 0, 2],
[ 0, 0, 5, ..., 0, 1, 3]] 

(100名用户X 1800餐厅)

1 个答案:

答案 0 :(得分:1)

降低评级数量并不是提高建议准确性的好方法(至少直接)。 说,稀疏性不是"大"问题。实际上,推荐的因子分解算法旨在处理这种稀疏性:99%,98%,95%的稀疏度。

目前,矩阵分解提供了最佳结果,其概念非常简单。此外,基于记忆的CF方法(如基于项目,基于用户,......)效率更低,灵活性更低,结果比基于模型的更差。

最常用的算法基于SVD:

  • Funk的SVD(a.k.a SVD,虽然不是真正的SVD。它是近似值。)
  • BRISM​​F(Funk' s的偏颇正规化版本)
  • SVD ++:BRISM​​F加隐式反馈信息。
  • timesSVD:也为日期时间建模的SVD ++
  • trustSVD:包含信任信息的SVD ++(如朋友)

这些算法的基础包括:

  1. 创建一些低秩矩阵并随机初始化它们
  2. 对于数据集中的每个评级,请根据您的预测计算错误。
  3. 使用您正在优化的函数的渐变更新低阶矩阵
  4. 重复
  5. Python示例(BRISM​​F):

    # Initialize low-rank matrices (K is the number of latent factors)
    P = np.random.rand(num_users, K)  # User-feature matrix
    Q = np.random.rand(num_items, K)  # Item-feature matrix
    
    # Factorize R matrix using SGD
    for step in range(steps):
    
        # Compute predictions
        for k in range(0, len(data)):
            i = data.X[k, user_col]  # Users
            j = data.X[k, item_col]  # Items
            r_ij = data.Y[k]  # rating(i, j)
    
            # NOTE: For simplicity (here) I've considered the 
            # bias a standard deviation, but it should be
            # learned for better accuracy.
            bias = global_avg + std_user[i] + std_item[j]
    
            # Make prediction and compute error
            rij_pred = bias + np.dot(Q[j, :], P[i, :])
            eij = rij_pred - r_ij
    
            # Update P and Q at the same time, they're dependents
            tempP = alpha * 2 * (eij * Q[j, :] + beta * P[i, :])
            tempQ = alpha * 2 * (eij * P[i, :] + beta * Q[j, :])
            P[i] -= tempP
            Q[j] -= tempQ
    

    <强>附加

    • 出于速度原因(以及代码的简单性),我建议您完成所有矢量化
    • 如果需要,尝试创建缓存。即使使用正确的数据结构,在稀疏矩阵中访问也可能非常慢。
    • 此算法在计算上非常昂贵,因此对于简单版本,您可以在1,000,000个等级的数据集中获得10s / iter
    • 我正在为 Orange3数据挖掘构建一个简单的库,所以如果您有兴趣,可以查看:https://github.com/biolab/orange3-recommendation