2

我正在尝试使用包含有关用户如何评价项目的数据sklearn.decomposition.NMF的矩阵R来预测他们尚未看到的项目的用户评分。

矩阵的行是用户,列是项目,值是分数,0 分数意味着用户还没有评价这个项目。

现在使用下面的代码,我只设法得到两个矩阵,当它们相乘时返回原始矩阵。

import numpy

R = numpy.array([
     [5,3,0,1],
     [4,0,0,1],
     [1,1,0,5],
     [1,0,0,4],
     [0,1,5,4],
    ])

from sklearn.decomposition import NMF
model = NMF(n_components=4)

A = model.fit_transform(R)
B = model.components_

n = numpy.dot(A, B)
print(n)

问题是,模型不会预测新值来代替0's,这将是预测的分数,而是按原样重新创建矩阵。

如何让模型代替原始矩阵的零点来预测用户分数?

4

2 回答 2

2

这就是应该发生的事情。

但是,在大多数情况下,您不会拥有与产品和/或客户数量如此相似的组件数量。

因此,例如考虑 2 个组件

model = NMF(n_components=2)
A = model.fit_transform(R)
B = model.components_
R_estimated = np.dot(A, B)
print(np.sum(R-R_estimated))
-1.678873127048393
R_estimated
array([[5.2558264 , 1.99313836, 0.        , 1.45512772],
       [3.50429478, 1.32891458, 0.        , 0.9701988 ],
       [1.31294288, 0.94415991, 1.94956896, 3.94609389],
       [0.98129195, 0.72179987, 1.52759811, 3.0788454 ],
       [0.        , 0.65008935, 2.84003662, 5.21894555]])

在这种情况下,您可以看到许多以前的零现在是您可以使用的其他数字。这里有一些上下文https://en.wikipedia.org/wiki/Matrix_factorization_(recommender_systems)

如何选择 n_components?

我认为上面的问题已经得到解答,但如果完整的程序可能如下所示。

为此,我们需要知道 R 中的真实值,并且我们希望专注于预测。

在许多情况下,R 中的 0 是那些新的案例/场景。通常用产品或客户的平均值更新 R,然后计算分解以选择理想的 n_components。对于选择它们可能是一个标准或更多来计算测试样本中的优势

  1. 创建 R_with_Averages
  2. 模型选择: 2.1) 拆分 R_with_Averages 测试和训练 2.2) 使用度量(您只考虑 R 中的真实评估)比较不同的 n_components(从 1 和任意数字) 2.3) 选择最佳模型 --> 最佳 n_components
  3. 使用最佳模型进行预测。

也许很高兴看到:

于 2021-02-06T22:22:53.467 回答
1

sklearn的实现NMF好像不支持缺失值(Nans,这里0值基本代表新用户对应的未知评分),参考这个issue。但是,我们可以使用suprise's 的NMF实现,如下代码所示:

import numpy as np
import pandas as pd
from surprise import NMF, Dataset, Reader

R = np.array([
     [5,3,0,1],
     [4,0,0,1],
     [1,1,0,5],
     [1,0,0,4],
     [0,1,5,4],
    ], dtype=np.float)

R[R==0] = np.nan
print(R)

# [[ 5.  3. nan  1.]
#  [ 4. nan nan  1.]
#  [ 1.  1. nan  5.]
#  [ 1. nan nan  4.]
#  [nan  1.  5.  4.]]

df = pd.DataFrame(data=R, index=range(R.shape[0]), columns=range(R.shape[1]))
df = pd.melt(df.reset_index(), id_vars='index', var_name='items', value_name='ratings').dropna(axis=0)
reader = Reader(rating_scale=(0, 5))
data = Dataset.load_from_df(df[['index', 'items', 'ratings']], reader)

k = 2
algo = NMF(n_factors=k) 
trainset = data.build_full_trainset() 
algo.fit(trainset)
predictions = algo.test(trainset.build_testset()) # predict the known ratings
R_hat = np.zeros_like(R)
for uid, iid, true_r, est, _ in predictions:
    R_hat[uid, iid] = est
predictions = algo.test(trainset.build_anti_testset()) # predict the unknown ratings
for uid, iid, true_r, est, _ in predictions:
    R_hat[uid, iid] = est
print(R_hat)

# [[4.40762528 2.62138084 3.48176319 0.91649316]
# [3.52973408 2.10913555 2.95701406 0.89922637]
# [0.94977826 0.81254138 4.98449755 4.34497549]
# [0.89442186 0.73041578 4.09958967 3.50951819]
# [1.33811051 0.99007556 4.37795636 3.53113236]]

NMF 实现是根据 [NMF:2014] 论文,如此处所述,如下所示

在此处输入图像描述

请注意,此处仅使用已知评分执行优化,导致已知评分的预测值接近真实评分(但未知评分的预测值通常0不像预期的那样接近)。

k同样,像往常一样,我们可以使用交叉验证找到因子的数量。

于 2021-02-17T19:03:09.263 回答