K-means聚类最优k值的选取

部署运行你感兴趣的模型镜像

       最近做了一个数据挖掘的项目,挖掘过程中用到了K-means聚类方法,但是由于根据行业经验确定的聚类数过多并且并不一定是我们获取到数据的真实聚类数,所以,我们希望能从数据自身出发去确定真实的聚类数,也就是对数据而言的最佳聚类数。为此,我查阅了大量资料和博客资源,总结出主流的确定聚类数k的方法有以下两类。

1.手肘法

1.1 理论

手肘法的核心指标是SSE(sum of the squared errors,误差平方和),


其中,Ci是第i个簇,p是Ci中的样本点,mi是Ci的质心(Ci中所有样本的均值),SSE是所有样本的聚类误差,代表了聚类效果的好坏。

       手肘法的核心思想是:随着聚类数k的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE自然会逐渐变小。并且,当k小于真实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,也就是说SSE和k的关系图是一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数。当然,这也是该方法被称为手肘法的原因。

1.2 实践

我们对预处理后数据.csv 中的数据利用手肘法选取最佳聚类数k。具体做法是让k从1开始取值直到取到你认为合适的上限(一般来说这个上限不会太大,这里我们选取上限为8),对每一个k值进行聚类并且记下对于的SSE,然后画出k和SSE的关系图(毫无疑问是手肘形),最后选取肘部对应的k作为我们的最佳聚类数。python实现如下:

import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

df_features = pd.read_csv(r'C:\预处理后数据.csv',encoding='gbk') # 读入数据
'利用SSE选择k'
SSE = []  # 存放每次结果的误差平方和
for k in range(1,9):
    estimator = KMeans(n_clusters=k)  # 构造聚类器
    estimator.fit(df_features[['R','F','M']])
    SSE.append(estimator.inertia_)
X = range(1,9)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X,SSE,'o-')
plt.show()
画出的k与SSE的关系图如下:


显然,肘部对于的k值为4,故对于这个数据集的聚类而言,最佳聚类数应该选4

2. 轮廓系数法

2.1 理论

该方法的核心指标是轮廓系数(Silhouette Coefficient),某个样本点Xi的轮廓系数定义如下:

                                                           

其中,a是Xi与同簇的其他样本的平均距离,称为凝聚度,b是Xi与最近簇中所有样本的平均距离,称为分离度。而最近簇的定义是

                                                    

其中p是某个簇Ck中的样本。事实上,简单点讲,就是用Xi到某个簇所有样本平均距离作为衡量该点到该簇的距离后,选择离Xi最近的一个簇作为最近簇。

       求出所有样本的轮廓系数后再求平均值就得到了平均轮廓系数。平均轮廓系数的取值范围为[-1,1],且簇内样本的距离越近,簇间样本距离越远,平均轮廓系数越大,聚类效果越好。那么,很自然地,平均轮廓系数最大的k便是最佳聚类数。

2.2 实践

我们同样使用2.1中的数据集,同样考虑k等于1到8的情况,对于每个k值进行聚类并且求出相应的轮廓系数,然后做出k和轮廓系数的关系图,选取轮廓系数取值最大的k作为我们最佳聚类系数,python实现如下:

import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt

df_features = pd.read_csv(r'C:\Users\61087\Desktop\项目\爬虫数据\预处理后数据.csv',encoding='gbk')
Scores = []  # 存放轮廓系数
for k in range(2,9):
    estimator = KMeans(n_clusters=k)  # 构造聚类器
    estimator.fit(df_features[['R','F','M']])
    Scores.append(silhouette_score(df_features[['R','F','M']],estimator.labels_,metric='euclidean'))
X = range(2,9)
plt.xlabel('k')
plt.ylabel('轮廓系数')
plt.plot(X,Scores,'o-')
plt.show()

得到聚类数k与轮廓系数的关系图:

                            

可以看到,轮廓系数最大的k值是2,这表示我们的最佳聚类数为2。但是,值得注意的是,从k和SSE的手肘图可以看出,当k取2时,SSE还非常大,所以这是一个不太合理的聚类数,我们退而求其次,考虑轮廓系数第二大的k值4,这时候SSE已经处于一个较低的水平,因此最佳聚类系数应该取4而不是2。

       但是,讲道理,k=2时轮廓系数最大,聚类效果应该非常好,那为什么SSE会这么大呢?在我看来,原因在于轮廓系数考虑了分离度b,也就是样本与最近簇中所有样本的平均距离。为什么这么说,因为从定义上看,轮廓系数大,不一定是凝聚度a(样本与同簇的其他样本的平均距离)小,而可能是b和a都很大的情况下b相对a大得多,这么一来,a是有可能取得比较大的。a一大,样本与同簇的其他样本的平均距离就大,簇的紧凑程度就弱,那么簇内样本离质心的距离也大,从而导致SSE较大。所以,虽然轮廓系数引入了分离度b而限制了聚类划分的程度,但是同样会引来最优结果的SSE比较大的问题,这一点也是值得注意的。

总结

从以上两个例子可以看出,轮廓系数法确定出的最优k值不一定是最优的,有时候还需要根据SSE去辅助选取,这样一来相对手肘法就显得有点累赘。因此,如果没有特殊情况的话,我还是建议首先考虑用手肘法。


您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

K-means聚类分析中广泛使用,但其需要预先指定聚类数量 $ K $,而如何选择最佳的 $ K $ 是一个关键问题。以下是几种常用的方: ### 1. 肘部则(Elbow Method) 肘部则是一种直观的方,通过计算不同 $ K $ 下的误差平方和(SSE, Sum of Squared Errors),并绘制 $ K $ 与 SSE 的关系图。随着 $ K $ 的增加,SSE 会逐渐减少,但当 $ K $ 增加到某个后,SSE 的下降幅度会显著减小。这个转折点被称为“肘部”,通常被视为最佳 $ K $ 的选择点[^3]。 ```python 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, random_state=42) # 计算不同 K 的 SSE sse = [] k_range = range(1, 10) for k in k_range: kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(X) sse.append(kmeans.inertia_) # 绘制肘部图 plt.plot(k_range, sse, marker='o') plt.xlabel('Number of clusters (K)') plt.ylabel('Sum of Squared Errors (SSE)') plt.title('Elbow Method for Optimal K') plt.grid(True) plt.show() ``` ### 2. 轮廓系数(Silhouette Coefficient) 轮廓系数是一种衡量聚类结果质量的指标,其范围为 $[-1, 1]$。越接近 1,表示样本越接近其所属簇的中心,且远离其他簇;越接近 -1,则表示样本可能被分配到了错误的簇。通过计算不同 $ K $ 下的平均轮廓系数,并选择轮廓系数最大的 $ K $ 作为最佳聚类数。 ```python from sklearn.metrics import silhouette_score # 计算不同 K 轮廓系数 silhouette_scores = [] k_range = range(2, 10) # 轮廓系数不适用于 K=1 for k in k_range: kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(X) labels = kmeans.predict(X) score = silhouette_score(X, labels) silhouette_scores.append(score) # 绘制轮廓系数图 plt.plot(k_range, silhouette_scores, marker='o') plt.xlabel('Number of clusters (K)') plt.ylabel('Silhouette Score') plt.title('Silhouette Analysis for Optimal K') plt.grid(True) plt.show() ``` ### 3. 信息准则(AIC/BIC) 基于模型的聚类(如高斯混合模型)可以利用 Akaike 信息准则(AIC)或贝叶斯信息准则(BIC)来确定最佳聚类数。虽然 K-means 不直接提供这些指标,但可以通过拟合高斯混合模型并计算 AIC/BIC 来间接选择最佳 $ K $。 ### 4. Gap Statistic Gap Statistic 是一种基于统计学的方,通过比较实际数据的聚类结果与随机数据的聚类结果来确定最佳 $ K $ 。Gap Statistic 计算每个 $ K $ 下的“Gap ”,选择 Gap 最大的 $ K $ 作为最佳聚类数。 ### 5. 领域知识与业务需求 在某些情况下,最佳 $ K $ 可能需要结合领域知识或具体的业务需求来确定。例如,在市场细分中,$ K $ 可能由业务目标决定。 ### 总结 选择最佳 $ K $ 通常需要结合多种方,并根据具体应用场景进行权衡。肘部则和轮廓系数是较为常用的直观方,而 Gap Statistic 和信息准则则提供了更严谨的统计依据。
评论 33
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值