Apache Spark K-Means聚类 - 用于输入的RDD

时间:2014-11-04 09:34:15

标签: scala machine-learning apache-spark

我试图在分组数据上运行Spark的k-means聚类,但是当我尝试聚集每个组时,我遇到了各种错误。

输入RDD看起来像(userID:Long,coords:[Vector]),即:

org.apache.spark.rdd.RDD[(Long, Seq[org.apache.spark.mllib.linalg.Vector])]

Vector包含X Y坐标,即双打对。我想为每个UserID识别坐标簇,因此我在RDD上进行映射,并尝试为每个组运行k-means:

val userClusters = userCoordVectors.map {
  case (userId, coords) =>
    val clusters = 4
    val iterations = 30
    // Need to convert coords to RDD for input into K-Means
    val parsedData = sc.parallelize(coords)

    // Apply k-means
    val model = KMeans.train(parsedData, clusters, iterations)
    ...
    etc
}

但是当我运行这个时,我会从线上获得一个NPE:

val parsedData = sc.parallelize(coords)

问题是,我必须将coords转换为K-Means操作的RDD。

另一方面,如果我先收集输入RDD,那么我就不会获得NPE。相反,我得到了Java堆错误,大概是因为我实现了整个RDD。

 val userClusters = sc.parallelize(userCoordVectors.collect.map {
 ...
 })

收集这个RDD中的数据在这里似乎不对,所以我假设应该有更好的方法,但我不知道如何让parsedData行工作。

任何人都可以看到我在这里尝试使用K-Means的任何明显错误,或者建议如何实现在每个群组中聚类数据的目标?

1 个答案:

答案 0 :(得分:3)

您不能在RDD运算符的任何函数内使用SparkContext或RDD。它们无法序列化并通过网络发送。

Matei Zaharia在这里回答:http://apache-spark-user-list.1001560.n3.nabble.com/Can-we-get-a-spark-context-inside-a-mapper-td9605.html

  

您目前无法在Spark任务中使用SparkContext,因此在这种情况下,您必须调用某种本地K-means库。您可以尝试使用的一个示例是Weka(http://www.cs.waikato.ac.nz/ml/weka/)。然后,您可以使用SparkContext.wholeTextFiles将文本文件作为字符串的RDD加载,并在每个文件上调用Weka。