【发布时间】:2017-03-22 13:17:43
【问题描述】:
我有一个包含 Userid、ItemID、Ratings 的 Spark 数据框。我正在建立一个推荐系统。
数据如下:
originalDF.show(5)
+----+----+------+
|user|item|rating|
+----+----+------+
| 353| 0| 1|
| 353| 1| 1|
| 353| 2| 1|
| 354| 3| 1|
| 354| 4| 1|
+----+----+------+
它有 56K 的唯一用户和 8.5K 的唯一项目。
因此,如果您看到每个 UserID 都有每个项目的记录 (RoW) 和相应的评级。因此,每个用户 ID 有多个记录。
现在我通过随机拆分 0.6,0.2,0.2 % 将其拆分为训练、验证和测试。所以基本上 60% 的随机记录用于训练,20% 用于验证,其余 20% 用于测试,如下所示:
random_split=originalDF.randomSplit(split_perc,seed=20)
return random_split[0],random_split[1],random_split[2]
这给我留下了以下数据集计数
train,validation,test=train_test_split(split_sdf,[0.6,0.2,0.2])
print "Training size is {}".format(train.count())
print "Validation size is {}".format(validation.count())
print "Test size is {}".format(test.count())
'/'
print "Original Dataset Size is {}".format(split_sdf.count())
Training size is 179950
Validation size is 59828
Test size is 60223
Original Dataset Size is 300001
现在我在训练数据上训练 Spark pyspark.ml.ALS 算法。
als = ALS(rank=120, maxIter=15, regParam=0.01, implicitPrefs=True)
model = als.fit(train)
当我从模型对象中检查 userFactors 和 itemFactors 时,我得到:
itemF=model.itemFactors
itemF.toPandas().shape
Out[111]:
(7686, 2)
In [113]:
userF=model.userFactors
userF.toPandas().shape
Out[113]:
(47176, 2)
这意味着它只给了我一个预测的因子矩阵。训练数据中的唯一用户和项目。
现在我如何获得每个用户的所有项目的预测?
如果我这样做了
prediction=model.transform(originalDF)
其中 OriginalDF 是分解为训练、验证和测试的整个数据集,是否可以预测每个用户的所有项目?
我的问题是,如果我的数据集有 56K 用户 X 8.5K 项,那么我想找到相同 56K X8.5K 的预测矩阵,而不仅仅是 47K X7.6K 训练数据。
我在这里做错了什么?我了解这些数据仅适用于 47k X7.6K 训练数据,而不是原始的 56k X8.5K 评级数据。那么我是否将数据拆分为 train,val 错误?
我知道对于推荐系统,应该为每个用户随机屏蔽某些项目的一些评分,并将剩余的用于训练并在这些屏蔽值上进行测试。我在这里做了同样的事情,因为用户的每条记录都是对不同项目的评分。当我们随机拆分时,我们实际上是在掩盖用户的一些评分,而不是将它们用于训练。
请指教。
编辑:
在具有用户 X 项目矩阵(56K 用户 X 8.5 项目)的典型推荐系统中
我们基本上为每个用户屏蔽(设为 0)一些随机项目评级。然后将整个矩阵传递给推荐算法,并将其分解为两个因素矩阵的乘积。
但是在 Spark 中,我们不使用 Userx 项目矩阵。我们基本上将每个项目列评级作为每个用户的单独行,而不是拥有 8.5K 项目列。
因此,如果您在原始用户项目矩阵中看到屏蔽(将某些项目评分设为 0),则与在 spark 数据框中不为每个用户使用一些随机行相同。正确的?
这是我找到了一种将数据拆分(我也使用过)为 train 和 val 的方法
training_RDD, validation_RDD, test_RDD = small_ratings_data.randomSplit([6, 2, 2], seed=0L)
validation_for_predict_RDD = validation_RDD.map(lambda x: (x[0], x[1]))
test_for_predict_RDD = test_RDD.map(lambda x: (x[0], x[1]))
我在这里也使用了类似的 randomSplit 东西。所以我不确定这里有什么问题。
我可以理解,由于训练数据不包含所有用户和项目,项目因素矩阵也只有那么多用户和项目因素。那么我该如何克服呢?最后,我基本上需要一个针对所有用户和项目的预测矩阵。
【问题讨论】:
-
这里有什么问题?是的,您可以使用在
train上训练的模型来预测test或originalDF,但后者不能很好地估计模型性能。
标签: python apache-spark pyspark apache-spark-mllib recommendation-engine