• 【聚类】K-Means聚类


    cluster:簇

    原理:

    这边暂时没有时间具体介绍kmeans聚类的原理。简单来说,就是首先初始化k个簇心;然后计算所有点到簇心的欧式距离,对一个点来说,距离最短就属于那个簇;然后更新不同簇的簇心(簇内所有点的平均值,也就是簇内点的重心);循环往复,直至簇心不变达到规定的迭代次数

    python实现

    我们这边通过调用sklearn.cluster中的kmeans方法实现kmeans聚类

    入门

    原始数据的散点图

    1. from sklearn.cluster import KMeans
    2. import numpy as np
    3. import matplotlib.pyplot as plt
    4. # 数据
    5. class1 = 1.5 * np.random.randn(100,2) #100个2维点,标准差1.5正态分布
    6. class2 = 1.5*np.random.randn(100,2) + np.array([5,5])#标准正态分布平移5,5
    7. # 画出数据的散点图
    8. plt.figure(0,dpi = 300)
    9. plt.scatter(class1[:,0],class1[:,1],c='y',marker='*')
    10. plt.scatter(class2[:,0],class2[:,1],c='k',marker='.')
    11. plt.axis('off') # 不显示坐标轴
    12. plt.show()

    kmeans聚类

    1. #---------------------------kmeans--------------------
    2. # 调用kmeans函数
    3. features = np.vstack((class1,class2))
    4. kmeans = KMeans(n_clusters=2)
    5. kmeans .fit(features)
    6. plt.figure(1,dpi = 300)
    7. #满足聚类标签条件的行
    8. ndx = np.where(kmeans.labels_==0)
    9. plt.scatter(features[ndx,0],features[ndx,1],c='b',marker='*')
    10. ndx = np.where(kmeans.labels_==1)
    11. plt.scatter(features[ndx,0],features[ndx,1],c='r',marker='.')
    12. # 画出簇心
    13. plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],c='g',marker='o')
    14. plt.axis('off') # 去除画布边框
    15. plt.show()

    进一步:选择簇心k的值 

    前面的数据是我们自己创建的,所以簇心k是我们自己可以定为2。但是在实际中,我们不了解数据,所以我们需要根据数据的情况确定最佳的簇心数k。

    这是下面用到的数据data11_2.txt【免费】这是kmean聚类中用到的一个数据资源-CSDN文库

    簇内离差平方方和与拐点法(不太好判断)

    定义w是簇内的点,m_i是簇的重心。

    则所有簇的簇内离差平方和的和为J_k = \sum_{i=1}^{k} \sum_{w \in G_i} ||w-m_i||^2。然后通过可视化的方法,找到拐点,认为突然变化的点就是寻找的目标点,因为继续随着k的增加,聚类效果没有大的变化

    借助python中的“md = KMeans(i).fit(b),md.inertia_”实现。

    1. import numpy as np
    2. from sklearn.cluster import KMeans
    3. import pylab as plt
    4. plt.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
    5. a = np.loadtxt('data/data11_2.txt') # 加载数
    6. b=(a-a.min(axis=0))/(a.max(axis=0)-a.min(axis=0)) # 标准化
    7. # 求出k对应的簇内离差平均和的和
    8. SSE = []; K = range(2, len(a)+1)
    9. for i in K:
    10. md = KMeans(i).fit(b)
    11. SSE.append(md.inertia_) # 它表示聚类结果的簇内平方误差和(Inertia)
    12. # 可视化
    13. plt.figure(1)
    14. plt.title('k值与离差平方和的关系曲线')
    15. plt.plot(K, SSE,'*-');
    16. # 生成想要的 x 轴刻度细化值
    17. x_ticks = np.arange(2, 10, 1)
    18. # 设置 x 轴刻度
    19. plt.xticks(x_ticks)
    20. plt.show()

    通过上图可以看出k=3时,是个拐点。所有选择k=3。

    轮廓系数法(十分客观)

    定义样本点i的轮廓系数S_i = \frac{b_i-a_i}{max(a_i,b_i)},S_i代表样本点i的轮廓系数,a_i代表该点到簇内其他点的距离的均值;b_i分两步,首先计算该点到其他簇内点距离的平均距离,然后将最小值作为b_i。a_i表示了簇内的紧密度,b_i表示了簇间的分散度。

    k个簇的总轮廓点系数定义为所有样本点轮廓系数的平均值。因此计算量大

    总轮廓系数越接近1,聚类效果越好。簇内平均距离小,簇间平均距离大。

    调用sklearn.metrics中的silhouette_score(轮廓分数)函数实现

    1. #程序文件ex11_7.py
    2. import numpy as np
    3. import matplotlib.pyplot as plt
    4. from sklearn.cluster import KMeans
    5. from sklearn.metrics import silhouette_score
    6. plt.rcParams['font.sans-serif'] = ['SimHei']
    7. # 忽略警告
    8. import warnings
    9. # 使用过滤器来忽略特定类型的警告
    10. warnings.filterwarnings("ignore")
    11. a = np.loadtxt('data/data11_2.txt')
    12. b=(a-a.min(axis=0))/(a.max(axis=0)-a.min(axis=0))
    13. S = []; K = range(2, len(a))
    14. for i in K:
    15. md = KMeans(i).fit(b)
    16. labels = md.labels_
    17. S.append(silhouette_score(b, labels))
    18. plt.figure(dpi = 300)
    19. plt.title('k值与轮廓系数的关系曲线')
    20. plt.plot(K, S,'*-'); plt.show()

    综上两种方法,好像并没有什么最好的方法,离差平均和不好判断,轮廓系数又像上面的情况。感觉综合两种方法比较好 

  • 相关阅读:
    Flask框架学习大纲
    【JavaScript 逆向】webpack 之某妹游戏登录逆向
    Android Snackbar
    Unity坐标系入门
    篇(18)-Asp.Net Core入门实战-文章管理之文章内容管理(下拉框二级结构递归)
    图的拉普拉斯矩阵
    深度学习数据集最常见的6大问题
    IDEFICS 简介: 最先进视觉语言模型的开源复现
    Vue基础_Vue2
    渔业安全生产综合管理指挥系统-航迹数据优化方案
  • 原文地址:https://blog.csdn.net/m0_67173953/article/details/132654670