不得不学的经典聚类算法K-Means

本文介绍了K-Means聚类算法的基本原理和步骤,包括初始中心点的选择、K值的确定、算法收敛的判断以及处理不收敛的情况。通过牧师-村民模型生动解释了算法迭代过程,并探讨了数据点权重的影响。K-Means虽然简单易实现,但也存在K值选择和局部最优等问题。文章最后提到了实际应用中确定K值的'手肘法'和使用sklearn库实现K-Means的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所谓聚类算法是指将一堆没有标签的数据自动划分成几类的方法,这个方法要保证同一类的数据有相似的特征,比如这样的数据:

img

聚类是无监督算法中最基础的一类,而K-Means Cluster算法又是聚类中最简单实用的一个。

它是一个循环迭代的算法:

  1. 假定我们要对N个样本观测做聚类,要求聚为K类,首先选择K个点作为初始中心点
  2. 接下来,按照距离初始中心点最小的原则,把所有观测分到各中心点所在的类中;
  3. 每类中有若干个观测,计算K个类中所有样本点的均值,作为第二次迭代的K个中心点;
  4. 然后根据这个中心重复第2、3步,直到收敛(中心点不再改变或达到指定的迭代次数),聚类过程结束。

K-Means算法有个很著名的解释,叫做牧师-村民模型:

有四个牧师去郊区布道,一开始牧师们随意选了几个布道点,并且把这几个布道点的情况公告给了郊区所有的居民,于是每个居民到离自己家最近的布道点去听课。
听课之后,大家觉得距离太远了,于是每个牧师统计了一下自己的课上所有的居民的地址,搬到了所有地址的中心地带,并且在海报上更新了自己的布道点的位置。
牧师每一次移动不可能离所有人都更近,有的人发现A牧师移动以后自己还不如去B牧师处听课更近,于是每个居民又去了离自己最近的布道点……
就这样,牧师每个礼拜更新自己的位置,居民根据自己的情况选择布道点,最终稳定了下来。

K-Means算法的特点是类别的个数是人为给定的,如果让机器自己去找类别的个数,它不适用。
K-Means的一个重要的假设是:数据之间的相似度可以使用”距离“度量,距离越小,两个数据相似度越高。当然这个”距离“有很多种,最最常见的是欧式距离(体现数值上的绝对差异),除此之外还有余弦距离(体现方向上的相对差异)

这里看下伪代码大概长这样:

function K-Means(输入数据,中心点个数K)``  ``获取输入数据的维度Dim和个数N``  ``随机生成K个Dim维的点``  ``while``(算法未收敛)``    ``对N个点:计算每个点属于哪一类。``    ``对于K个中心点:``      ``1``,找出所有属于自己这一类的所有数据点``      ``2``,把自己的坐标修改为这些数据点的中心点坐标``  ``end``  ``输出结果:``end

关于K-Means这里有几个关键问题:

  1. 初始中心点怎么确定
  2. K值怎么确定
  3. 如何评价算法是否收敛
  4. 算法不收敛怎么办
  5. 能不能给每个点设置权重

问题1:初始中心点怎么确定

方法有很多,最粗暴的方式就是随便选K个点,然后等待算法在循环中自己慢慢收敛(不过这样有可能找到的是局部最优而不是全局最优)

再譬如先随便选个点作为第1个初始中心C1,接下来计算所有样本点与C1的距离,距离最大的被选为下一个中心C2,直到选完K个中心。这个算法叫做K-Means++,可以理解为K-Means的改进版,它可以能有效地解决初始中心的选取问题,但无法解决离群点问题。

或者初始化的时候,不妨先估计一下数据的中心在哪里,数据的尺度有多大,总的而言还是要多尝试。

问题2:K值怎么确定

首先我们了解一个概念:目标函数。

数据给分成不同的簇,目标是同一个簇中的差异小,不同簇之间的差异大,这个目标怎么用数学语言描述呢?我们一般用误差平方和作为目标函数,记为SSE。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3mrtY8vy-1673366027097)(null)]

其中C表示聚类中心,如果x属于Ci这个簇,则计算两者的欧式距离,将所有样本点到其中心点距离算出来,并加总,就是K-Means的目标函数。实现同一个簇中的样本差异小,就是最小化SSE。


容易知道,K设置得越大,样本划分得就越细,每个簇的聚合程度就越高。极限情况下,K足够大,每个点都是一类,当然这样分类就没有意义了。

确定K值有一个主流方法叫“手肘法”。

我们从一个比较小的K,譬如K=2开始尝试

  • K每增大一个单位,就会大幅增加每个簇的聚合程度,这时SSE的下降幅度会很大;
  • 到了某个阶段,再增加K所得到的聚合程度回报会迅速变小,SSE的下降幅度也会减小;
  • K继续增大,SSE的变化会趋于平缓。

大概这个感觉:

img

因为SSE和K的关系图就像是手肘的形状,而肘部对应的K值就被认为是数据的真实聚类数。这里我们可以取4作为K的值。

当然,很多时候聚类的簇数量是比较主观的,下图所示,我们聚成3类或聚成2类都可。

img

问题3、如何评价算法是否收敛

看代价函数**
**

问题4、算法不收敛怎么办

我也不懂(-。-)

问题5、能不能给每个点设置权重

先回答:可以。

首先明确一个问题:为什么要设置权重?

设置权重一般发生在两种情况下:
1,数据集中有大量的重复点,而且数据量比较大计算非常的烧CPU;
2,数据点之间的重要程度不一样,某些点我们认为更重要,就可以为其分配高权重来影响聚类结果。

总结

K-Means优点在于原理简单,容易实现,聚类效果好。

当然,也有一些缺点:

  • K值、初始点的选取不好确定;
  • 得到的结果只是局部最优;
  • 受离群值影响大。

附代码实现

因为K-Means思路很明确,自己手撸也是可以的,不过也有很成熟的现成方案,比如sklearn中就有算法包,直接调即可

# 导入算法包
import pandas as pd
from sklearn.cluster import KMeans
# 读文件数据
data=pd.read_excel("kmeans.xlsx")
# 瞅一眼数据
data
# 设定训练集
train_x=data.iloc[0:10,1:4]
# 建模预测
kmeans = KMeans(n_clusters=3)#n_clusters=3即指定划分为3个类型
kmeans.fit(train_x)#模型训练
y_kmeans = kmeans.predict(train_x)#模型预测
# 查看聚类结果
y_kmeans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值