宝子们👋,在机器学习的江湖里,K-Means算法那可是响当当的“大侠”,简单又实用。今天咱就一起揭开它的神秘面纱,看看它到底有啥本事😎。
📌K-Means算法原理
想象一下,你有一群小伙伴,他们分布在操场的各个角落。现在呢,你要把这些小伙伴分成几个小组,让每个小组里的小伙伴都离得比较近。K-Means算法干的就是类似的事儿,只不过它处理的是数据点,而不是小伙伴😜。
K-means是无监督学习中最经典的聚类算法,由James MacQueen在1967年提出。它的目标是将n
个数据点自动划分到k
个簇中,使得:
- 同一簇内的数据点尽可能相似(距离小)
- 不同簇间的数据点尽可能不同(距离大)
💡具体步骤
1、随机选“大哥”——随机初始化K个簇中心:从数据中随机选K
个点作为初始质心(簇中心)。就好比在操场上随机选了K个小伙伴作为小组的“领头羊”。比如,我们想把这些小伙伴分成3组,那就随机选3个小朋友作为初始的组长👨👦👦。
2、小弟站队——分配数据点到最近的簇中心:计算每个点到各质心的距离,将其分配到最近质心所在的簇📏
常用欧氏距离:距离 = √[(x₁-x₂)² + (y₁-y₂)²]
👇点击了解更多度量距离
3、大哥挪位——更新簇中心:重新计算每个簇的质心(取簇内所有点的坐标平均值)。
4、重复迭代:重复步骤2~3,直到质心不再变化或达到最大迭代次数⚙️
终止条件:质心移动距离 < 阈值 或 数据点不再切换簇
📌K值选择
K值就是我们要把数据分成的簇的数量,选择合适的K值可是个技术活🤔。
📈肘部法则(Elbow Method)
- 做法:计算不同K值对应的簇内平方和(SSE),绘制K-SSE曲线
- 选点:选择曲线拐点(像手肘弯曲处)对应的K值
-
从图中可以看到,当K值从1增加到3时,WCSS下降得很快;当K值大于3后,WCSS下降得越来越慢。所以,K=3就是一个比较合适的选择😎
# Python代码:肘部法则 sse = [] for k in range(1, 10): kmeans = KMeans(n_clusters=k).fit(data) sse.append(kmeans.inertia_) # inertia_即SSE plt.plot(range(1,10), sse, 'bx-')
🧠领域知识
有时候,我们可以根据实际的业务需求和领域知识来确定K值。比如,在市场细分中,如果我们知道市场可以分为高端、中端和低端三个层次,那么K值就可以设为3🤓。
2. 轮廓系数法(Silhouette Score)
- 原理:衡量样本与自身簇的紧密度 vs 与其他簇的分离度
- 范围:系数∈[-1, 1],越大越好
- 代码:
from sklearn.metrics import silhouette_score scores = [] for k in range(2, 10): labels = KMeans(n_clusters=k).fit_predict(data) scores.append(silhouette_score(data, labels))
3. GAP统计量
- 思想:对比真实数据与随机数据的聚类效果,GAP值最大时K最优
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
肘部法则 | K值范围明显时 | 直观易理解 | 肘点可能不明显 |
轮廓系数 | 簇形状复杂时 | 量化评估聚类质量 | 计算量较大 |
GAP统计量 | 数据分布均匀性未知时 | 减少主观性 | 实现复杂 |
📌K-Means算法用途与场景
🎯用途
- 数据压缩:把大量的数据点聚类成少量的簇,然后用簇中心来代表整个簇的数据,从而减少数据的存储量和计算量😃。
- 图像分割:把图像中的像素点聚类成不同的簇,每个簇代表图像中的一个区域,从而实现图像的分割🖼️。
- 客户细分:根据客户的消费行为、偏好等数据,把客户分成不同的群体,以便进行精准营销🎯。
🌈场景
- 电商行业:电商平台可以根据用户的购买历史、浏览记录等数据,使用K-Means算法对用户进行细分,然后为不同的用户群体推荐个性化的商品🛒。
- 医疗行业:医院可以根据患者的症状、检查结果等数据,对患者进行聚类分析,从而发现潜在的疾病类型和治疗方案🏥。
📌代码示例
下面是一个使用Python和scikit-learn库实现K-Means算法的简单示例😎。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# 生成模拟数据
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
# 绘制原始数据
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title("Original Data")
plt.show()
# 使用K-Means算法进行聚类
kmeans = KMeans(n_clusters=4, random_state=0)
kmeans.fit(X)
y_kmeans = kmeans.predict(X)
# 绘制聚类结果
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75)
plt.title("K-Means Clustering")
plt.show()
📝代码解释
- 生成模拟数据:使用
make_blobs
函数生成300个二维数据点,这些数据点被分成4个簇,每个簇的标准差为0.6。 - 绘制原始数据:使用
plt.scatter
函数绘制原始数据的散点图。 - 使用K-Means算法进行聚类:创建一个
KMeans
对象,设置簇的数量为4,然后调用fit
方法对数据进行聚类,predict
方法预测每个数据点所属的簇。 - 绘制聚类结果:绘制聚类后的散点图,不同簇用不同的颜色表示,簇中心用红色的大圆点表示。
运行这段代码,你就能看到原始数据和聚类后的结果啦👏。
⚖️ 六、优缺点与改进方案
✅ 优点
- 简单高效:逻辑清晰,计算复杂度低(适合大规模数据)
- 易于实现:主流语言均有现成库(Python/R/MATLAB)
- 扩展性强:可处理高维数据(如文本TF-IDF向量)
❌ 缺点
- 需预设K值:实际中最佳K值难以确定
9对初值敏感:不同初始质心可能导致不同结果(改进:K-means++初始化)
- 仅适用球状簇:对非凸簇效果差(如图示)👇
https://img-blog.csdnimg.cn/20200819153758673.gif - 怕噪声/离群点:异常值会拉偏质心(改进:K-medoids算法)
🛠️ 改进算法推荐
算法 | 核心改进 | 适用场景 |
---|---|---|
K-means++ | 优化初始质心选择,分散初始点 | 通用 |
Mini-Batch | 小批量更新,大幅降低内存占用 | 超大规模数据 |
K-medoids | 用实际数据点代替均值作质心 | 含噪声/离群点数据 |
DBSCAN | 基于密度聚类,识别任意形状簇 | 非凸簇、含噪声数据 |
📌总结
K-Means算法是一种简单而强大的聚类算法,它的原理简单易懂,应用场景广泛。不过,K值的选择是一个需要仔细考虑的问题,我们可以结合肘部法则和领域知识来确定合适的K值。希望通过今天的分享,大家对K-Means算法有了更深入的了解😎。
如果你觉得这篇文章对你有帮助,别忘了点赞👍、收藏🌟、转发📤哦!咱们下次再见👋!