K-Means 聚类实战3种K值选择方法对比与轮廓系数评估1. 引言K-Means 聚类的核心挑战在无监督学习领域K-Means算法因其简洁高效而广受欢迎。然而这个看似简单的算法隐藏着一个关键难题如何确定最佳的聚类数量K选择不当的K值会导致聚类结果失去意义——K值过小会掩盖数据的真实结构而K值过大则可能导致过拟合。想象你正在分析客户数据以进行市场细分。选择3个细分市场可能过于笼统无法捕捉不同客户群体的独特需求而选择20个细分又可能过于碎片化难以制定有效的营销策略。这就是为什么K值选择成为K-Means实践中最为关键的决策点。本文将深入探讨三种主流的K值选择方法肘部法则、轮廓系数法和Gap统计量并通过Python代码实战演示如何在真实数据集鸢尾花数据集上应用这些方法。我们不仅会对比它们的计算原理和可视化表现还会提供一份清晰的决策指南帮助你在不同场景下做出明智选择。2. 环境准备与数据加载2.1 安装必要库在开始之前确保已安装以下Python库pip install numpy pandas matplotlib scikit-learn scipy2.2 加载鸢尾花数据集from sklearn.datasets import load_iris import pandas as pd iris load_iris() X iris.data # 特征矩阵 y iris.target # 真实标签仅用于验证实际聚类中不可用 feature_names iris.feature_names df pd.DataFrame(X, columnsfeature_names) print(df.head())输出示例sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) 0 5.1 3.5 1.4 0.2 1 4.9 3.0 1.4 0.2 2 4.7 3.2 1.3 0.2 3 4.6 3.1 1.5 0.2 4 5.0 3.6 1.4 0.22.3 数据标准化K-Means对特征的尺度敏感因此需要标准化from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X)3. 肘部法则(Elbow Method)3.1 原理与数学基础肘部法则通过观察不同K值下模型的惯性inertia即样本到其最近聚类中心的平方距离和变化来确定最佳K值。当K增大到真实聚类数时惯性的下降会突然变缓形成肘部。数学表达式 $$ \text{Inertia} \sum_{i1}^n \min_{\mu_j \in C}(||x_i - \mu_j||^2) $$其中$n$是样本数$\mu_j$是第j个聚类中心$C$是所有聚类中心的集合3.2 Python实现与可视化from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertias [] K_range range(1, 11) for k in K_range: kmeans KMeans(n_clustersk, random_state42) kmeans.fit(X_scaled) inertias.append(kmeans.inertia_) plt.figure(figsize(10, 6)) plt.plot(K_range, inertias, bo-) plt.xlabel(Number of clusters (K)) plt.ylabel(Inertia) plt.title(Elbow Method For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()3.3 结果解读与局限性在鸢尾花数据集上我们通常会看到在K3处出现明显的肘部。这表明数据可能自然分为3类与真实情况一致。然而肘部法则有几点局限主观性强肘部位置有时不明显需要人工判断适用于凸聚类对于非球形或不规则形状的聚类效果不佳对噪声敏感异常值可能影响惯性计算提示当肘部不明显时可以结合其他方法验证或考虑数据可能没有明显的聚类结构。4. 轮廓系数法(Silhouette Coefficient)4.1 算法原理与公式轮廓系数结合了聚类的内聚度和分离度为每个样本计算一个得分对于样本i计算a(i)i与同簇其他样本的平均距离内聚度计算b(i)i与最近其他簇样本的平均距离分离度轮廓系数 $$ s(i) \frac{b(i) - a(i)}{\max(a(i), b(i))} $$整体轮廓系数是所有样本s(i)的平均值范围在[-1,1]之间接近1表示样本被正确分配到紧密的簇接近0表示样本在两个簇边界接近-1表示样本可能被分配到错误簇4.2 代码实现from sklearn.metrics import silhouette_score silhouette_scores [] K_range range(2, 11) # 轮廓系数需要至少2个簇 for k in K_range: kmeans KMeans(n_clustersk, random_state42) cluster_labels kmeans.fit_predict(X_scaled) silhouette_avg silhouette_score(X_scaled, cluster_labels) silhouette_scores.append(silhouette_avg) plt.figure(figsize(10, 6)) plt.plot(K_range, silhouette_scores, bo-) plt.xlabel(Number of clusters (K)) plt.ylabel(Silhouette Score) plt.title(Silhouette Method For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()4.3 轮廓分析进阶我们可以可视化每个K值下的个体轮廓系数分布from sklearn.metrics import silhouette_samples import numpy as np plt.figure(figsize(15, 10)) for i, k in enumerate(range(2, 5)): plt.subplot(3, 1, i1) kmeans KMeans(n_clustersk, random_state42) cluster_labels kmeans.fit_predict(X_scaled) silhouette_avg silhouette_score(X_scaled, cluster_labels) sample_silhouette_values silhouette_samples(X_scaled, cluster_labels) y_lower 10 for j in range(k): jth_cluster_silhouette_values sample_silhouette_values[cluster_labels j] jth_cluster_silhouette_values.sort() size_cluster_j jth_cluster_silhouette_values.shape[0] y_upper y_lower size_cluster_j color plt.cm.nipy_spectral(float(j) / k) plt.fill_betweenx(np.arange(y_lower, y_upper), 0, jth_cluster_silhouette_values, facecolorcolor, edgecolorcolor, alpha0.7) plt.text(-0.05, y_lower 0.5 * size_cluster_j, str(j)) y_lower y_upper 10 plt.title(fSilhouette plot for K{k} (avg{silhouette_avg:.3f})) plt.xlabel(Silhouette coefficient values) plt.ylabel(Cluster label) plt.axvline(xsilhouette_avg, colorred, linestyle--) plt.tight_layout() plt.show()4.4 优缺点分析优点综合考虑了簇内和簇间距离结果在[-1,1]范围内易于解释可以发现不规则的聚类形状缺点计算复杂度高O(n²)不适合大规模数据倾向于选择中等数量的簇对密度差异大的聚类效果不佳5. Gap统计量(Gap Statistic)5.1 理论基础Gap统计量由Tibshirani等人提出通过比较实际数据的聚类质量与参考分布通常为均匀分布下数据的聚类质量差异来确定最佳K值。基本思想是当实际数据的聚类质量显著优于参考数据时对应的K值就是合适的聚类数。Gap统计量定义 $$ \text{Gap}(k) E^*[\log(W_k)] - \log(W_k) $$ 其中$W_k$是实际数据的聚类误差惯性$E^*$是在参考分布下期望值的估计5.2 Python实现from sklearn.utils import check_random_state from scipy.spatial.distance import pdist, squareform def compute_gap_statistic(X, K_range, B10, random_state42): 计算Gap统计量 参数: X: 标准化后的数据 K_range: 要测试的K值范围 B: 参考数据集数量 返回: gaps: 各K对应的Gap值 s_k: 标准差 gaps np.zeros(len(K_range)) s_k np.zeros(len(K_range)) # 计算实际数据的log(W_k) logWks np.zeros(len(K_range)) for i, k in enumerate(K_range): kmeans KMeans(n_clustersk, random_staterandom_state) kmeans.fit(X) logWks[i] np.log(kmeans.inertia_) # 生成参考数据集并计算期望 random_state check_random_state(random_state) reference_inertias np.zeros((len(K_range), B)) # 生成参考数据集的最小最大值边界 mins X.min(axis0) maxs X.max(axis0) for b in range(B): # 生成均匀分布的参考数据 reference random_state.uniform(mins, maxs, sizeX.shape) for i, k in enumerate(K_range): kmeans KMeans(n_clustersk, random_staterandom_state) kmeans.fit(reference) reference_inertias[i, b] np.log(kmeans.inertia_) # 计算Gap统计量 gaps reference_inertias.mean(axis1) - logWks s_k np.sqrt(1 1/B) * reference_inertias.std(axis1) return gaps, s_k K_range range(1, 11) gaps, s_k compute_gap_statistic(X_scaled, K_range) plt.figure(figsize(10, 6)) plt.errorbar(K_range, gaps, yerrs_k, fmto-, capsize5) plt.xlabel(Number of clusters (K)) plt.ylabel(Gap statistic) plt.title(Gap Statistic For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()5.3 结果解释与选择标准选择满足以下条件的最小K $$ \text{Gap}(k) \geq \text{Gap}(k1) - s_{k1} $$在鸢尾花数据集中我们通常会看到在K3时Gap值达到峰值之后开始下降。这表明3是最佳聚类数。优势自动化程度高减少主观判断理论基础坚实适用于各种形状的聚类局限计算量大需要生成多个参考数据集对参考分布的选择敏感6. 方法对比与实战决策指南6.1 三种方法结果对比方法最佳K值计算复杂度主观性适用场景肘部法则3低高快速初步评估轮廓系数2-3高中精确评估中等规模数据Gap统计量3很高低自动化需求小规模数据6.2 决策流程图graph TD A[开始] -- B{数据规模} B --|小| C{需要自动化} B --|大| D[使用肘部法则] C --|是| E[使用Gap统计量] C --|否| F{聚类形状} F --|球形| G[使用肘部法则或轮廓系数] F --|不规则| H[使用轮廓系数]6.3 综合建议初步探索先使用肘部法则快速了解可能的K值范围精确评估对候选K值使用轮廓系数验证自动化需求当需要完全自动化时使用Gap统计量验证检查最终选择的K值应在多种方法中得到支持7. 完整案例鸢尾花数据集聚类分析7.1 综合应用三种方法# 综合可视化 plt.figure(figsize(12, 8)) # 肘部法则 plt.subplot(3, 1, 1) plt.plot(K_range, inertias, bo-) plt.title(Elbow Method) plt.xticks(K_range) plt.grid(True) # 轮廓系数 plt.subplot(3, 1, 2) plt.plot(range(2,11), silhouette_scores, bo-) plt.title(Silhouette Score) plt.xticks(range(2,11)) plt.grid(True) # Gap统计量 plt.subplot(3, 1, 3) plt.errorbar(K_range, gaps, yerrs_k, fmto-, capsize5) plt.title(Gap Statistic) plt.xticks(K_range) plt.grid(True) plt.tight_layout() plt.show()7.2 最终聚类可视化选择K3进行最终聚类并可视化from sklearn.decomposition import PCA # 使用PCA降维可视化 pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) # K3聚类 kmeans KMeans(n_clusters3, random_state42) cluster_labels kmeans.fit_predict(X_scaled) # 可视化 plt.figure(figsize(10, 6)) colors [red, blue, green] for i in range(3): plt.scatter(X_pca[cluster_labels i, 0], X_pca[cluster_labels i, 1], colorcolors[i], labelfCluster {i}) plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s300, cyellow, marker*, labelCentroids) plt.title(Iris Clustering with K3) plt.xlabel(PCA Component 1) plt.ylabel(PCA Component 2) plt.legend() plt.grid(True) plt.show()7.3 聚类结果评估from sklearn.metrics import adjusted_rand_score # 与真实标签比较仅在有真实标签时使用 ari adjusted_rand_score(y, cluster_labels) print(fAdjusted Rand Index (vs true labels): {ari:.3f}) # 轮廓系数 silhouette silhouette_score(X_scaled, cluster_labels) print(fSilhouette Score: {silhouette:.3f})输出示例Adjusted Rand Index (vs true labels): 0.730 Silhouette Score: 0.4598. 高级话题与优化技巧8.1 K-Means初始化默认的K-Means使用随机初始化可能导致次优解。K-Means通过智能选择初始中心点改善这一问题kmeans KMeans(n_clusters3, initk-means, random_state42)8.2 处理不同尺度特征当特征尺度差异大时考虑使用Mahalanobis距离from sklearn.covariance import EmpiricalCovariance cov EmpiricalCovariance().fit(X_scaled) mahalanobis_kmeans KMeans(n_clusters3, random_state42) mahalanobis_kmeans.fit(cov.mahalanobis(X_scaled))8.3 确定K值的新方法贝叶斯信息准则(BIC)用于GMM 虽然不直接适用于K-Means但可通过高斯混合模型(GMM)评估from sklearn.mixture import GaussianMixture bics [] for k in range(1, 11): gmm GaussianMixture(n_componentsk, random_state42) gmm.fit(X_scaled) bics.append(gmm.bic(X_scaled)) plt.plot(range(1,11), bics, bo-) plt.xlabel(Number of components) plt.ylabel(BIC score) plt.title(BIC For Optimal K) plt.xticks(range(1,11)) plt.grid(True) plt.show()8.4 处理大规模数据对于大数据集使用MiniBatchKMeansfrom sklearn.cluster import MiniBatchKMeans mbk MiniBatchKMeans(n_clusters3, random_state42) mbk.fit(X_scaled)
K-Means 聚类实战:3种K值选择方法对比与轮廓系数评估
发布时间:2026/7/6 17:05:59
K-Means 聚类实战3种K值选择方法对比与轮廓系数评估1. 引言K-Means 聚类的核心挑战在无监督学习领域K-Means算法因其简洁高效而广受欢迎。然而这个看似简单的算法隐藏着一个关键难题如何确定最佳的聚类数量K选择不当的K值会导致聚类结果失去意义——K值过小会掩盖数据的真实结构而K值过大则可能导致过拟合。想象你正在分析客户数据以进行市场细分。选择3个细分市场可能过于笼统无法捕捉不同客户群体的独特需求而选择20个细分又可能过于碎片化难以制定有效的营销策略。这就是为什么K值选择成为K-Means实践中最为关键的决策点。本文将深入探讨三种主流的K值选择方法肘部法则、轮廓系数法和Gap统计量并通过Python代码实战演示如何在真实数据集鸢尾花数据集上应用这些方法。我们不仅会对比它们的计算原理和可视化表现还会提供一份清晰的决策指南帮助你在不同场景下做出明智选择。2. 环境准备与数据加载2.1 安装必要库在开始之前确保已安装以下Python库pip install numpy pandas matplotlib scikit-learn scipy2.2 加载鸢尾花数据集from sklearn.datasets import load_iris import pandas as pd iris load_iris() X iris.data # 特征矩阵 y iris.target # 真实标签仅用于验证实际聚类中不可用 feature_names iris.feature_names df pd.DataFrame(X, columnsfeature_names) print(df.head())输出示例sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) 0 5.1 3.5 1.4 0.2 1 4.9 3.0 1.4 0.2 2 4.7 3.2 1.3 0.2 3 4.6 3.1 1.5 0.2 4 5.0 3.6 1.4 0.22.3 数据标准化K-Means对特征的尺度敏感因此需要标准化from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X)3. 肘部法则(Elbow Method)3.1 原理与数学基础肘部法则通过观察不同K值下模型的惯性inertia即样本到其最近聚类中心的平方距离和变化来确定最佳K值。当K增大到真实聚类数时惯性的下降会突然变缓形成肘部。数学表达式 $$ \text{Inertia} \sum_{i1}^n \min_{\mu_j \in C}(||x_i - \mu_j||^2) $$其中$n$是样本数$\mu_j$是第j个聚类中心$C$是所有聚类中心的集合3.2 Python实现与可视化from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertias [] K_range range(1, 11) for k in K_range: kmeans KMeans(n_clustersk, random_state42) kmeans.fit(X_scaled) inertias.append(kmeans.inertia_) plt.figure(figsize(10, 6)) plt.plot(K_range, inertias, bo-) plt.xlabel(Number of clusters (K)) plt.ylabel(Inertia) plt.title(Elbow Method For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()3.3 结果解读与局限性在鸢尾花数据集上我们通常会看到在K3处出现明显的肘部。这表明数据可能自然分为3类与真实情况一致。然而肘部法则有几点局限主观性强肘部位置有时不明显需要人工判断适用于凸聚类对于非球形或不规则形状的聚类效果不佳对噪声敏感异常值可能影响惯性计算提示当肘部不明显时可以结合其他方法验证或考虑数据可能没有明显的聚类结构。4. 轮廓系数法(Silhouette Coefficient)4.1 算法原理与公式轮廓系数结合了聚类的内聚度和分离度为每个样本计算一个得分对于样本i计算a(i)i与同簇其他样本的平均距离内聚度计算b(i)i与最近其他簇样本的平均距离分离度轮廓系数 $$ s(i) \frac{b(i) - a(i)}{\max(a(i), b(i))} $$整体轮廓系数是所有样本s(i)的平均值范围在[-1,1]之间接近1表示样本被正确分配到紧密的簇接近0表示样本在两个簇边界接近-1表示样本可能被分配到错误簇4.2 代码实现from sklearn.metrics import silhouette_score silhouette_scores [] K_range range(2, 11) # 轮廓系数需要至少2个簇 for k in K_range: kmeans KMeans(n_clustersk, random_state42) cluster_labels kmeans.fit_predict(X_scaled) silhouette_avg silhouette_score(X_scaled, cluster_labels) silhouette_scores.append(silhouette_avg) plt.figure(figsize(10, 6)) plt.plot(K_range, silhouette_scores, bo-) plt.xlabel(Number of clusters (K)) plt.ylabel(Silhouette Score) plt.title(Silhouette Method For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()4.3 轮廓分析进阶我们可以可视化每个K值下的个体轮廓系数分布from sklearn.metrics import silhouette_samples import numpy as np plt.figure(figsize(15, 10)) for i, k in enumerate(range(2, 5)): plt.subplot(3, 1, i1) kmeans KMeans(n_clustersk, random_state42) cluster_labels kmeans.fit_predict(X_scaled) silhouette_avg silhouette_score(X_scaled, cluster_labels) sample_silhouette_values silhouette_samples(X_scaled, cluster_labels) y_lower 10 for j in range(k): jth_cluster_silhouette_values sample_silhouette_values[cluster_labels j] jth_cluster_silhouette_values.sort() size_cluster_j jth_cluster_silhouette_values.shape[0] y_upper y_lower size_cluster_j color plt.cm.nipy_spectral(float(j) / k) plt.fill_betweenx(np.arange(y_lower, y_upper), 0, jth_cluster_silhouette_values, facecolorcolor, edgecolorcolor, alpha0.7) plt.text(-0.05, y_lower 0.5 * size_cluster_j, str(j)) y_lower y_upper 10 plt.title(fSilhouette plot for K{k} (avg{silhouette_avg:.3f})) plt.xlabel(Silhouette coefficient values) plt.ylabel(Cluster label) plt.axvline(xsilhouette_avg, colorred, linestyle--) plt.tight_layout() plt.show()4.4 优缺点分析优点综合考虑了簇内和簇间距离结果在[-1,1]范围内易于解释可以发现不规则的聚类形状缺点计算复杂度高O(n²)不适合大规模数据倾向于选择中等数量的簇对密度差异大的聚类效果不佳5. Gap统计量(Gap Statistic)5.1 理论基础Gap统计量由Tibshirani等人提出通过比较实际数据的聚类质量与参考分布通常为均匀分布下数据的聚类质量差异来确定最佳K值。基本思想是当实际数据的聚类质量显著优于参考数据时对应的K值就是合适的聚类数。Gap统计量定义 $$ \text{Gap}(k) E^*[\log(W_k)] - \log(W_k) $$ 其中$W_k$是实际数据的聚类误差惯性$E^*$是在参考分布下期望值的估计5.2 Python实现from sklearn.utils import check_random_state from scipy.spatial.distance import pdist, squareform def compute_gap_statistic(X, K_range, B10, random_state42): 计算Gap统计量 参数: X: 标准化后的数据 K_range: 要测试的K值范围 B: 参考数据集数量 返回: gaps: 各K对应的Gap值 s_k: 标准差 gaps np.zeros(len(K_range)) s_k np.zeros(len(K_range)) # 计算实际数据的log(W_k) logWks np.zeros(len(K_range)) for i, k in enumerate(K_range): kmeans KMeans(n_clustersk, random_staterandom_state) kmeans.fit(X) logWks[i] np.log(kmeans.inertia_) # 生成参考数据集并计算期望 random_state check_random_state(random_state) reference_inertias np.zeros((len(K_range), B)) # 生成参考数据集的最小最大值边界 mins X.min(axis0) maxs X.max(axis0) for b in range(B): # 生成均匀分布的参考数据 reference random_state.uniform(mins, maxs, sizeX.shape) for i, k in enumerate(K_range): kmeans KMeans(n_clustersk, random_staterandom_state) kmeans.fit(reference) reference_inertias[i, b] np.log(kmeans.inertia_) # 计算Gap统计量 gaps reference_inertias.mean(axis1) - logWks s_k np.sqrt(1 1/B) * reference_inertias.std(axis1) return gaps, s_k K_range range(1, 11) gaps, s_k compute_gap_statistic(X_scaled, K_range) plt.figure(figsize(10, 6)) plt.errorbar(K_range, gaps, yerrs_k, fmto-, capsize5) plt.xlabel(Number of clusters (K)) plt.ylabel(Gap statistic) plt.title(Gap Statistic For Optimal K) plt.xticks(K_range) plt.grid(True) plt.show()5.3 结果解释与选择标准选择满足以下条件的最小K $$ \text{Gap}(k) \geq \text{Gap}(k1) - s_{k1} $$在鸢尾花数据集中我们通常会看到在K3时Gap值达到峰值之后开始下降。这表明3是最佳聚类数。优势自动化程度高减少主观判断理论基础坚实适用于各种形状的聚类局限计算量大需要生成多个参考数据集对参考分布的选择敏感6. 方法对比与实战决策指南6.1 三种方法结果对比方法最佳K值计算复杂度主观性适用场景肘部法则3低高快速初步评估轮廓系数2-3高中精确评估中等规模数据Gap统计量3很高低自动化需求小规模数据6.2 决策流程图graph TD A[开始] -- B{数据规模} B --|小| C{需要自动化} B --|大| D[使用肘部法则] C --|是| E[使用Gap统计量] C --|否| F{聚类形状} F --|球形| G[使用肘部法则或轮廓系数] F --|不规则| H[使用轮廓系数]6.3 综合建议初步探索先使用肘部法则快速了解可能的K值范围精确评估对候选K值使用轮廓系数验证自动化需求当需要完全自动化时使用Gap统计量验证检查最终选择的K值应在多种方法中得到支持7. 完整案例鸢尾花数据集聚类分析7.1 综合应用三种方法# 综合可视化 plt.figure(figsize(12, 8)) # 肘部法则 plt.subplot(3, 1, 1) plt.plot(K_range, inertias, bo-) plt.title(Elbow Method) plt.xticks(K_range) plt.grid(True) # 轮廓系数 plt.subplot(3, 1, 2) plt.plot(range(2,11), silhouette_scores, bo-) plt.title(Silhouette Score) plt.xticks(range(2,11)) plt.grid(True) # Gap统计量 plt.subplot(3, 1, 3) plt.errorbar(K_range, gaps, yerrs_k, fmto-, capsize5) plt.title(Gap Statistic) plt.xticks(K_range) plt.grid(True) plt.tight_layout() plt.show()7.2 最终聚类可视化选择K3进行最终聚类并可视化from sklearn.decomposition import PCA # 使用PCA降维可视化 pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) # K3聚类 kmeans KMeans(n_clusters3, random_state42) cluster_labels kmeans.fit_predict(X_scaled) # 可视化 plt.figure(figsize(10, 6)) colors [red, blue, green] for i in range(3): plt.scatter(X_pca[cluster_labels i, 0], X_pca[cluster_labels i, 1], colorcolors[i], labelfCluster {i}) plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s300, cyellow, marker*, labelCentroids) plt.title(Iris Clustering with K3) plt.xlabel(PCA Component 1) plt.ylabel(PCA Component 2) plt.legend() plt.grid(True) plt.show()7.3 聚类结果评估from sklearn.metrics import adjusted_rand_score # 与真实标签比较仅在有真实标签时使用 ari adjusted_rand_score(y, cluster_labels) print(fAdjusted Rand Index (vs true labels): {ari:.3f}) # 轮廓系数 silhouette silhouette_score(X_scaled, cluster_labels) print(fSilhouette Score: {silhouette:.3f})输出示例Adjusted Rand Index (vs true labels): 0.730 Silhouette Score: 0.4598. 高级话题与优化技巧8.1 K-Means初始化默认的K-Means使用随机初始化可能导致次优解。K-Means通过智能选择初始中心点改善这一问题kmeans KMeans(n_clusters3, initk-means, random_state42)8.2 处理不同尺度特征当特征尺度差异大时考虑使用Mahalanobis距离from sklearn.covariance import EmpiricalCovariance cov EmpiricalCovariance().fit(X_scaled) mahalanobis_kmeans KMeans(n_clusters3, random_state42) mahalanobis_kmeans.fit(cov.mahalanobis(X_scaled))8.3 确定K值的新方法贝叶斯信息准则(BIC)用于GMM 虽然不直接适用于K-Means但可通过高斯混合模型(GMM)评估from sklearn.mixture import GaussianMixture bics [] for k in range(1, 11): gmm GaussianMixture(n_componentsk, random_state42) gmm.fit(X_scaled) bics.append(gmm.bic(X_scaled)) plt.plot(range(1,11), bics, bo-) plt.xlabel(Number of components) plt.ylabel(BIC score) plt.title(BIC For Optimal K) plt.xticks(range(1,11)) plt.grid(True) plt.show()8.4 处理大规模数据对于大数据集使用MiniBatchKMeansfrom sklearn.cluster import MiniBatchKMeans mbk MiniBatchKMeans(n_clusters3, random_state42) mbk.fit(X_scaled)