gpt4 book ai didi

Scala - HashMap 上的折叠操作示例 ** 不是 foldLeft

转载 作者:行者123 更新时间:2023-12-01 23:53:31 33 4
gpt4 key购买 nike

我对使用 Scala 很感兴趣,因为它似乎是并行化操作的好方法。我需要设计一种利用向量乘法的机器学习算法(很多都是如此)。我知道如何做算法,但我想做的是来自 HashMaps 的稀疏向量实现。几乎所有向量都存储为 HashMaps[Int, Double],其中向量中给定 double 的索引是作为键的整数。

使用 Pythonish 伪代码,
<7, 6, 5, 4> ==> {1:7, 2:6, 3:5, 4:4}

我想使用 fold、reduce、map ... 等定义点积函数,但我不想使用 foldLeft、reduceLeft ... 因为我希望它具有潜在的并行性,因为我的向量可以起来到 6000 多个维度,对于点积,顺序无关紧要。

我已经阅读了许多 foldLeft 和 reduceLeft 的例子,但我还没有找到如何使用 HashMap.fold 或 HashMap.reduce。

我对函数式编程有相当程度的了解,但我不了解 Scala 中的错误消息。这是我或多或少想要的模板。

object NGramAnalysis {
def main(args: Array[String]) {
val mapped = HashMap(1->1.2, 5->2.4)
println(mapped.fold( .... What goes here ... )
}
}

结论
我想要一个使用 HashMap.fold 的可靠示例 不折叠左和 HashMap.reduce 一样

先感谢您。我已经挣扎了一段时间。

最佳答案

首先,fold的区别和 reduce在那fold接受一个额外的参数作为初始值,而 reduce将集合中的第一个元素作为初始值,如果集合为空,则抛出异常。所以,foldreduce 更通用一些,所以我将这两个函数都称为 fold从现在开始。

对于 fold要正确工作,集合中的元素必须形成半群,也就是说,应该有一个二元运算,它也必须是结合的,也就是说,应该保持以下恒等式:(a `op` b) `op` c == a `op` (b `op` c) .需要关联性,因为 fold不指定操作应用顺序,这在并行上下文中尤为重要。此操作用于执行折叠:

a1 `op` a2 `op` a3 `op` ... `op` an

reduce并行运行,它可以拆分集合并在一个线程中减少前半部分,在另一个线程中减少后半部分;然后使用相同的操作将它们的结果连接起来。只有当操作是关联的时,这才能正常工作。

正如我已经说过的, fold方法有两个参数:初始值和一个 [associative] 二元运算符。例如,要并行连接字符串列表,您可以这样做:
val strings = Seq("a", "b", "c", "d", ...)
strings.par.fold("")(_ ++ _) // or strings.par.reduce(_ ++ _) if you know that strings is non-empty

因此,要实现点积,您需要考虑要折叠/归约的集合以及执行此归约的二元运算符。

这是两个集合的点积的简单实现:
(c1 zip c2).par.map {
case (e1, e2) => e1 * e2
}.reduce(_ + _)

也就是说,我们使用 * 将这些集合压缩在一起以成对地相乘它们的元素。运算符,然后我们使用 + 减少结果运算符(operator)。当然, *+必须在 c1 的元素上定义和 c2 .

然而, HashMap未排序,因此其迭代顺序未定义。无法保证 zip将连接具有相同键的元素,这使得上述点积的想法不正确。你需要做这样的事情:
c1.par.map {
case (k, v) => v * c2(k)
}.reduce(_ + _)

在这里,我们没有压缩集合,而是使用第一个映射中的所有键在第二个映射中执行查找。

关于Scala - HashMap 上的折叠操作示例 ** 不是 foldLeft,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25321691/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com