我想要执行群集的大量数据。问题是,我不希望整个集合有一个集群,但每个用户都需要集群。基本上我会先用userid做一个groupby,然后运行KMeans。
问题是,一旦你执行了groupby,任何映射都将在spark控制器上下文之外,因此任何创建RDD的尝试都将失败。 mllib中Spark的KMeans lib需要一个RDD(因此它可以并行化)。
我看到两个解决方法,但我希望有更好的解决方案。
1)手动循环控制器中的所有成千上万的用户(当事情变大时可能有数百万用户),并为每个用户运行kmeans。
2)在控制器中执行groupby,然后在map中运行由外部库提供的非并行kmeans。
请告诉我还有另一种方式,我宁愿拥有一切||尽可能。
答案 0 :(得分:1)
编辑:我在回复时并不知道它是pyspark
。但是,我会将其留作可以改编的想法
我有类似的问题,我能够提高性能,但它仍然不是我理想的解决方案。也许对你来说它可以奏效。
我们的想法是在许多较小的RDD(每个用户ID为一个新的RDD)中打破RDD,将它们保存到数组中,然后为每个" sub-RDD&调用处理函数(在您的情况下为聚类) #34 ;.建议的代码如下(注释中的解释):
// A case class just to use as example
case class MyClass(userId: Long, value: Long, ...)
// A Scala local array with the user IDs (Could be another iterator, such as List or Array):
val userList: Seq[Long] = rdd.map{ _.userId }.distinct.collect.toSeq // Just a suggestion!
// Now we can create the new rdds:
val rddsList: Seq[RDD[MyClass]] = userList.map {
userId => rdd.filter({ item: MyClass => item.userId == userId })
}.toSeq
// Finally, we call the function we want for each RDD, saving the results in a new list.
// Note the ".par" call, which is used to start the expensive execution for multiple RDDs at the same time
val results = rddsList.par.map {
r => myFunction(r)
}
我知道这与您的第一个选项大致相同,但通过使用.par
调用,我能够提高性能。
此调用将rddsList
对象转换为https://us.mc-api.net/对象。这个新的Scala对象允许并行计算,因此理想情况下,map函数会同时为多个RDD调用myFunction(r)
,这可以提高性能。
有关并行收藏的详细信息,请查看ParSeq
。