apache-spark - K-Means 聚类偏向于一个中心

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

我有一个 wiki 页面的语料库(棒球、曲棍球、音乐、足球),我通过 tfidf 运行,然后通过 kmeans 运行。在开始几个问题之后(您可以看到我之前的问题),我终于得到了 KMeansModel...但是当我尝试预测时,我不断得到同一个中心。这是因为数据集较小,还是因为我正在将多单词文档与少量单词(1-20)查询进行比较?还是我做错了什么?请参阅下面的代码:

//Preprocessing of data includes splitting into words 
//and removing words with only 1 or 2 characters
val corpus: RDD[Seq[String]]
val hashingTF = new HashingTF(100000)
val tf = hashingTF.transform(corpus)
val idf = new IDF().fit(tf)
val tfidf = idf.transform(tf).cache
val kMeansModel = KMeans.train(tfidf, 3, 10)

val queryTf = hashingTF.transform(List("music"))
val queryTfidf = idf.transform(queryTf)
kMeansModel.predict(queryTfidf) //Always the same, no matter the term supplied

这个问题似乎与this one有些关系。

最佳答案

更多的是 list 而不是答案:

  1. 单个单词查询或非常短的句子可能不是一个好的选择,尤其是与大型特征向量结合使用时。我将从语料库中的重要文档片段开始

    手动检查每个集群的查询之间的相似性。它与每个集群有远程相似吗?

    import breeze.linalg.{DenseVector => BDV, SparseVector => BSV, Vector => BV}
    import breeze.linalg.functions.cosineDistance
    import org.apache.spark.mllib.linalg.{Vector, SparseVector, DenseVector}
    
    def toBreeze(v: Vector): BV[Double] = v match {
      case DenseVector(values) => new BDV[Double](values)
      case SparseVector(size, indices, values) => {
        new BSV[Double](indices, values, size)
      }
    }
    
    val centers =  kMeansModel.clusterCenters.map(toBreeze(_))
    val query = toBreeze(queryTfidf)
    centers.map(c => cosineDistance(query, c))
    
  2. K 均值收敛吗?根据数据集和初始质心,十次或二十次迭代可能是不够的。尝试将此数字增加到一千左右,看看问题是否仍然存在。

  3. 您的语料库是否足够多样化以形成有意义的集群?尝试找到语料库中每个文档的质心。您是否获得相对均匀的分布或几乎所有文档都分配到单个集群。

    进行目视检查。将您的 tfidf RDD 转换为矩阵,应用 PCA、绘图、按簇着色,看看是否获得有意义的结果。

    同时绘制质心并检查它们是否覆盖了可能的簇。如果没有再次检查收敛性。

    您还可以检查质心之间的相似性:

    (0 until centers.size)
      .toList
      .flatMap(i => ((i + 1) until centers.size)
      .map(j => (i, j, 1 - cosineDistance(centers(i), centers(j)))))
    
  4. 你的预处理足够彻底吗?简单地删除简短的单词很可能是不够的。我至少会使用删除停用词来扩展它。一些词干也不会造成伤害。

  5. K-Means 结果取决于初始质心。尝试多次运行算法,看看问题是否仍然存在。

  6. 尝试更复杂的算法,例如 LDA

关于apache-spark - K-Means 聚类偏向于一个中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32936380/

相关文章:

java - 如何将配置属性传递给 SparkListener?

machine-learning - 将 URL 分类 - 机器学习

machine-learning - 我可以删除预训练 Keras 模型中的层吗?

scala - 分别处理spark中的多个目录

sql - 在 zeppelin %sql 中显示完整的列大小

python - 减少(键,值),其中值是 Spark 中的字典

machine-learning - Julia ML : Is there a recommended data format for loading data to Flux, Knet,深度学习库

machine-learning - 如何使用 k-means 聚类获得更多特征

c# - 数据聚类方法

matlab - 显示集群 kmeans 数据上的行