修改K-means代码 用Inertia替换轮廓系数确定最优聚类数
问题描述
使用k-means算法开展聚类分析、确定最优聚类数时,若数据集规模过大,silhouette(轮廓系数)的计算开销会过高无法使用。此时可替换为Inertia(惯性值,即簇内误差平方和)结合肘部法则完成k值选择,需要将原有基于轮廓系数的评估、可视化代码修改为惯性值实现,输出标准肘部法则图。
原有最小可复现代码
from sklearn.cluster import KMeans import numpy as np from sklearn.metrics import silhouette_score import matplotlib as mpl import matplotlib.pyplot as plt X = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0],]) kmeans_per_k = [KMeans(n_clusters=k, random_state=42).fit(X) for k in range(1, 10)] inertias = [model.inertia_ for model in kmeans_per_k] silhouette_scores = [silhouette_score(X, model.labels_) for model in kmeans_per_k[1:]] from sklearn.metrics import silhouette_samples from matplotlib.ticker import FixedLocator, FixedFormatter plt.figure(figsize=(11, 9)) for k in (3, 4, 5, 6): plt.subplot(2, 2, k - 2) y_pred = kmeans_per_k[k - 1].labels_ silhouette_coefficients = silhouette_samples(X, y_pred) padding = len(X) // 30 pos = padding ticks = [] for i in range(k): coeffs = silhouette_coefficients[y_pred == i] coeffs.sort() color = mpl.cm.Spectral(i / k) plt.fill_betweenx(np.arange(pos, pos + len(coeffs)), 0, coeffs, facecolor=color, edgecolor=color, alpha=0.7) ticks.append(pos + len(coeffs) // 2) pos += len(coeffs) + padding plt.gca().yaxis.set_major_locator(FixedLocator(ticks)) plt.gca().yaxis.set_major_formatter(FixedFormatter(range(k))) if k in (3, 5): plt.ylabel("Cluster") if k in (5, 6): plt.gca().set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1]) plt.xlabel("Silhouette Coefficient") else: plt.tick_params(labelbottom=False) plt.axvline(x=silhouette_scores[k - 2], color="red", linestyle="--") plt.title("$k={}$".format(k), fontsize=16) #save_fig("silhouette_analysis_plot") plt.show()
预期效果参考

修改后适配代码
核心修改点:
- 移除所有轮廓系数相关的导入、计算、多子图可视化代码
- 直接使用KMeans模型训练后自带的
inertia_属性获取各k值对应的惯性值,无需额外计算,适配大规模数据集 - 绘制单图折线,横轴为聚类数k,纵轴为惯性值,匹配肘部法则图标准样式
from sklearn.cluster import KMeans import numpy as np import matplotlib.pyplot as plt # 测试数据集 X = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0], [10, 2], [10, 4], [10, 0], [1, 2], [1, 4], [1, 0],]) # 遍历k值1~9训练模型,提取惯性值 k_range = range(1, 10) kmeans_per_k = [KMeans(n_clusters=k, random_state=42, n_init='auto').fit(X) for k in k_range] inertias = [model.inertia_ for model in kmeans_per_k] # 绘制肘部法则图 plt.figure(figsize=(10, 6)) plt.plot(k_range, inertias, 'bo-', linewidth=2, markersize=8) plt.xlabel('Number of clusters (k)', fontsize=12) plt.ylabel('Inertia', fontsize=12) plt.title('Elbow Method for Optimal k Selection', fontsize=14) plt.xticks(k_range) plt.grid(alpha=0.3) plt.show()
运行后折线下降趋势明显变缓的拐点即为最优k值,针对本次示例测试数据,拐点在k=2位置,符合数据集天然的2类分布特征。
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

