用KMeans需调参:标准化、n_init≥20、固定random_state;选K优先看轮廓系数(>0.5合理),辅以Calinski-Harabasz分数;空簇因初值差或K过大,需离群点检测;非凸/多尺度数据应换DBSCAN等算法。

怎么用 sklearn.cluster.KMeans 快速跑通聚类
直接调 KMeans 很容易出错,不是结果全一样,就是报 ConvergenceWarning。核心问题在于默认参数太“懒”:n_init=10 太低,max_iter=300 在高维数据里常不够,init='k-means++' 虽好但对异常值敏感。
- 必须设
n_init=20以上,避免陷入局部极小——KMeans是贪心算法,只跑一次大概率不准 - 如果数据量大(行 > 10万)或特征 > 50,先用
StandardScaler标准化,否则欧氏距离被量纲大的特征主导 - 别信默认的
random_state=None,固定random_state=42才能复现结果,调试时省半小时 - 示例:
from sklearn.cluster import KMeans<br>from sklearn.preprocessing import StandardScaler<br><br>scaler = StandardScaler()<br>X_scaled = scaler.fit_transform(X)<br>kmeans = KMeans(n_clusters=3, n_init=20, random_state=42)<br>labels = kmeans.fit_predict(X_scaled)
怎么判断 K 值选得对不对
肘部法(Elbow Method)和轮廓系数(Silhouette Score)经常打架,不是因为方法错,而是它们优化目标不同:肘部法看簇内误差平方和(inertia_),轮廓系数看簇间分离度。实际中,inertia_ 永远随 K 增大而下降,根本没“肘”,这时候硬找拐点就是在拟合噪声。
- 优先看
silhouette_score,它对 K 敏感且有明确范围(-1 到 1),>0.5 算合理,>0.7 算不错;但注意:当簇大小极度不均时,它会高估 K - 用
calinski_harabasz_score作交叉验证,它对簇间离散度更鲁棒,和轮廓系数趋势相反时,往往说明数据本身不适合 K-Means - 画图别只画一条线——把
inertia_、silhouette_score、calinski_harabasz_score三条曲线叠在一起,K=4 和 K=5 分数接近,就别硬选 K=5 - 代码片段:
from sklearn.metrics import silhouette_score, calinski_harabasz_score<br><br>sil_scores = []<br>ch_scores = []<br>for k in range(2, 10):<br> km = KMeans(n_clusters=k, n_init=15, random_state=42)<br> labels = km.fit_predict(X_scaled)<br> sil_scores.append(silhouette_score(X_scaled, labels))<br> ch_scores.append(calinski_harabasz_score(X_scaled, labels))
为什么聚类结果每次都不一样,还老出空簇
KMeans 初始化本质是随机选点,如果某次初始中心恰好落在稀疏区,后续迭代可能把整个簇“吸”过去,最后某个中心周围没点可分,就触发 EmptyClusterError(虽然 sklearn 默认静默忽略,但 labels 里会出现 -1 或错位)。
- 空簇最常见于 K 设得太大,或数据有强偏态分布(比如 90% 样本挤在左下角),这时改用
init='k-means++'并提高n_init是治标,治本得先做离群点检测(比如用IsolationForest)再剔除 - 如果必须保留所有样本,加个兜底:
KMeans(..., n_init=30).fit(X_scaled)后检查km.n_iter_,小于 50 就重跑——说明收敛太快,大概率卡在坏初值上 - 别用
predict对新样本聚类,要用fit_predict重新算;predict只适用于训练时见过的簇结构,新数据分布一变就失效
什么情况下 K-Means 会彻底失效
不是所有“看起来能分组”的数据都适合 K-Means。它隐含三个强假设:簇是凸形的、各向同性的、大小相近。一旦违背,比如环形分布、长条形簇、密度差异大的多尺度结构,KMeans 会强行切成圆饼,结果毫无业务意义。
立即学习“Python免费学习笔记(深入)”;
- 先画
PCA降维到 2D 散点图,肉眼观察形状——如果点明显绕圈、拉丝、或一堆密一堆疏,立刻停手,换DBSCAN或AgglomerativeClustering - 特征相关性高(比如
price和area相关系数 > 0.8)时,K-Means 的欧氏距离会重复加权,必须先用 PCA 或TruncatedSVD降维 - 类别型变量(如
city,product_type)不能直接 one-hot 后喂给KMeans,距离失去含义;得用Gower distance+ 层次聚类,或者先做嵌入(CategoryEncoders)
真正麻烦的从来不是调参,而是确认问题本身是否属于 K-Means 的解题范围——这点在探索性分析阶段最容易被跳过。









