KMeans 聚类分析怎么做?标准化、选 K 与核对分组结果

用 KMeans 对虚构数值样本分组,先统一尺度,再比较候选 K,并把中心还原到原单位供人工解释。

KMeans 适合把数值相近的样本分成若干组。第一次做聚类时,先解决量纲差异,再比较候选 K,最后查看每组大小和原单位中心;只打印一串 cluster 编号没有完成分析。

适用前提与选 K 的依据

本文用 visits 和 spend 两列虚构数值演示,不对应真实用户画像。标准化可避免金额列因数值范围大而主导距离;是否应让两列权重相同,仍由任务决定。ID、类别编号和缺失值不能不加判断直接当数值特征。

KMeans 聚类分析怎么做?标准化、选 K 与核对分组结果

KMeans 官方接口说明 n_init 控制不同初始中心下重复求解次数,random_state 控制随机性。本例显式设 n_init=10,避免把不同版本的默认行为当成固定条件。

轮廓系数官方说明给出的值通常位于 -1 到 1;越接近 1 表示当前距离定义下组内更紧、组间更分离。只有标签数至少为 2 且少于样本数时才有定义。inertia 是组内平方距离总和,增加 K 通常会降低它,不能单凭最低 inertia 选 K。

准备独立 Python 环境

本文使用 Python 3.13。下面命令适用于 Windows PowerShell,在新建练习目录运行;其他系统用对应的 Python 路径。先用 python –version 确认版本,再创建环境。

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install "scikit-learn==1.9.1" "numpy==2.5.3" "pandas==3.0.6"

以下代码和数据只用于教学。本站于 2026-10-01 在 Windows、Python 3.13.14、scikit-learn 1.9.1、NumPy 2.5.3、pandas 3.0.6 环境运行了本文脚本;这只验证示例能执行和断言通过,不代表真实业务效果。

完整代码:比较 K,再导出分组

保存为 cluster_demo.py,运行 .\.venv\Scripts\python.exe cluster_demo.py。本例比较 K=2、3、4、5 四个候选值。中心用 inverse_transform 还原为 visits 和 spend 的原单位。

import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score

rng = np.random.default_rng(42)
X = np.vstack([rng.normal([10, 100], [0.5, 4], (30, 2)),
               rng.normal([30, 500], [0.5, 4], (30, 2)),
               rng.normal([60, 900], [0.5, 4], (30, 2))])
df = pd.DataFrame(X, columns=["visits", "spend"])
scaler = StandardScaler()
Z = scaler.fit_transform(df)
rows, fitted = [], {}
for k in range(2, 6):
    m = KMeans(n_clusters=k, n_init=10, random_state=42)
    labels = m.fit_predict(Z)
    s = silhouette_score(Z, labels)
    rows.append({"k": k, "silhouette": s, "inertia": m.inertia_})
    fitted[k] = m
table = pd.DataFrame(rows)
best_k = int(table.loc[table["silhouette"].idxmax(), "k"])
model = fitted[best_k]
result = df.assign(cluster=model.labels_)
centres = pd.DataFrame(scaler.inverse_transform(model.cluster_centers_),
                       columns=df.columns)
print(table.to_string(index=False))
print("selected_k", best_k)
print("counts", result["cluster"].value_counts().sort_index().to_dict())
print("centres_in_original_units")
print(centres.round(2).to_string(index=False))
result.to_csv("clusters.csv", index=False, encoding="utf-8-sig")
assert len(result) == 90
assert result["cluster"].nunique() == best_k
assert best_k == 3

怎样检查输出

 k  silhouette   inertia
 2    0.777224 36.496889
 3    0.982390  0.051874
 4    0.811068  0.038251
 5    0.641234  0.030348
selected_k 3
counts {0: 30, 1: 30, 2: 30}
centres_in_original_units
 visits  spend
  29.91 499.26
  59.99 899.68
  10.06 100.03

这是合成数据的实际本地输出:三个预设中心相隔很远,所以这一次比较会选到 3。断言 best_k==3 只用来检查这个教学例子;替换真实数据后不能继续要求一定为 3。

导出的 clusters.csv 必须有 90 行,每行只能有一个 cluster 标签。核对 value_counts 的合计等于样本数,并确认还原后的中心数量等于 selected_k。再查看每组的最小值、最大值和代表记录;中心可能隐藏同一组里差异很大的个体。

换成真实表格并解释组别

用 pd.read_csv 读取表格后,先单独保留 row_id,再选择稳定且有业务含义的数值列拟合。若同一个客户有多条记录,先确定聚类单位是客户还是事件。要给新样本分组,就复用已拟合的 scaler.transform 和 model.predict,不能重新拟合缩放器后还使用旧中心。

例如一个组的中心为较少访问且较低金额,只能描述为当前特征下的低频低额组;不能直接命名“流失用户”,除非有额外事实支持。组0、组1的编号在另一轮训练中可能交换,比较两次结果应按中心或样本对应关系对齐。

失败与边界

KMeans 的分组编号没有优劣顺序,轮廓系数高也不等于业务分组正确。弯曲形状、极不均衡组或大量异常点可能不适合 KMeans 的距离与中心假设。

若出现重复点导致实际簇数小于 K,先看唯一记录数;若 silhouette_score 报标签数量错误,检查实际 labels 的数量;若得分随 K 很接近,不要把微小差异当确定结论,可改变随机种子检查稳定性,并由业务核对每组是否有可解释的用途。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30153.html

赞 (0)
AI小管家的头像AI小管家
DeepSeek 如何生成 Excel 表格?用 Python 写入明细和汇总两个工作表
上一篇 1天前
Python 回归分析怎么做?训练线性模型并检查预测误差
下一篇 1天前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部