scala - K均值||用于 Spark 情绪分析

标签 scala apache-spark machine-learning k-means apache-spark-mllib

我正在尝试编写基于Spark的情感分析程序。为此,我使用了 word2vec 和 KMeans 聚类。从 word2Vec 中,我在 100 维空间中获得了 20k 个单词/向量集合,现在我正在尝试对该向量空间进行聚类。当我使用默认并行实现运行 KMeans 时,该算法运行了 3 个小时!但如果采用随机初始化策略,大约需要 8 分钟。 我究竟做错了什么?我有 mac book pro 机器,带有 4 内核处理器和 16 GB RAM。

K ~= 4000 最大Interation为20

var vectors: Iterable[org.apache.spark.mllib.linalg.Vector] =
      model.getVectors.map(entry => new VectorWithLabel(entry._1, entry._2.map(_.toDouble)))
    val data = sc.parallelize(vectors.toIndexedSeq).persist(StorageLevel.MEMORY_ONLY_2)
    log.info("Clustering data size {}",data.count())
    log.info("==================Train process started==================");
    val clusterSize = modelSize/5

    val kmeans = new KMeans()
    kmeans.setInitializationMode(KMeans.K_MEANS_PARALLEL)
    kmeans.setK(clusterSize)
    kmeans.setRuns(1)
    kmeans.setMaxIterations(50)
    kmeans.setEpsilon(1e-4)

    time = System.currentTimeMillis()
    val clusterModel: KMeansModel = kmeans.run(data)

Spark 上下文初始化在这里:

val conf = new SparkConf()
      .setAppName("SparkPreProcessor")
      .setMaster("local[4]")
      .set("spark.default.parallelism", "8")
      .set("spark.executor.memory", "1g")
    val sc = SparkContext.getOrCreate(conf)

关于运行该程序的更新也很少。我在 Intelij IDEA 中运行它。我没有真正的 Spark 集群。但我以为你的个人机可以是Spark集群

我看到程序卡在 Spark 代码 LocalKMeans.scala 的循环内:

// Initialize centers by sampling using the k-means++ procedure.
    centers(0) = pickWeighted(rand, points, weights).toDense
    for (i <- 1 until k) {
      // Pick the next center with a probability proportional to cost under current centers
      val curCenters = centers.view.take(i)
      val sum = points.view.zip(weights).map { case (p, w) =>
        w * KMeans.pointCost(curCenters, p)
      }.sum
      val r = rand.nextDouble() * sum
      var cumulativeScore = 0.0
      var j = 0
      while (j < points.length && cumulativeScore < r) {
        cumulativeScore += weights(j) * KMeans.pointCost(curCenters, points(j))
        j += 1
      }
      if (j == 0) {
        logWarning("kMeansPlusPlus initialization ran out of distinct points for centers." +
          s" Using duplicate point for center k = $i.")
        centers(i) = points(0).toDense
      } else {
        centers(i) = points(j - 1).toDense
      }
    }

最佳答案

使用KMeans.K_MEANS_PARALLEL进行初始化比随机更复杂。然而,它不应该产生这么大的差异。我建议调查一下,是否是并行算法花费了很多时间(它实际上应该比 KMeans 本身更有效)。

有关分析的信息,请参阅: http://spark.apache.org/docs/latest/monitoring.html

如果不是初始化占用了时间,则存在严重错误。然而,使用随机初始化对于最终结果来说应该不会更差(只是效率较低!)。

实际上,当您使用 KMeans.K_MEANS_PARALLEL 进行初始化时,您应该通过 0 次迭代获得合理的结果。如果情况并非如此,则数据分布中可能存在一些规律性,导致 KMeans 偏离轨道。因此,如果您没有随机分发数据,您也可以更改它。然而,如果迭代次数固定,这样的影响会让我感到惊讶。

关于scala - K均值||用于 Spark 情绪分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34616842/

相关文章:

scala - 缩小、折叠或扫描(左/右)?

python - 了解贝叶斯过滤在 SciKit 中的工作原理并提高准确性

machine-learning - 在 sagemaker 中使用相同的预处理代码进行训练和推理

scala - 为什么在 sbt 1.0.x 中使用 "sbt run"运行 Spark 应用程序会失败?

python - 尝试保存数据帧时内存不足

java - 如何使用 Java 中的结构化流从 Kafka 反序列化记录?

machine-learning - SVR与其他简单回归模型的区别

scala - 无法将表示类型实现为类型成员

scala - 如果在 Slick 3.0.0 中不存在则插入以进行批量插入

scala - 带有只读基目录的 SBT