跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

K-means 聚类算法:原理、步骤与 Python 实现

K-means 是一种基于距离的迭代聚类算法,通过最小化簇内平方误差将数据划分为 K 个簇。核心流程包括随机初始化质心、分配样本点到最近质心、更新质心位置,直至收敛。文章详细解析了算法数学原理、时间复杂度、优缺点及 K 值选择方法(如肘部法),并提供了 scikit-learn 调用与手动实现的 Python 代码示例,帮助读者深入理解其工作机制与工程落地细节。

AiEngineer发布于 2026/2/23更新于 2026/10/2186 浏览
K-means 聚类算法:原理、步骤与 Python 实现

K-means 聚类算法详解

K-means 是一种基于距离的迭代聚类算法,旨在将数据集划分为 $K$ 个簇。其核心目标是最小化簇内点到簇中心的距离总和。下面我们从底层原理、算法步骤、数学基础、参数选择到代码实现进行系统解析。

1. 核心思想

K-means 的目标是将数据集划分为 $K$ 个簇(Clusters),使得每个数据点属于距离最近的簇中心。通过反复调整簇中心的位置,算法不断优化簇内的紧密度,从而获得尽量紧凑、彼此分离的簇。

  • 簇(Cluster):K-means 通过最小化簇内距离的平方和,使得数据点在簇内聚集。一个簇是数据点的集合,这些点在某种意义上'彼此相似'。
  • 簇中心(Centroid):簇中心是簇中所有点的平均值,表示簇的中心位置。
  • 迭代优化:K-means 通过反复迭代,调整簇的分配,使得簇内数据点与质心的距离尽可能小,逐步收敛。

2. 工作流程

K-means 使用'最近距离'来分组,流程分为两个主要步骤:分配(Assignment)和更新(Update)。

  1. 初始化:随机选择 $K$ 个数据点作为初始簇中心(Centroids)。
  2. 分配:对于数据集中的每个点,将它分配到最近的簇中心对应的簇。这里的'距离'通常使用欧氏距离。
  3. 更新:根据当前的簇分配,重新计算每个簇的中心,即计算簇内所有点的均值作为新的簇中心。
  4. 重复:不断重复分配和更新步骤,直到簇中心不再发生变化(收敛)或达到指定的最大迭代次数。
实例演示

假设我们有以下二维数据点,表示顾客的'消费金额'和'访问次数',目标是将这些点分为 $K=2$ 个簇。

数据点编号消费金额(x)访问次数(y)
点 112
点 221
点 345
点 456
点 588

第一步:初始化质心 随机选择两个点作为初始质心(假设选择点 1 和点 5)。

  • C1 = (1, 2)
  • C2 = (8, 8)

第二步:分配簇 计算每个点到两个质心的欧几里得距离:$d = \sqrt{(x_1-x_2)^2 + (y_1-y_2)^2}$。

数据点编号到 C1 的距离到 C2 的距离最近质心分配簇
点 108.49C1簇 1
点 21.418.06C1簇 1
点 34.245.0C1簇 1
点 45.04.24C2簇 2
点 58.490C2簇 2

分配结果:

  • 簇 1:点 1、点 2、点 3
  • 簇 2:点 4、点 5

第三步:重新计算质心 对于每个簇,计算新质心的位置:

  • 簇 1 的质心:(平均 x, 平均 y) = ((1+2+4)/3, (2+1+5)/3) ≈ (2.33, 2.67)
  • 簇 2 的质心:(平均 x, 平均 y) = ((5+8)/2, (6+8)/2) = (6.5, 7.0)

第四步:重复分配与更新 再次计算每个点到新质心的距离,重复上述步骤,直到质心不再变化。最终质心稳定在 C1=(2.33, 2.67), C2=(6.5, 6.0)。

3. 数学基础

K-means 的目标是最小化簇内平方误差和(Within-Cluster Sum of Squares,WCSS),公式如下: $$ J = \sum_{i=1}^{K} \sum_{x \in C_i} ||x - \mu_i||^2 $$ 其中 $||x - \mu_i||^2$ 表示数据点 $x$ 与簇中心 $\mu_i$ 之间的欧氏距离平方。

欧氏距离公式为: $$ d(x, \mu) = \sqrt{\sum_{j=1}^{n} (x_j - \mu_j)^2} $$ 其中 $n$ 是数据的维度。

4. 伪代码

KMeans(X, K):
  1. 随机选择 K 个点作为初始簇中心
  2. 重复以下步骤,直到簇中心不再发生变化:
     a. 分配每个点到最近的簇中心
     b. 重新计算每个簇的中心,作为簇内所有点的均值
  3. 返回最终的簇分配和簇中心

5. 时间复杂度

若迭代次数为 $T$,则总体复杂度为 $O(n \cdot K \cdot T)$。

  • 分配步骤:需要计算每个点到 $K$ 个簇中心的距离,复杂度为 $O(n \cdot K)$。
  • 更新步骤:重新计算每个簇的中心,需要遍历所有点,复杂度也是 $O(n \cdot K)$。

6. 优缺点分析

优点

  • 简单高效:适合大规模数据,处理大数据集时非常高效,具有良好的伸缩性。
  • 收敛速度快:在适合的初始中心选择下,K-means 通常可以较快收敛。

缺点

  • 对初始点敏感:初始簇中心的选择对最终结果影响较大。
  • 形状限制:假设每个簇是凸形且大小相近,不适合发现非凸形状的簇(如'月牙型'数据)。
  • 对噪声敏感:离群点会影响簇的中心计算。
  • 局部最优:不能保证全局最优,只能达到局部最优。

7. K 值的选择

确定最佳的簇数 $K$ 是 K-means 聚类中的一个难点。常用的选择方法有:

  1. 轮廓系数(Silhouette Coefficient):衡量聚类结果的紧密度和分离度。
  2. Calinski-Harabasz 指数:衡量簇内的方差与簇间方差之比。
  3. 肘部法(Elbow Method):绘制不同 K 值下的 WCSS 图,寻找'肘部'点作为最佳 $K$ 值。当 SSE 图像下降幅度最大放缓时,即为最佳 K 值区间。

8. Python 实现

我们可以使用 scikit-learn 中的 KMeans,以及手动实现以便更深入理解。

8.1 使用 scikit-learn
from sklearn.cluster import KMeans
import numpy as np

# 生成示例数据
X = np.array([[1, 2], [2, 2], [3, 3], [8, 7], [8, 8], [25, 80]])

# 初始化并训练模型
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)

# 获取簇标签和簇中心
labels = kmeans.labels_
centroids = kmeans.cluster_centers_

print("Cluster labels:", labels)
print("Centroids:", centroids)
8.2 手动实现

以下是 K-means 的核心逻辑手动实现,有助于理解内部机制:

import numpy as np

def initialize_centroids(X, k):
    indices = np.random.choice(len(X), k, replace=False)
    return X[indices]

def closest_centroid(X, centroids):
    distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
    return np.argmin(distances, axis=1)

def update_centroids(X, labels, k):
    return np.array([X[labels == i].mean(axis=0) for i in range(k)])

def kmeans(X, k, max_iters=100, tol=1e-4):
    centroids = initialize_centroids(X, k)
    for i in range(max_iters):
        labels = closest_centroid(X, centroids)
        new_centroids = update_centroids(X, labels, k)
        if np.all(np.abs(new_centroids - centroids) < tol):
            break
        centroids = new_centroids
    return labels, centroids

# 示例数据
X = np.array([[1, 2], [2, 2], [3, 3], [8, 7], [8, 8], [25, 80]])
labels, centroids = kmeans(X, k=2)
print("最终簇:", labels)
print("质心位置:", centroids)

9. 收敛性与 K-means++

K-means 的收敛性受到初始簇中心选择的影响。K-means++ 是一种改进的初始化方法,优先选择'距离最远'的点作为初始质心,减少陷入局部最优的风险。

K-means++ 步骤

  1. 随机选择一个点作为第一个中心。
  2. 对于每个点,计算其与已选择中心的最小距离 $D(x)$。
  3. 根据 $D(x)$ 的平方来选择下一个聚类中心,距离越远的点被选为新中心的概率越大。
  4. 重复直到选择 $K$ 个聚类中心。

优势

  • 避免随机性问题:确保初始中心分布更均匀。
  • 提高收敛速度:减少迭代次数。
  • 更稳定的结果:尤其在处理复杂结构数据时效果更佳。

10. 总结

K-means 是一种简单、快速的聚类算法,广泛应用于数据聚类任务。通过反复优化簇中心位置,K-means 不断收敛并找到数据的聚类结构。然而,它对初始条件敏感,对簇形状有限制,适合于球形且均匀分布的簇。在实际应用中,可通过结合 K-means++、肘部法和轮廓系数等手段改进其效果。

目录

  1. K-means 聚类算法详解
  2. 1. 核心思想
  3. 2. 工作流程
  4. 实例演示
  5. 3. 数学基础
  6. 4. 伪代码
  7. 5. 时间复杂度
  8. 6. 优缺点分析
  9. 7. K 值的选择
  10. 8. Python 实现
  11. 8.1 使用 scikit-learn
  12. 生成示例数据
  13. 初始化并训练模型
  14. 获取簇标签和簇中心
  15. 8.2 手动实现
  16. 示例数据
  17. 9. 收敛性与 K-means++
  18. 10. 总结

更多推荐文章

查看全部
  • Web Worker:前端多线程的隐形引擎
  • VMware 虚拟机 CentOS 磁盘扩容实战:解决 growpart 报错与 LVM 调整
  • 命令行大模型交互工具 MCPHost 实战指南
  • 智能家居中的边缘计算与隐私保护
  • 双指针算法专题:有效三角形与多数之和
  • RAG(检索增强生成)技术详解:原理、架构与应用
  • AI PPT 生成工具性能评测与选择指南
  • C++ 手写 HTTP 服务器:从请求解析到响应构建
  • AI 大模型时代个人工作站硬件配置与成本分析
  • 无人机烟幕投放策略:如何用代码计算最长遮蔽时间
  • AIGC 个性化与定制化内容生成:技术原理与应用
  • 基于 FPGA 的高精度 TDC 设计
  • Unity 2022 + UXR 3.0:Rokid AR 眼镜轻量级消消乐开发实录
  • 无人机视角山区泥石流与滑坡图像识别数据集
  • Qt 与 Web 混合编程:CEF 与 QCefView 深度解析
  • 二叉树算法实战:美国血统与公共祖先求解
  • Python 项目打包发布完整指南:从构建到上传 PyPI
  • Fanuc 机器人与 PLC 基于 Ethernet/IP 的高速通信实战
  • C#属性与C++成员变量的核心哲学差异对比
  • 选择排序详解:直接、树形与堆排序实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online