kmeans 最佳聚类个数 | 轮廓系数(越大越好)

轮廓系数越大,表示簇内实例之间紧凑,簇间距离大,这正是聚类的标准概念。

  • 簇内的样本应该尽可能相似。
  • 不同簇之间应该尽可能不相似。

目的:鸢尾花数据进行kmeans聚类,最佳聚类个数是多少?

plot(iris[,1:4], col=iris$Species)

1. 标准化很重要

假设已经知道最佳是3类,

  • 使用原始数据做kmeans,和原始标签不一致的很多。
  • 如果做了标准化,kmeans的分类结果和原始标签一模一样。

(1). raw dat (错了好多)

复制代码
dat=iris[, 1:4]
rownames(dat) = paste0("obs", 1:nrow(dat))
dat[1:3,]

km_model <- kmeans( dat, centers = 3)

# 获取分类结果
predictions <- km_model$cluster
table(predictions)

dat$origin=iris$Species
dat$pred=predictions

table(dat$origin, dat$pred)
#           1  2  3
#setosa      0  0 50
#versicolor 48  2  0
#virginica  14 36  0

plot(dat$Sepal.Length, dat$Sepal.Width, col=dat$origin, pch=19)
plot(dat$Sepal.Length, dat$Sepal.Width, col=dat$pred, pch=19)

(2). normalized dat (几乎全对)

复制代码
dat=iris[, 1:4]
rownames(dat) = paste0("obs", 1:nrow(dat))
dat[1:3,]

dat=apply(dat, 1, function(x){
  x/sum(x) * 1e4
}) |> t()  |> as.data.frame()
head(dat)

# 行作为观测值
km_model <- kmeans( dat, centers = 3)

# 获取分类结果
predictions <- km_model$cluster
table(predictions)

dat$origin=iris$Species
dat$pred=predictions

table(dat$origin, dat$pred)
#             1  2  3
#setosa     50  0  0
#versicolor  0 45  5
#virginica   0  0 50

2. 最佳分类数

(0) 预处理

复制代码
dat=iris[, 1:4]
rownames(dat) = paste0("obs", 1:nrow(dat))
dat[1:3,]

dat=apply(dat, 1, function(x){
  x/sum(x) * 1e4
}) |> t()  |> as.data.frame()
head(dat)

(1) factoextra - silhouette: n=2

复制代码
library(factoextra)
tmp = factoextra::fviz_nbclust( dat, kmeans, method = "silhouette")
#str(tmp)
tmp #图

# fviz_nbclust(dat, kmeans, method = "silhouette", k.max = 20)

(2) 碎石图: n=2

复制代码
# 在一个循环中进行15次的kmeans聚类分析
{
totalwSS=vector(mode = "numeric", 15)
for (i in 1:15){
  t1= kmeans(dat, i)
  totalwSS[i] <- t1$tot.withinss
}
# 聚类碎石图 - 使用plot函数绘制total_wss与no-of-clusters的数值。
plot(x=1:15,                         # x= 类数量, 1 to 15
     totalwSS,                      #每个类的total_wss值
     col="navy", lwd=2,
     type="b"                       # 绘制两点,并将它们连接起来
)
}

(3) silhouette 画图: n=2?

逐个画:

复制代码
# 逐个画轮廓系数
library(cluster)
dis = dist(dat) #行之间的距离
#
n=3
kclu <- kmeans(dat, centers = 3, nstart=25)
kclu.sil=sortSilhouette( silhouette(kclu$cluster, dist = dis) )
plot(kclu.sil, 
     col =1:n, #c("red", "orange", "blue"), 
     main="")

#
n=4
#library(cluster)
#dis = dist(dat) #行之间的距离
kclu <- kmeans(dat, centers = n, nstart=25)
kclu.sil=sortSilhouette( silhouette(kclu$cluster, dist = dis) )
plot(kclu.sil, 
     col =1:n, # c("red", "orange", "blue"), 
     main="")
#
#
n=8
#library(cluster)
#dis = dist(dat) #行之间的距离
kclu <- kmeans(dat, centers = n, nstart=25)
kclu.sil=sortSilhouette( silhouette(kclu$cluster, dist = dis) )
plot(kclu.sil, 
     col =1:n, # c("red", "orange", "blue"), 
     main="")
#

批量计算:

复制代码
silhouette_score <- function(k){
  km <- kmeans(dat, centers = k, nstart=25)
  ss <- silhouette(km$cluster, dist(dat))
  mean(ss[, 3])
}
k <- 2:15
avg_sil <- sapply(k, silhouette_score)
plot(k, avg_sil, 
     type='b',
     xlab='Number of clusters', ylab='Average Silhouette Scores', 
     frame=FALSE)

最大是2,其次是3类。

根据本文图1,忽略颜色,只看数值分布,确实最佳是2类。

用标准化后的数据呢?
plot(dat, col=iris$Species, main="Normalized data")

plot(dat,main="Normalized data")

结论不变:如果忽略颜色,依旧是很清晰的2类。

(4) pam 是一种更稳定的 kmeans

Partitioning Around Medoids:

Partitioning (clustering) of the data into k clusters "around medoids", a more robust version of K-means.

复制代码
# 最佳分类数:
Ks=sapply(2:15, function(i){
  summary(silhouette(pam(dat, k=i)))$avg.width
})
plot(2:15,Ks,xlab="k",ylab="av. silhouette",type="b", pch=19)


效果:
t1=pam(dat, k=3)
> table(t1$clustering, iris$Species)   
    setosa versicolor virginica
  1     50          0         0
  2      0         44         0
  3      0          6        50
还是有几个错的。

End

相关推荐
有Li7 天前
PTCMIL:基于提示 token 聚类的全切片图像多实例学习分析文献速递/多模态医学影像最新进展
论文阅读·学习·数据挖掘·聚类·文献·医学生
星川皆无恙7 天前
大数据k-means聚类算法:基于k-means聚类算法+NLP微博舆情数据爬虫可视化分析推荐系统(新版)
大数据·人工智能·爬虫·算法·机器学习·自然语言处理·kmeans
deephub8 天前
Flash-KMeans:快速且内存高效的精确 K-Means,可在单张 GPU 进行亿级数据的聚类
人工智能·机器学习·kmeans·聚类·rag
MartinYeung59 天前
[论文学习]LLM 情境学习资料的快速精确遗忘技术:基于 In-Context Learning 与量化 K-Means 的 ERASE 方法
学习·算法·kmeans
叫我:松哥10 天前
基于机器学习和flask的体育健身风险智能分析系统,系统集成DeepSeek、聚类算法、分类算法等,准确率达90%
人工智能·python·神经网络·算法·机器学习·flask·聚类
暖阳华笺14 天前
【高频考点】K-Means聚类算法
c++·算法·机器学习·kmeans·聚类
zhumin72615 天前
基于人类行为聚类与虚拟内分泌时间序列的硅基情绪计算模型构建研究
机器学习·数据挖掘·聚类
Dontla16 天前
聚类找不到簇原因分析(聚类失败)(DBSCAN聚类算法、eps参数、Epsilon参数、最大允许距离)
算法·数据挖掘·聚类
幽冥三王爷18 天前
手机蓝牙分档策略的理论基础与科学定档方法:从 RSSI 物理规律到稳健聚类定档
智能手机·数据挖掘·聚类·蓝牙定位·rssi
apcipot_rain19 天前
计科八股20260604——AI安全、K-means、SVM、nano
人工智能·神经网络·安全·支持向量机·kmeans