Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 从数据帧触发MLLib Kmeans,然后再返回_Apache Spark_K Means - Fatal编程技术网

Apache spark 从数据帧触发MLLib Kmeans,然后再返回

Apache spark 从数据帧触发MLLib Kmeans,然后再返回,apache-spark,k-means,Apache Spark,K Means,我的目标是使用Spark(1.3.1)MLLib将kmeans聚类算法应用于非常大的数据集。我使用Spark的hiveContext调用了HDFS中的数据,并最终希望以这种格式将其放回那里 |I.D |cluster | =================== |546 |2 | |6534 |4 | |236 |5 | |875 |2 | 我已经运行了下面的代

我的目标是使用Spark(1.3.1)MLLib将kmeans聚类算法应用于非常大的数据集。我使用Spark的hiveContext调用了HDFS中的数据,并最终希望以这种格式将其放回那里

    |I.D     |cluster |
    ===================
    |546     |2       |
    |6534    |4       |
    |236     |5       |
    |875     |2       |
我已经运行了下面的代码,其中“data”是一个双精度的数据帧,并且是第一列的ID

    val parsedData = data.rdd.map(s => Vectors.dense(s.getDouble(1),s.getDouble(2))).cache()
    val clusters = KMeans.train(parsedData, 3, 20)
这成功地运行了,我现在被困在上面描述的数据帧中,将集群映射回它们各自的ID。我可以通过以下方式将其转换为datframe:

    sc.makeRDD(clusters.predict(parsedData).toArray()).toDF()
但这就是我所能做到的。在正确的轨道上,我想他问了一个与我类似的问题

我怀疑需要标签点库。如果您有任何意见和答案,我们将不胜感激,干杯


编辑:刚刚在Spark用户列表中找到,看起来很有前途

我正在使用pySpark做类似的事情。我猜您可以直接将其转换为Scala,因为没有特定于python的内容。myPointsWithID是我的RDD,每个点都有一个ID,该点表示为一个值数组

# Get an RDD of only the vectors representing the points to be clustered
points = myPointsWithID.map(lambda (id, point): point)
clusters = KMeans.train(points, 
                        100, 
                        maxIterations=100, 
                        runs=50,
                        initializationMode='random')

# For each point in the original RDD, replace the point with the
# ID of the cluster the point belongs to. 
clustersBC = sc.broadcast(clusters)
pointClusters = myPointsWithID.map(lambda (id, point): (id, clustersBC.value.predict(point)))

我知道您希望在最后获得数据帧。我看到两种可能的解决办法。我要说的是,两者之间的选择是品味的问题

从RDD创建列 以RDD的形式获得成对的ID和集群非常容易:

val idPointRDD = data.rdd.map(s => (s.getInt(0), Vectors.dense(s.getDouble(1),s.getDouble(2)))).cache()
val clusters = KMeans.train(idPointRDD.map(_._2), 3, 20)
val clustersRDD = clusters.predict(idPointRDD.map(_._2))
val idClusterRDD = idPointRDD.map(_._1).zip(clustersRDD)
然后从中创建数据帧

val idCluster = idClusterRDD.toDF("id", "cluster")
它之所以有效,是因为映射不会改变RDD中数据的顺序,这就是为什么您可以只压缩ID和预测结果

使用自定义函数(用户定义函数) 第二种方法涉及使用
聚类。预测
方法作为自定义项:

val bcClusters = sc.broadcast(clusters)
def predict(x: Double, y: Double): Int = {
    bcClusters.value.predict(Vectors.dense(x, y))
}
sqlContext.udf.register("predict", predict _)
现在我们可以使用它向数据中添加预测:

val idCluster = data.selectExpr("id", "predict(x, y) as cluster")
请记住,Spark API不允许取消UDF注册。这意味着闭包数据将保存在内存中

错误/非最佳解决方案
  • 使用clusters.predict而不广播
它在分布式设置中不起作用。编辑:实际上它会工作的,我被它搞糊涂了,它使用广播

  • sc.makeRDD(clusters.predict(parsedData.toArray()).toDF()

toArray
收集驱动程序中的所有数据。这意味着在分布式模式下,您将把集群ID复制到一个节点中。

请告知此代码是否适用于您:

import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.clustering._

val rows = data.rdd.map(r => (r.getDouble(1),r.getDouble(2))).cache()
val vectors = rows.map(r => Vectors.dense(r._1, r._2))
val kMeansModel = KMeans.train(vectors, 3, 20)
val predictions = rows.map{r => (r._1, kMeansModel.predict(Vectors.dense(r._1, r._2)))}
val df = predictions.toDF("id", "cluster")
df.show

根据您的代码,我假设:

  • data
    是一个具有三列的数据框(
    label:Double
    x1:Double
    x2:Double
  • 您需要
    KMeans.predict
    使用
    x1
    x2
    进行集群分配
    closestCluster:Int
  • 结果数据帧的格式应为(
    label:Double
    closestCluster:Int
下面是一个简单的示例应用程序,其中一些玩具数据遵循假定的模式:

import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.clustering.KMeans
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.sql.functions.{col, udf}

case class DataRow(label: Double, x1: Double, x2: Double)
val data = sqlContext.createDataFrame(sc.parallelize(Seq(
    DataRow(3, 1, 2),
    DataRow(5, 3, 4),
    DataRow(7, 5, 6),
    DataRow(6, 0, 0)
)))

val parsedData = data.rdd.map(s => Vectors.dense(s.getDouble(1),s.getDouble(2))).cache()
val clusters = KMeans.train(parsedData, 3, 20)
val t = udf { (x1: Double, x2: Double) => clusters.predict(Vectors.dense(x1, x2)) }
val result = data.select(col("label"), t(col("x1"), col("x2")))
重要的部分是最后两行

  • 创建一个UDF(用户定义函数),该函数可直接应用于数据帧列(在本例中为两列
    x1
    x2

  • 选择
    标签
    列以及应用于
    x1
    x2
    列的UDF。由于UDF将预测
    closestCluster
    ,因此在此之后
    结果将是一个由(
    label
    closestCluster
    )组成的数据帧