我有一个维基页面(棒球,曲棍球,音乐,足球),我正在tfidf
然后通过kmeans
。在开始几个问题之后(你可以看到我之前的问题),我终于得到了KMeansModel
...但是当我尝试predict
时,我会继续获得相同的中心。这是因为小数据集,还是因为我将多字文档与少量字(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
有些相关答案 0 :(得分:3)
更多的清单而不是答案:
单词查询或非常短的句子可能不是一个好选择,特别是与大特征向量组合时。我将从语料库
中的重要文件片段开始手动检查查询每个群集之间的相似性。它甚至与每个集群远程相似吗?
[value1, value2, ..., value]
K-Means会聚吗?根据数据集和初始质心,十次或二十次迭代可能是不够的。尝试将此数字增加到一千左右,看看问题是否仍然存在。
您的语料库是否足够多样化以形成有意义的群集?尝试在语料库中找到每个文档的质心。您是否获得相对统一的分布,或者几乎所有文档都分配到单个群集。
进行目视检查。将您的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))
RDD转换为矩阵,应用PCA,绘图,逐个颜色,看看是否得到了有意义的结果。
绘制质心并检查它们是否涵盖了可能的群集。如果不再检查收敛。
您还可以检查质心之间的相似性:
tfidf
您的预处理是否足够彻底?简单地删除简短的单词很可能不够。我会用删除停用词来扩展它。一些干预也不会受到伤害。
K-Means结果取决于初始质心。尝试多次运行算法,看看问题是否仍然存在。
尝试更复杂的算法,如LDA