K-means聚类模型教程(个人总结版)

K-means聚类是一种广泛应用于数据挖掘和数据分析的无监督学习算法。它通过将数据点分成K个簇(cluster),使得同一簇内的数据点之间的相似度最大,不同簇之间的相似度最小。本文将详细介绍K-means聚类算法的背景、基本原理、具体实现步骤、算法优化方法、优劣势以及应用实例。

一、算法背景

1.1 聚类分析的历史

聚类分析是一种重要的数据分析技术,可以追溯到20世纪50年代。其目的是将数据集分成若干个簇,使得同一个簇内的数据点尽可能相似,不同簇的数据点尽可能不同。聚类分析在许多领域有广泛应用,如模式识别、图像分析、市场研究、生物信息学等。

1.2 K-means算法的提出

K-means算法最早由Hugo Steinhaus在1956年提出,并由Stuart Lloyd在1957年进一步发展。其核心思想是通过迭代优化,使得每个数据点所属的簇中心与其距离最小,从而实现数据的聚类。

二、K-means聚类的基本原理

K-means聚类算法的目标是通过最小化簇内数据点到簇中心(centroid)的平方距离,使得每个簇内的数据点尽可能接近簇中心。具体步骤如下:

  1. 选择K个初始簇中心
  2. 分配数据点到最近的簇中心
  3. 重新计算簇中心:对于每个簇,计算其所有数据点的平均值,作为新的簇中心。
  4. 重复步骤2和步骤3,直到簇中心不再变化或达到预定的迭代次数

三、K-means聚类的具体实现步骤

3.1 数据准备

在开始聚类之前,需要准备数据集。假设我们有一个二维数据集,每个数据点有两个特征。

复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

# 生成示例数据
X, y = make_blobs(n_samples=300, centers=4, random_state=42, cluster_std=0.60)

# 可视化数据
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.show()

3.2 选择初始簇中心

初始化K个簇中心可以随机选择数据点或使用其他初始化方法(如K-means++)。

复制代码
def initialize_centroids(X, k):
    indices = np.random.choice(X.shape[0], k, replace=False)
    return X[indices]

# 初始化簇中心
k = 4
centroids = initialize_centroids(X, k)
print("Initial centroids:\n", centroids)

3.3 分配数据点到最近的簇中心

计算每个数据点到所有簇中心的距离,并将其分配到最近的簇中心。

复制代码
def assign_clusters(X, centroids):
    distances = np.sqrt(((X - centroids[:, np.newaxis])**2).sum(axis=2))
    return np.argmin(distances, axis=0)

# 分配数据点到最近的簇中心
labels = assign_clusters(X, centroids)
print("Initial cluster assignments:\n", labels)

3.4 重新计算簇中心

根据分配结果,计算每个簇的新中心。

复制代码
def compute_centroids(X, labels, k):
    return np.array([X[labels == i].mean(axis=0) for i in range(k)])

# 重新计算簇中心
new_centroids = compute_centroids(X, labels, k)
print("New centroids:\n", new_centroids)

3.5 迭代步骤

重复分配数据点和重新计算簇中心,直到簇中心不再变化或达到最大迭代次数。

复制代码
def kmeans(X, k, max_iters=100):
    centroids = initialize_centroids(X, k)
    for _ in range(max_iters):
        labels = assign_clusters(X, centroids)
        new_centroids = compute_centroids(X, labels, k)
        if np.all(centroids == new_centroids):
            break
        centroids = new_centroids
    return centroids, labels

# 运行K-means聚类
centroids, labels = kmeans(X, k)
print("Final centroids:\n", centroids)

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], s=200, c='red', marker='X')
plt.show()

四、K-means聚类的优化方法

4.1 K-means++初始化

K-means++是一种改进的初始化方法,通过更好地选择初始簇中心,减少了K-means的收敛时间,提高了结果的稳定性。

复制代码
from sklearn.cluster import KMeans

# 使用K-means++初始化
kmeans = KMeans(n_clusters=k, init='k-means++', max_iter=300, n_init=10, random_state=42)
y_kmeans = kmeans.fit_predict(X)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=200, c='red', marker='X')
plt.show()

4.2 确定最佳簇数

使用肘部法或轮廓系数等方法,可以帮助确定数据的最佳簇数。

4.2.1 肘部法

肘部法通过计算不同簇数下的总误差平方和(SSE),选择SSE下降速度减缓的点作为最佳簇数。

复制代码
sse = []
for k in range(1, 11):
    kmeans = KMeans(n_clusters=k, init='k-means++', max_iter=300, n_init=10, random_state=42)
    kmeans.fit(X)
    sse.append(kmeans.inertia_)

# 可视化肘部法
plt.plot(range(1, 11), sse, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('SSE')
plt.show()
4.2.2 轮廓系数

轮廓系数通过计算簇内和簇间的距离,评估不同簇数下的聚类效果。

复制代码
from sklearn.metrics import silhouette_score

silhouette_scores = []
for k in range(2, 11):
    kmeans = KMeans(n_clusters=k, init='k-means++', max_iter=300, n_init=10, random_state=42)
    y_kmeans = kmeans.fit_predict(X)
    silhouette_scores.append(silhouette_score(X, y_kmeans))

# 可视化轮廓系数
plt.plot(range(2, 11), silhouette_scores, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('Silhouette Score')
plt.show()

五、K-means聚类的优劣势

5.1 优势

  1. 简单易懂:K-means算法的基本思想简单直观,易于理解和实现。
  2. 计算效率高:对于大规模数据集,K-means算法的计算效率较高,适合快速聚类。
  3. 结果解释性强:聚类结果易于解释,可以直接通过簇中心和簇内数据点之间的关系进行分析。

5.2 劣势

  1. 对初始值敏感:K-means算法对初始簇中心的选择非常敏感,不同的初始值可能导致不同的聚类结果。
  2. 需要预先确定K值:K-means算法需要预先指定簇的数量K,这在实际应用中可能不容易确定。
  3. 对噪声和异常值敏感:K-means算法对数据中的噪声和异常值较为敏感,可能影响聚类结果的准确性。
  4. 适用数据类型有限:K-means算法主要适用于数值型数据,对于类别型数据或高维稀疏数据的效果不佳。

六、K-means聚类的应用实例

6.1 图像压缩

K-means聚类可以用于图像压缩,将图像像素分配到K个簇,从而减少颜色数量,实现图像压缩。

复制代码
from skimage import io
from sklearn.utils import shuffle

# 加载图像
image = io.imread('path/to/your/image.jpg')
image = np.array(image, dtype=np.float64) / 255

# 将图像像素展开为二维数组
w, h, d = image.shape
image_array = np.reshape(image, (w * h, d))

# 使用K-means进行图像压缩
k = 16
image_array_sample = shuffle(image_array, random_state=42)[:1000]
kmeans = KMeans(n_clusters=k, random_state=42).fit(image_array_sample)
labels = kmeans.predict(image_array)
compressed_image = kmeans.cluster_centers_[labels].reshape(w, h, d)

# 显示压缩后的图像
plt.imshow(compressed_image)
plt.show()

6.2 客户细分

K-means聚类可以用于客户细分,根据客户的购买行为、人口统计数据等,将客户分成不同的簇,帮助企业进行精准营销。

复制代码
import pandas as pd

# 加载客户数据
data = pd.read_csv('path/to/your/customer_data.csv')

# 选择特征进行聚类
X = data[['Annual Income (k$)', 'Spending Score (1-100)']]

# 使用K-means进行客户细分
kmeans = KMeans(n_clusters=5, random_state=42)
y_kmeans = kmeans.fit_predict(X)

# 可视化客户细分结果
plt.scatter(X.iloc[:, 0], X.iloc[:, 1], c=y_kmeans, s=50, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=200, c='red', marker='X')
plt.xlabel('Annual Income (k$)')
plt.ylabel('Spending Score (1-100)')
plt.show()

七、总结

K-means聚类是一种简单高效的无监督学习算法,广泛应用于图像处理、市场营销、客户细分等领域。通过详细介绍K-means聚类的基本原理、具体实现步骤、算法优化方法和应用实例,希望能帮助读者更好地理解和应用这一重要的机器学习技术。在实际应用中,选择合适的簇数和初始化方法,并结合具体问题的需求进行调整和优化,将有助于获得更好的聚类效果。

参考文献

为了深入理解和应用K-means聚类算法,建议参考以下资料:

  1. 《机器学习》 - 周志华
  2. 《模式分类》 - Duda, Hart, Stork
  3. 《数据挖掘:概念与技术》 - Han, Kamber, Pei
  4. K-means++: The Advantages of Careful Seeding - Arthur, Vassilvitskii (2007)
  5. A Comparison of the K-means and K-medoids Algorithms - Park, Jun (2009)

这些资料将提供更深入的理论背景和实践指南,帮助读者进一步掌握K-means聚类算法及其应用。

相关推荐
地平线开发者14 分钟前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考22 分钟前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
冬奇Lab1 小时前
OpenClaw 源码精读(2):Channel & Routing——一条消息如何找到它的 Agent?
人工智能·开源·源码阅读
冬奇Lab1 小时前
一天一个开源项目(第38篇):Claude Code Telegram - 用 Telegram 远程用 Claude Code,随时随地聊项目
人工智能·开源·资讯
格砸2 小时前
从入门到辞职|从ChatGPT到OpenClaw,跟上智能时代的进化
前端·人工智能·后端
可观测性用观测云3 小时前
可观测性 4.0:教系统如何思考
人工智能
sunny8653 小时前
Claude Code 跨会话上下文恢复:从 8 次纠正到 0 次的工程实践
人工智能·开源·github
小笼包包仔3 小时前
OpenClaw 多Agent软件开发最佳实践指南
人工智能
smallyoung3 小时前
AgenticRAG:智能体驱动的检索增强生成
人工智能
_skyming_3 小时前
OpenCode 如何做到结果不做自动质量评估,为什么结果还不错?
人工智能