在sklearn中使用轮廓系数有效评估k-means算法
我正在对大约100万个项目进行k-means聚类(每个项目用大约100个特征的向量表示)。我已经尝试了不同的k值,现在想用sklearn中实现的轮廓系数来评估这些不同的结果。不过,如果不进行抽样直接运行,似乎是不可行的,而且会花费很长时间,所以我想我需要使用抽样,也就是说:
metrics.silhouette_score(feature_matrix, cluster_labels, metric='euclidean',sample_size=???)
不过,我对合适的抽样方法并没有很好的把握。对于我的矩阵大小,有没有什么经验法则来决定使用多大的样本?是选择我分析机器能处理的最大样本,还是选择多个较小样本的平均值更好?
我之所以这样问,主要是因为我之前的测试(样本大小=10000)得出的结果非常不直观。
我也愿意考虑其他更可扩展的评估指标。
我编辑一下来可视化这个问题:图表显示了不同样本大小下,轮廓系数与聚类数量的关系
不奇怪的是,增加样本大小似乎能减少噪音。但奇怪的是,考虑到我有100万个非常不同的向量,2或3个聚类居然是“最佳”的聚类数量。换句话说,令人困惑的是,当我增加聚类数量时,轮廓系数却呈现出大致单调下降的趋势。
3 个回答
因为目前没有一个大家都认可的最佳方法来确定聚类的最佳数量,所以所有的评估技术,包括 轮廓系数、间隙统计量 等,基本上都是依赖某种经验法则或试错的方式。所以我认为,最好的办法就是尝试多种技术,而不要对任何一种方法过于自信。
在你的情况下,理想且最准确的评分应该是在整个数据集上计算的。不过,如果你需要使用部分样本来加快计算速度,你应该使用你机器能处理的尽可能大的样本量。这样做的原因就像是想从你关注的人群中获取尽可能多的数据点一样。
还有一点,sklearn实现的轮廓系数是使用随机(非分层)抽样的。你可以多次使用相同的样本量(比如 sample_size=50000
)重复计算,这样可以判断这个样本量是否足够大,能够产生一致的结果。
kmeans算法会收敛到局部最优解。初始位置对找到最佳聚类数量非常重要。通常,使用主成分分析(PCA)或其他降维技术来减少噪声和维度,然后再进行kmeans聚类是个不错的主意。
为了完整性补充一下,使用“围绕中位数划分”(partition around medoids)来找到最佳聚类数量也是个好方法。这和使用轮廓法(silhouette method)是等价的。
出现奇怪观察结果的原因可能是因为不同大小的样本有不同的起始点。
说了这么多,评估手头数据集的聚类能力是很重要的。一个可行的方法是使用最坏对比率(Worst Pair ratio),具体可以参考这里的内容 Clusterability。
其他指标
肘部法则:计算每个K值所解释的方差百分比,然后选择图表开始平稳的K值。(这里有个不错的描述 https://en.wikipedia.org/wiki/Determining_the_number_of_clusters_in_a_data_set)。显然,如果K等于数据点的数量,你可以解释100%的方差。关键是在哪个K值开始,方差的改善不再明显。
信息理论:如果你能为某个K值计算出一个可能性,那么你可以使用AIC、AICc或BIC(或者其他信息理论的方法)。比如,对于AICc,它就是在增加K值时平衡可能性的提升和所需参数数量的增加。实际上,你只需要选择一个能让AICc最小化的K值。
你可以通过运行其他方法来大致了解合适的K值,这些方法会给你估计聚类的数量,比如DBSCAN。虽然我没见过这种方法用来估计K值,但依赖它可能不太合适。不过,如果DBSCAN也给你一个小的聚类数量,那么可能你的数据中有些特征你没有注意到(也就是说,聚类的数量没有你想象的那么多)。
采样量多少合适
看起来你从图中已经得出了答案:无论你的采样如何,轮廓分数的模式都是一样的。所以这个模式似乎对采样的假设非常稳健。