在机器学习中并不是所有任务都带有“标准答案”。有一类问题的目标不是根据已知标签去预测结果而是直接从数据本身出发寻找样本之间潜在的结构与分组。聚类Clustering正是这种无监督学习任务的典型代表。其中的 K 均值聚类K-Means Clustering通常把样本划分为若干组并通过最小化组内平方和准则来完成聚类。一、K 均值聚类的基本思想K 均值的核心思想是用 K 个中心点去代表数据中的 K 个簇并让每个样本归属于距离自己最近的那个中心。从直观上看K 均值完成的是这样一件事• 先假设数据中存在 K 个簇• 为这 K 个簇各设一个中心• 把每个样本分配给最近的中心• 再根据分配结果更新各簇中心• 不断重复直到中心基本稳定图 1K 均值聚类的基本迭代过程这样做的目标是让同一簇内部的样本尽量彼此接近而不同簇之间尽量相互分离。这说明K 均值聚类并不是在学习一个“输入到输出”的监督映射而是在寻找一种更紧凑、更有组织的数据划分方式。二、K 均值聚类的数学表达1、簇中心的含义设数据集包含 n 个样本每个样本记为假设我们希望把它们划分为 K 个簇每个簇记为并为每个簇定义一个中心这里的μⱼ就是第 j 个簇的中心通常也称为质心centroid。这些中心一般并不是原始样本中的某个点而是处在相同特征空间中的均值点。2、优化目标K 均值的目标是让每个样本到其所属簇中心的平方距离之和尽可能小。常见写法为这就是 K 均值聚类最核心的目标函数也常被称为簇内平方和准则。它的含义非常直观• 如果样本离所属中心越近这个值就越小• 如果同一簇内部样本越紧凑这个值也越小因此最小化这个目标就等价于追求“簇内更紧凑”。3、距离度量K 均值通常以欧氏距离为基础。对于两个样本 x 和 z若它们都是 p 维向量则欧氏距离可写为由于 K 均值目标函数本身使用的是平方距离因此它对特征尺度非常敏感某个量纲较大的特征可能在距离计算中占主导地位。这也是为什么在很多实际任务中使用 K 均值前常常需要先做标准化。三、K 均值聚类如何工作1、初始化K 均值并不会自动知道“哪 K 个位置最适合做中心”因此一开始必须先给出初始中心。Scikit-learn 中 KMeans 的 init 参数支持多种初始化方式最常见的是• k-means• random其中k-means 会以一种更有策略的方式选择初始中心以加快收敛并减少糟糕初始化带来的影响它也是当前默认初始化方式。2、分配步骤给定一组中心后算法会把每个样本分配给距离最近的那个中心。这一步的含义是先固定中心再重新决定“谁属于哪个簇”。3、更新步骤当所有样本都完成分配后每个簇都会重新计算自己的中心。新的中心通常是该簇内所有样本的均值因此才叫“K 均值”。4、迭代直到稳定分配和更新会不断重复直到中心变化足够小或者达到最大迭代次数。KMeans 的 max_iter 默认值为 300tol 用于判断相邻两次中心变化是否足够小从而宣布收敛。这说明K 均值本质上是一种迭代优化算法在固定簇分配时更新中心在固定中心时更新簇分配二者交替进行。四、K 的含义与初始化问题1、K 表示簇的数量参数 K 表示我们希望把数据划分成多少个簇。这意味着K 均值的一个前提是聚类前需要先给定簇数。Scikit-learn 中对应的参数是 n_clusters默认值为 8。如果 K 设得太小不同结构可能会被强行合并如果 K 设得太大原本属于同一结构的数据又可能被过度拆分。图 2簇数选择与初始化对聚类结果的影响2、初始化会影响最终结果K 均值并不保证找到全局最优解它常常会停在局部最优附近。这意味着不同的初始化方式可能会得到不同结果。Scikit-learn 的 n_init 参数就用于控制用不同初始化重复运行算法的次数并最终选择 inertia 最小的一次结果。比如当前稳定版中n_initauto 是默认值当 initk-means 时默认运行 1 次当 initrandom 时默认运行 10 次。因此初始化并不是无关紧要的细节而是 K 均值聚类效果的重要影响因素。五、聚类结果如何解释1、簇标签的含义K 均值输出的 labels_ 表示每个样本所属的簇编号。需要特别注意的是这些簇编号本身没有固定语义顺序。例如标签 0、1、2 并不表示“大小递增”或“重要程度递增”它们只是算法内部给不同簇分配的编号。2、簇中心的含义训练完成后cluster_centers_ 给出各簇中心的坐标。这些中心可以帮助我们理解每个簇的大致位置与特征均值特征。例如• 某个簇中心在“收入高、消费高”区域可能对应高价值客户群• 某个簇中心在“收入低、消费低”区域可能对应另一类群体3、inertia 的意义KMeans 训练后还会给出 inertia_ 属性它表示所有样本到其最近簇中心的平方距离之和。这意味着inertia 越小说明样本整体上离各自中心越近。但 inertia 小并不自动意味着“聚类就一定有意义”当 K 增大时inertia 通常会继续下降。因此inertia 是一个重要的内部指标但不能机械地孤立解读。六、Python 实现二维 K 均值聚类示例下面先用 make_blobs 生成一个二维样本集并用 KMeans 完成聚类。Scikit-learn 把 KMeans 描述为对数据进行 K 组划分、并最小化 inertia 的方法make_blobs 则常用于生成聚类示例数据。import matplotlib.pyplot as plt # 绘图库用于可视化聚类结果from sklearn.cluster import KMeans # KMeans聚类算法from sklearn.datasets import make_blobs # 生成各向同性高斯团块聚簇数据的工具 # 根据操作系统选择中文字体二选一取消注释对应行plt.rcParams[font.sans-serif] [Microsoft YaHei] # Windows# plt.rcParams[font.sans-serif] [Songti SC] # macOSplt.rcParams[axes.unicode_minus] False # 解决负号 - 显示为方块的问题使负号正常显示 # 1. 生成二维聚类数据# make_blobs 生成各向同性的高斯分布团块常用于聚类算法的演示# 参数解释# n_samples300: 生成300个样本点# centers4: 数据真实的中心数量为4即数据会围绕4个中心点分布# cluster_std0.80: 每个团块的标准差为0.80控制簇的分散程度值越大簇越分散# random_state42: 随机种子保证每次生成的数据相同便于复现# 返回值X 是特征数组形状 300×2_ 是真实标签此处用不到故用下划线忽略X, _ make_blobs( n_samples300, centers4, cluster_std0.80, random_state42) # 2. 创建 KMeans 模型# KMeans 参数解释# n_clusters4: 指定要聚类的簇的数量为4与真实中心数一致# initk-means: 使用 k-means 初始化方法能更快收敛并得到更优的聚类结果默认# n_initauto: 自动选择初始化次数默认10次取其中 inertia 最小的作为最终模型# random_state42: 固定随机种子确保每次运行结果可复现model KMeans( n_clusters4, initk-means, n_initauto, random_state42) # 3. 训练模型并获得聚类标签# fit_predict 方法等价于先调用 fit() 再调用 predict()返回每个样本所属簇的标签0,1,2,3labels model.fit_predict(X) # 4. 查看聚类中心与 inertia# cluster_centers_ 属性每个簇的中心坐标形状为 n_clusters × n_features此处为 4×2print(聚类中心\n, model.cluster_centers_)# inertia_ 属性所有样本到其最近簇中心的距离平方和Sum of Squared Distances用于评估聚类效果值越小越好print(inertia_ , model.inertia_) # 5. 可视化plt.figure(figsize(8, 5)) # 创建画布大小为宽8英寸、高5英寸 # 绘制散点图X 的第一列作为 x 坐标第二列作为 y 坐标clabels 表示按聚类标签着色plt.scatter(X[:, 0], X[:, 1], clabels) # 在相同坐标系中绘制聚类中心plt.scatter( model.cluster_centers_[:, 0], # 所有中心的 x 坐标 model.cluster_centers_[:, 1], # 所有中心的 y 坐标 markerX, # 标记形状为叉形与普通样本点区分 s200, # 标记大小面积200 表示较大 label聚类中心 # 图例标签) # 添加图表标题和坐标轴标签plt.title(K 均值聚类示例)plt.xlabel(特征 1)plt.ylabel(特征 2)plt.legend() # 显示图例此时会显示“聚类中心”plt.show() # 展示图形会弹出窗口或显示在 Jupyter 中这段代码展示了 K 均值聚类的基本工作流1、生成或加载数据2、创建 KMeans 模型3、用 fit_predict 完成训练与标签输出4、查看 cluster_centers_ 与 inertia_4、用散点图观察聚类结果这里的 fit_predict 会先拟合模型再直接返回聚类标签这是 KMeans 提供的常用便捷方法。七、Python 实现用 inertia 观察不同 K 的变化下面再给出一个简单示例用不同的 K 重复训练并观察 inertia_ 的变化趋势。from sklearn.cluster import KMeansfrom sklearn.datasets import make_blobs # 1. 生成数据X, _ make_blobs( n_samples400, centers4, cluster_std0.90, random_state42) # 2. 比较不同 K 下的 inertiafor k in range(1, 8): model KMeans( n_clustersk, initk-means, n_initauto, random_state42 ) model.fit(X) print(fK {k}, inertia {model.inertia_:.2f})这段代码常用于帮助理解一个基本现象随着 K 增大inertia 通常会不断减小因为簇数越多每个样本更容易靠近某个中心。但这并不意味着 “K 越大越好”因为聚类的目标并不是把每个样本都单独变成一个簇而是在紧凑性与可解释性之间寻找较合适的划分。八、K 均值适用场景与主要局限1、适用场景K 均值较适合以下情况• 希望把样本划分为若干相对紧凑的簇• 特征空间中的距离具有明确意义• 簇大致接近“球形”或“均值可代表”• 数据规模中等且希望使用一个直观、快速的聚类基线模型• 需要一个简单方法来进行客户分群、样本分组或原型发现Scikit-learn 的 KMeans 对大样本数具有较好的可扩展性并已广泛应用于许多领域。2、主要局限K 均值虽然常用但也并不是万能方法• 需要预先指定 K聚类前必须先给定簇数• 对初始化敏感不同初始中心可能得到不同局部解• 对特征尺度敏感未标准化时大尺度特征可能主导结果• 不适合任意形状的簇若真实簇呈细长、环状或密度差异很大K 均值往往表现不好• 对异常值较敏感少量离群点可能显著拉动中心位置因此K 均值最适合的是“簇中心有代表性、距离度量合理、簇形状相对规则”的任务如果数据结构明显更复杂往往需要考虑 DBSCAN、层次聚类或高斯混合模型等其他方法。 小结K 均值聚类通过“分配样本—更新中心”的迭代过程寻找使簇内平方和尽量小的样本划分。它直观、高效是理解无监督学习、距离度量与簇结构的重要入口。“点赞有美意赞赏是鼓励”