我试图在分组数据上运行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的任何明显错误,或者建议如何实现在每个群组中聚类数据的目标?
答案 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。