使用肘部法则确定GMM最优聚类数:绘图异常问题求助
GMM肘部法则图绘制问题解决思路
问题描述
我想绘制高斯混合模型(GMM)的肘部法则图来确定最优聚类数量,目前使用mean_属性计算样本到聚类中心的距离,但无法生成典型的肘部法则图,求解决思路?
当前代码:
from sklearn.mixture import GaussianMixture from scipy.spatial.distance import cdist def elbow_report(X): meandist = [] n_clusters = range(2,15) for n_cluster in n_clusters: gmm = GaussianMixture(n_components=n_cluster) gmm.fit(X) meandist.append( sum( np.min( cdist(X, gmm.means_, 'mahalanobis', VI=gmm.precisions_), axis=1 ), X.shape[0] ) ) plt.plot(n_clusters,meandist,'bx-') plt.xlabel('Number of Clusters') plt.ylabel('Mean Mahalanobis Distance') plt.title('GMM Clustering for n_cluster=2 to 15') plt.show()
核心问题与解决步骤
1. 修复计算逻辑错误
你代码里的sum(..., X.shape[0])是关键错误:sum()的第二个参数是求和的初始值,不是用来求平均的除数。这会导致结果被额外加上样本数,完全偏离“平均距离”的计算逻辑,自然出不来肘部曲线。
正确的做法是先计算所有样本到最近聚类中心的最小马氏距离之和,再除以样本数得到平均值。
2. 选择更贴合GMM的评估指标
GMM是概率模型,单纯用距离的肘部法则效果有限,更推荐用BIC(贝叶斯信息准则)或AIC(赤池信息准则):
- BIC/AIC会平衡模型拟合度和复杂度,数值先降后升,最低点对应的聚类数就是最优解;
- 相比距离指标,这两个准则更能反映GMM的拟合质量,避免过拟合。
3. 确保模型收敛
默认迭代次数可能不够,建议设置max_iter=500,同时可以检查gmm.converged_属性确认模型是否收敛,避免无效结果。
修正后的代码示例
方案1:修正距离计算的肘部法则图
import numpy as np import matplotlib.pyplot as plt from sklearn.mixture import GaussianMixture from scipy.spatial.distance import cdist def elbow_report(X): mean_distances = [] n_clusters = range(2, 15) for n_cluster in n_clusters: # 增加迭代次数,固定随机种子保证可复现 gmm = GaussianMixture(n_components=n_cluster, max_iter=500, random_state=42) gmm.fit(X) # 计算每个样本到最近聚类中心的马氏距离,求平均值 min_distances = np.min(cdist(X, gmm.means_, 'mahalanobis', VI=gmm.precisions_), axis=1) avg_distance = np.mean(min_distances) mean_distances.append(avg_distance) plt.plot(n_clusters, mean_distances, 'bx-') plt.xlabel('聚类数量') plt.ylabel('平均马氏距离') plt.title('GMM聚类肘部法则图(2-15类)') plt.show()
方案2:BIC/AIC准则图(更推荐)
import numpy as np import matplotlib.pyplot as plt from sklearn.mixture import GaussianMixture def gmm_model_selection(X): bic_scores = [] aic_scores = [] n_clusters = range(2, 15) for n_cluster in n_clusters: gmm = GaussianMixture(n_components=n_cluster, max_iter=500, random_state=42) gmm.fit(X) bic_scores.append(gmm.bic(X)) aic_scores.append(gmm.aic(X)) plt.figure(figsize=(10, 5)) plt.plot(n_clusters, bic_scores, 'bx-', label='BIC') plt.plot(n_clusters, aic_scores, 'rx-', label='AIC') plt.xlabel('聚类数量') plt.ylabel('准则值') plt.title('GMM聚类BIC/AIC准则图(2-15类)') plt.legend() plt.show()
说明
用BIC/AIC时,曲线的最低点就是最优聚类数——BIC更倾向于选择更简洁的模型,AIC更看重拟合效果,两者结果相近时可信度更高。
内容的提问来源于stack exchange,提问作者Elliott de Launay
相关产品推荐
相关产品推荐

