0


聚类-KMeans算法(图解算法原理)

文章目录

简介


k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,也就是将数据分成K个簇的算法,其中K是用户指定的。

比如将下图中数据分为3簇,不同颜色为1簇。
在这里插入图片描述

K-means算法的作用就是将数据划分成K个簇,每个簇高度相关,即离所在簇的质心是最近的。
下面将简介K-means算法原理步骤。

算法原理


  1. 随机选取K个质心

随机3个点为质心(红黄蓝),淡蓝色为数据。
在这里插入图片描述

附可视化代码:

  1. import matplotlib.pyplot as plt
  2. from sklearn.datasets import make_blobs
  3. # 生成数据集:500个点,二维特征,3个质心
  4. x, y = make_blobs(n_samples=500, n_features=2, centers=3, random_state=20220929)
  5. plt.scatter(x[:,0], x[:,1], color="lightblue")# 随机
  6. center =[[3,-1],[5,-2.5],[8,-2]]
  7. colors =["red","gold","blue"]
  8. plt.scatter(center[0][0], center[0][1], color=colors[0])
  9. plt.scatter(center[1][0], center[1][1], color=colors[1])
  10. plt.scatter(center[2][0], center[2][1], color=colors[2])
  11. plt.show()
  1. 计算每个数据到各质心距离

一般使用欧氏距离来计算,为了便于展示,取特征维数为2,即

  1. (
  2. x
  3. 1
  4. x
  5. 2
  6. )
  7. 2
  8. +
  9. (
  10. y
  11. 1
  12. y
  13. 2
  14. )
  15. 2
  16. \sqrt{(x_1-x_2)^2+(y_1-y_2)^2}
  17. (x1​−x2​)2+(y1​−y2​)2
  1. def_distance(v1, v2):# 不开根号节省算力,效果一致return np.sum(np.square(v1-v2))
  1. 将数据分到最近质心的簇
  1. dist = np.zeros((500,3),float)# 距离
  2. c =[3]# 3个簇for i inrange(500):
  3. mx =-1.# 最近值
  4. idx =0#最近簇for j inrange(3):
  5. dist[i][j]= _distance(x[i], center[j])if mx > dist[i][j]or mx ==-1.:
  6. mx = dist[i][j]
  7. idx = j
  8. # 设置透明度,以区分质心
  9. plt.scatter(x[i][0], x[i][1], color=colors[idx], alpha=0.2)
  10. c[idx].append(i)
  11. plt.show()

在这里插入图片描述

  1. 根据各簇数据更新质心

    1. c
    2. j
    3. =
    4. 1
    5. c
    6. j
    7. x
    8. c
    9. j
    10. x
    11. c_j=\frac{1}{\left|c_j\right|}\sum_{x\in c_j}x

    cj​=∣cj​∣1​∑x∈cj​​x

其中

  1. c
  2. j
  3. c_j
  4. cj​表示第
  5. j
  6. j
  7. j个质心,也就是计算属于当前簇数据的均值作为新的质心。即K均值算法名称由来。

当平均误差和SSE越小越接近质心,由推导得质心取数据均值时,SSE最小。

比如数据[[1, 2], [3, 4]]属于同一个簇,则更新簇中心为[2, 3]。

  1. # 更新质心for i inrange(3):
  2. sum_x =0.
  3. sum_y =0.for j inrange(len(c[i])):
  4. sum_x += x[c[i][j]][0]
  5. sum_y += x[c[i][j]][1]
  6. center[i]=[sum_x/len(c[i]), sum_y/len(c[i])]
  7. plt.scatter(center[0][0], center[0][1], color=colors[0])
  8. plt.scatter(center[1][0], center[1][1], color=colors[1])
  9. plt.scatter(center[2][0], center[2][1], color=colors[2])
  10. plt.show()

在这里插入图片描述

(插播反爬信息 )博主CSDN地址:https://wzlodq.blog.csdn.net/

  1. 重复2-4步直到收敛

    1. i
    2. =
    3. 1
    4. n
    5. a
    6. r
    7. g
    8. m
    9. i
    10. n
    11. x
    12. i
    13. c
    14. i
    15. \sum_{i=1}^n argmin||x_i-c_i ||

    ∑i=1n​argmin∣∣xi​−ci​∣∣

计算当前聚类的平方差,循环退出条件是取得最小的平方差,也就是质心不再改变的时候。最终质心一定是确定的,不会陷入死循环。

随着循环次数逐渐收敛,不难证第1步随机的初始质心对结果无影响,即使得K-means算法具有普遍适用性。

在这里插入图片描述
在这里插入图片描述

可以看出,第六次更新后聚类相同,数据收敛。
大家可以尝试修改初始质心,查看结果是否一致。

sklearn库调用


上面手动复现了K-means代码的实现,但其实sklearn库有相应的封装函数,本节介绍其调用。

  1. sklearn.cluster.KMeans

,主要参数:

  • n_clusters:k值,质心数,默认8
  • max_iter : int, default:最大迭代次数
  • tol:质心的变化率小于此值时结束,默认1e-4
  • random_state:随机种子
  1. import matplotlib.pyplot as plt
  2. from sklearn.cluster import KMeans
  3. from sklearn.datasets import make_blobs
  4. if __name__ =="__main__":# 数据
  5. x, y = make_blobs(n_samples=500, n_features=2, centers=3, random_state=20220929)# 创建KMeans对象
  6. km = KMeans(n_clusters=3, random_state=20220929)# 训练模型
  7. km.fit(x)# 测试
  8. predict = km.predict(x)# 可视化
  9. plt.scatter(x[:,0], x[:,1], c=predict)
  10. plt.show()

在这里插入图片描述
用过都说好(~ ̄▽ ̄)~

K的取值


最后还有一个问题,就是K是用户指定的,那又该怎么确定K值呢?

站在巨人的肩膀上,主要有两种方法:手肘法和轮廓系数法。

  1. 手肘法

    1. S
    2. S
    3. E
    4. =
    5. i
    6. =
    7. 1
    8. k
    9. p
    10. C
    11. i
    12. p
    13. m
    14. i
    15. 2
    16. SSE=\sum_{i=1}^k\sum_{p\in C_i}|p-m_i|^2

    SSE=∑i=1k​∑p∈Ci​​∣p−mi​∣2

    1. C
    2. i
    3. C_i

    Ci​表示第

    1. i
    2. i

    i个簇,

    1. m
    2. i
    3. m_i

    mi​表示第

    1. i
    2. i

    i个簇的质心,

    1. p
    2. p

    p是数据样本点。

根据误差平方和SSE来选择K值,但并不是选SSE最小时对应的K,而是选SSE突然变小时的K,如下图,K应选3,图似手肘故得名。
在这里插入图片描述

  1. import matplotlib.pyplot as plt
  2. from sklearn.cluster import KMeans
  3. from sklearn.datasets import make_blobs
  4. if __name__ =="__main__":
  5. x, y = make_blobs(n_samples=500, n_features=2, centers=3, random_state=20220929)
  6. SSE =[]for k inrange(2,10):
  7. km = KMeans(n_clusters=k)
  8. km.fit(x)
  9. SSE.append(km.inertia_)
  10. plt.xlabel('K')
  11. plt.ylabel('误差平方和')
  12. plt.plot(range(2,10), SSE,'o-')
  13. plt.rcParams['font.sans-serif']=['SimHei']
  14. plt.show()
  1. 轮廓系数法

    1. S
    2. =
    3. b
    4. a
    5. m
    6. a
    7. x
    8. (
    9. a
    10. ,
    11. b
    12. )
    13. S=\frac{b-a}{max(a,b)}

    S=max(a,b)b−a​

    1. a
    2. a

    a是到同簇中其它样本的平均距离,表示内聚度。

    1. b
    2. b

    b是到其他簇中所有样本的平均距离,表示分离度。

考虑内聚度和分离度两个因素,计算轮廓系数(Silhouette Coefficient)S,S越接近1则聚类效果越好。如下图,K=3时,S最接近1。
在这里插入图片描述

  1. import matplotlib.pyplot as plt
  2. from sklearn.cluster import KMeans
  3. from sklearn.datasets import make_blobs
  4. from sklearn.metrics import silhouette_score
  5. if __name__ =="__main__":
  6. x, y = make_blobs(n_samples=500, n_features=2, centers=3, random_state=20220929)
  7. S =[]for k inrange(2,10):
  8. km = KMeans(n_clusters=k)
  9. km.fit(x)
  10. S.append(silhouette_score(x, km.labels_))
  11. plt.xlabel('K')
  12. plt.ylabel('轮廓系数')
  13. plt.plot(range(2,10), S,'o-')
  14. plt.rcParams['font.sans-serif']=['SimHei']
  15. plt.show()

原创不易,请勿转载(本不富裕的访问量雪上加霜 )
博主首页:https://wzlodq.blog.csdn.net/
来都来了,不评论两句吗👀
如果文章对你有帮助,记得一键三连❤

标签: 聚类 算法 kmeans

本文转载自: https://blog.csdn.net/qq_45034708/article/details/127087587
版权归原作者 吾仄lo咚锵 所有, 如有侵权,请联系我们删除。

“聚类-KMeans算法(图解算法原理)”的评论:

还没有评论