【手撕算法】K-Means聚类全解析:从数学推导到图像分割实战

摘要

聚类算法是探索数据内在结构的利器!本文手撕K-Means核心公式,结合Python代码实现与图像分割案例,详解:

✅ 欧氏距离计算 ✅ 簇中心迭代更新 ✅ 肘部法则优化


目录

摘要

目录

一、算法核心思想

二、数学原理详解

[2.1 初始化阶段](#2.1 初始化阶段)

[2.2 迭代更新公式](#2.2 迭代更新公式)

[2.3 收敛条件](#2.3 收敛条件)

三、Python代码实战

[3.1 手写K-Means核心逻辑](#3.1 手写K-Means核心逻辑)

[3.2 图像分割实战案例](#3.2 图像分割实战案例)

四、算法优化技巧

[4.1 K-Means++初始化](#4.1 K-Means++初始化)

[4.2 肘部法则确定K值](#4.2 肘部法则确定K值)

五、常见问题解答

Q1:如何处理不同量纲的特征?

Q2:算法陷入局部最优怎么办?

六、结语与资源

附录:其他聚类算法


一、算法核心思想

K-Means通过最小化簇内平方和 实现聚类,目标函数为:

其中:

  • :预设簇数量

  • :第i个簇的中心点

  • :第i个簇的数据集合


二、数学原理详解

2.1 初始化阶段

随机选择k个初始质心:

2.2 迭代更新公式

  1. 分配样本到最近簇

  2. 更新簇中心

2.3 收敛条件

当簇中心变化量小于阈值时停止:


三、Python代码实战

3.1 手写K-Means核心逻辑

复制代码
import numpy as np

class KMeans:
    def __init__(self, n_clusters=3, max_iter=300):
        self.n_clusters = n_clusters  # 簇数量
        self.max_iter = max_iter      # 最大迭代次数
        
    def fit(self, X):
        # 1. 随机初始化质心
        n_samples, n_features = X.shape
        self.centroids = X[np.random.choice(n_samples, self.n_clusters, replace=False)]
        
        for _ in range(self.max_iter):
            # 2. 计算样本到质心的距离
            distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
            
            # 3. 分配样本到最近簇
            self.labels = np.argmin(distances, axis=0)
            
            # 4. 更新质心
            new_centroids = np.array([X[self.labels == i].mean(axis=0) 
                                    for i in range(self.n_clusters)])
            
            # 5. 检查收敛
            if np.allclose(self.centroids, new_centroids):
                break
            self.centroids = new_centroids
            
        return self

3.2 图像分割实战案例

复制代码
from sklearn.datasets import load_sample_image
import matplotlib.pyplot as plt

# 加载示例图片
china = load_sample_image("china.jpg")
X = china.reshape(-1, 3) / 255.0  # 归一化像素值

# 使用K-Means进行颜色量化
kmeans = KMeans(n_clusters=16).fit(X)
compressed_colors = kmeans.centroids[kmeans.labels].reshape(china.shape)

# 可视化对比
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12,6))
ax1.imshow(china)
ax2.imshow(compressed_colors)
ax1.set_title("原始图像(16.7万色)")
ax2.set_title("压缩后图像(16色)")

四、算法优化技巧

4.1 K-Means++初始化

初始化方法 优点 实现步骤
随机初始化 简单快速 直接随机选取样本
K-Means++ 减少局部最优 按概率分布选择初始点

4.2 肘部法则确定K值

复制代码
# 计算不同K值的SSE
sse = []
for k in range(1, 10):
    kmeans = KMeans(n_clusters=k).fit(X)
    sse.append(np.sum((X - kmeans.centroids[kmeans.labels])**2))

# 绘制肘部曲线
plt.plot(range(1,10), sse, 'bx-')
plt.xlabel('K值')
plt.ylabel('SSE')

五、常见问题解答

Q1:如何处理不同量纲的特征?

解决方案 :使用标准化预处理

Q2:算法陷入局部最优怎么办?

  • 多次随机初始化取最优结果

  • 增加max_iter参数值

  • 改用K-Means++初始化


六、结语与资源

通过本文您已掌握:

🔹 K-Means数学本质 🔹 手写实现关键代码 🔹 图像分割高级应用


附录:其他聚类算法

算法名称 适用场景 核心公式
DBSCAN 任意形状簇 密度可达性
层次聚类 树状结构 距离矩阵合并
GMM 概率分布 EM算法迭代
相关推荐
Navigator_Z8 小时前
LeetCode //C - 1089. Duplicate Zeros
c语言·算法·leetcode
云泽80811 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
wlsh1511 小时前
Go 迭代器
算法
语戚11 小时前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
CS创新实验室12 小时前
从顺序表到动态数组:数据结构的永恒基石与现代语言的优雅封装
数据结构·算法
Black蜡笔小新13 小时前
自动化AI算法训练服务器DLTM训推一体化平台助力农业生产管理实现安全智能化
人工智能·算法·自动化
8Qi814 小时前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
QiLinkOS14 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
松间听晚14 小时前
Agentic RL 环境和代码学习:以HGPO为例
算法
智者知已应修善业15 小时前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机