k均值中k的k折交叉验证?
在文档聚类的过程中,作为数据预处理的一步,我首先使用了奇异值分解,得到了 U
、S
和 Vt
。然后,我选择了合适数量的特征值,截断了 Vt
,这样我就能从中得到不错的文档之间的相关性,具体可以参考我在这里看到的内容。接下来,我对矩阵 Vt
的列进行聚类,以将相似的文档聚在一起。为此,我选择了k-means算法,最初的结果看起来还不错(我设置了k=10个聚类),但我想更深入地了解如何选择k值本身。为了确定k-means中的聚类数量 k
,有人建议我查看交叉验证的相关内容这里。
在实施之前,我想先弄清楚是否有内置的方法可以使用numpy或scipy来实现。目前,我进行 kmeans
的方式是直接使用scipy中的函数。
import numpy, scipy
# Preprocess the data and compute svd
U, S, Vt = svd(A) # A is the TFIDF representation of the original term-document matrix
# Obtain the document-document correlations from Vt
# This 50 is the threshold obtained after examining a scree plot of S
docvectors = numpy.transpose(self.Vt[0:50, 0:])
# Prepare the data to run k-means
whitened = whiten(docvectors)
res, idx = kmeans2(whitened, 10, iter=20)
假设到目前为止我的方法是正确的(如果我漏掉了什么步骤,请纠正我),在这个阶段,使用输出进行交叉验证的标准方法是什么?如果有任何参考资料、实现方法或建议,关于如何将其应用于k-means,我将非常感激。
3 个回答
这里提到的“withinss”是用来找到最佳聚类数量的。它是kmeans对象返回的一个属性。这个属性可以用来找到最小的“误差”。
https://www.statmethods.net/advstats/cluster.html
wss <- (nrow(mydata)-1)*sum(apply(mydata,2,var))
for (i in 2:15) wss[i] <- sum(kmeans(mydata,
centers=i)$withinss)
plot(1:15, wss, type="b", xlab="Number of Clusters",
ylab="Within groups sum of squares")
这个公式并不完全正确。不过我自己正在研究一个。这个模型每次都会有所变化,但至少它会是多次迭代中最好的模型。
确实,如果你想用F1分数或V-Measure这样的评分方法来进行传统的交叉验证,你需要一些带标签的数据作为真实情况的参考。不过在这种情况下,你可以直接计算真实数据集中类别的数量,然后把这个数量作为K的最佳值,这样就不需要进行交叉验证了。
另外,你也可以使用聚类稳定性度量作为无监督的性能评估,并为此进行某种交叉验证过程。不过这在scikit-learn中还没有实现,尽管这仍然是我个人的待办事项之一。
你可以在以下链接找到关于这种方法的更多信息:metaoptimize.com/qa上的回答。特别是你应该阅读Ulrike von Luxburg的《聚类稳定性:概述》。
要进行k折交叉验证,你需要一些质量指标来进行优化。这可以是分类指标,比如准确率或者F1分数,或者是一些专门的指标,比如V-measure。
我知道的聚类质量指标也需要一个带标签的数据集(也就是“真实情况”)才能工作;与分类不同的是,分类只需要你的一部分数据有标签就可以进行评估,而k均值算法则可以利用所有数据来确定中心点,从而形成聚类。
V-measure和其他一些评分在scikit-learn这个库中都有实现,还有一些通用的交叉验证代码和一个“网格搜索”模块,可以根据指定的评估指标使用k折交叉验证进行优化。免责声明:我参与了scikit-learn的开发,但我没有写过提到的任何代码。