我正在使用Spark类computeSVD
中的方法IndexedRowMatrix
(在Scala中)。我注意到它没有setSeed()
方法。在同一输入矩阵上多次运行,我得到的结果略有不同,可能是由于Spark使用的内部算法。尽管它也实现了近似可伸缩的SVD算法,但是从源代码中我可以说,computeSVD()
中的IndexedRowMatrix
并不应用近似值,而是精确的版本。
由于我使用SVD结果进行建议,并且用户和项目潜在因子矩阵不同,因此我实际上得到了不同的建议列表:在某些运行中,相同项目的排列顺序不同,有时一些新项目会进入列表中的一些缺失了,因为在对传递给computeSVD()
的缺失输入评分矩阵进行插补后,预测评分通常几乎被捆绑在一起。
还有其他人有这个问题吗?有没有办法使这个完全确定性,或者我错过了什么?
谢谢
答案 0 :(得分:1)
每当在Apache Spark中使用数值计算时,都必须牢记两件事:
FP算法不具有关联性。
scala> (0.1 + 0.2) + 0.3 == 0.1 + (0.2 + 0.3)
res0: Boolean = false
Spark中的每次交换都是不确定性的潜在来源。为了获得最佳性能,Spark可以按任意顺序合并上游任务的部分结果。
这可以通过一些防御性编程来解决,但是运行时开销通常很高,在实践中很有用。
因为最终结果可能会波动,即使该过程不依赖于随机数生成器(如computeSVD
)或设置了生成器种子也是如此。
实际上,除了重写内部结构外,您实际上无能为力。如果您怀疑问题是ill-conditioned的问题,则可以尝试使用随机噪声构建多个模型,以查看最终预测的敏感性,并在生成预测时将其考虑在内。