我正在参与编程竞赛,我有数据,其中第一列是用户,第二列是电影,第三列是十分评分系统中的数字。
0 0 9
0 1 8
1 1 4
1 2 6
2 2 7
我必须预测第三栏(用户,电影,?):
0 2
1 0
2 0
2 1
我也知道答案:
0 2 7.052009
1 0 6.687943
2 0 6.995272
2 1 6.687943
表中的这些数据:行是用户0,1和2;列是电影0,1和2;单元格得分,0
未投票:
[,1] [,2] [,3]
[1,] 9 8 0
[2,] 0 4 6
[3,] 0 0 7
我使用R lang获取SVD:
$d
[1] 12.514311 9.197763 2.189331
$u
[,1] [,2] [,3]
[1,] 0.9318434 -0.3240669 0.1632436
[2,] 0.3380257 0.6116879 -0.7152458
[3,] 0.1319333 0.7216776 0.6795403
$v
[,1] [,2] [,3]
[1,] 0.6701600 -0.31709904 0.6710691
[2,] 0.7037423 -0.01584988 -0.7102785
[3,] 0.2358650 0.94825998 0.2125341
转置v是:
[,1] [,2] [,3]
[1,] 0.6701600 0.7037423 0.2358650
[2,] -0.31709904 -0.01584988 0.94825998
[3,] 0.6710691 -0.7102785 0.2125341
我读到了使用这个公式预测电影评级:
但我不明白如何预测这样的评分:
0 2 7.052009
1 0 6.687943
2 0 6.995272
2 1 6.687943
对于这些数据:
0 2
1 0
2 0
2 1
答案 0 :(得分:5)
对于我的例子,有几件事似乎不合适。首先,如果您没有针对特定用户/电影组合的排名,则不应将此填充为零。这将告诉SVD或任何其他类型的主成分分析(PCA)这些是排名(人为地低)。此外,使用零填充数据计算的协方差将基于不正确的观察数来计算。
使用SVD方法的Netflix获奖者(link for more info)也必须使用某种缺失的数据PCA例程。在这种情况下,非值不应该为零,而是NaN
,尽管我还没有看到他们使用的实际方法的细节。
我的第二个问题是,如果"答案"您提供的实际上是基于您在示例中提供的相当小的数据集。给定3个电影数据集的3个用户,用户之间的相关性计算的位置非常少,因此任何预测都将非常差。然而,我能够产生一个结果,但它与你预期的答案不符。
该方法被称为"递归减去经验正交函数" (RSEOF),这是专门设计的PCA处理缺失数据的方法。也就是说,如果没有更大的训练数据集,我对预测没有多大信心。
因此,我首先加载原始数据集和预测数据集,然后使用acast
包中的reshape2
将训练数据重新整形为矩阵:
library(reshape2)
library(sinkr) (download from GitHub: https://github.com/menugget/sinkr)
# Original data
df1 <- data.frame(user=factor(c(0,0,1,1,2)), movie=factor(c(0,1,1,2,2)), rank=c(9,8,4,6,7))
df1
# Data to predict
df2 <-data.frame(user=factor(c(0,1,2,2)), movie=factor(c(2,0,0,1)))
df2
# Re-organize data into matrix(movies=rows, users=columns)
m1 <- acast(df1, movie ~ user, fill=NaN)
m1
然后使用eof
包(link)的sinkr
函数,我们执行RSEOF:
# PCA of m1 (using recursive SVD)
E <- eof(m1, method="svd", recursive=TRUE, center=FALSE, scale=FALSE)
E$u
E$A #(like "v" but with Lambda units added)
E$Lambda
通过使用PCA信息重建完整矩阵(基本上NaN
),可以获得数据中E$A %*% t(E$u)
位置的预测值:
# Reconstruct full m1 matrix using PCs
R <- eofRecon(E)
R
# Add predicted ranks to df2
pos <- (as.numeric(df2$user)-1)*length(levels(df1$movie)) + as.numeric(df2$movie)
pos
df2$rank <- R[pos]
df2
对象df2
包含您在预测数据集中指定的用户/电影组合的特定预测排名:
user movie rank
1 0 2 9.246148
2 1 0 7.535567
3 2 0 6.292984
4 2 1 5.661985
我个人认为这些值比预期结果更有意义(大约7个)。例如,在按用户(列),m1
,
0 1 2
0 9 NaN NaN
1 8 4 NaN
2 NaN 6 7
我希望用户&#34; 0&#34;想要电影&#34; 2&#34;不仅仅是电影&#34; 1&#34;,鉴于这是用户&#34; 1&#34;的趋势。我们只有电影排名&#34; 1&#34;它们之间的共同点是我们预测的基础。您的期望值为7.05,这将低于电影&#34; 1&#34; (即8),而RSEOF预测是9.2。
我希望这可以帮助你 - 但是,如果你的预期答案是你正在拍摄的,那么我会怀疑&#34;真相持有者&#34;使用的方法。您更有可能只提供较小版本的数据集,因此我们不会得到与您较小的可重复示例中相同的答案。
答案 1 :(得分:3)
这是一个经典的矩阵完成问题,我们用数据矩阵中的零替换未知值。您需要首先获取数据矩阵的特征分解(因为它是对称的,但SVD是等价的,请注意U == V)。然后你有A_pred = UEU ^ T,其中A_pred是A(你的数据矩阵)的预测完整版本。因此,您对A [i] [j]的预测值只是A_pred [i] [j]。