我正在使用 Spark 类 IndexedRowMatrix
中的方法 computeSVD
(在 Scala 中)。我注意到它没有 setSeed()
方法。我在同一个输入矩阵上多次运行得到的结果略有不同,这可能是由于 Spark 使用的内部算法。虽然它也实现了近似可扩展的 SVD 算法,但我会从源代码中说,IndexedRowMatrix
中的 computeSVD()
不应用近似版本,而是应用精确版本。
由于我使用 SVD 结果进行推荐,并且用户和项目潜在因子矩阵不同,我实际上得到了不同的推荐列表:在一些运行中,以不同的顺序大致相同的项目,有时一些新项目进入列表和一些缺失,因为在对传递给 computeSVD()
的缺失输入评分矩阵进行插补后,预测的评分通常几乎是相关的。
有没有人遇到过这个问题?有没有办法让它完全确定,或者我遗漏了什么?
谢谢
最佳答案
无论何时在 Apache Spark 中进行数值计算,您都必须牢记两点:
FP 算法不是关联的。
scala> (0.1 + 0.2) + 0.3 == 0.1 + (0.2 + 0.3) res0: Boolean = false
Spark 中的每个交换都是非确定性的潜在来源。为了获得最佳性能,Spark 可以按任意顺序合并上游任务的部分结果。
这可以通过一些防御性编程来解决,但运行时开销通常很高,无法在实践中发挥作用。
因此,即使该过程不依赖于随机数生成器(如 computeSVD
),或者如果设置了生成器种子,最终结果可能会波动。
在实践中,除了重写内部结构之外,您实际上无能为力。如果您怀疑问题出在某种程度上 ill-conditioned您可以尝试使用一些随机噪声构建多个模型,以查看最终预测的敏感度,并在生成预测时将其考虑在内。
关于apache-spark - Spark SVD 不可重现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53468193/