• 机器学习算法——聚类3(k均值算法)


    一、理论讲解

    给定样本集D=\{x_1,x_2,...,x_m \},k均值(k-means)算法针对聚类所得簇划分C=\{C_1,C_2,...,C_k \}最小化平方误差为:

    E=\sum_{i=1}^{k} \sum_{x \in C_i} || x-\mu_i ||_2^2    (1)

    其中\mu_i = \frac{1}{|C_i|} \sum_{x \in C_i} x是簇内C_i的均值向量。直观来看,(1)式在一定程度上刻画了簇内样本围绕簇均值向量的紧密程度,E越小,则簇内样本相似度越高。

    最小化(1)式并不容易,找到它的最优解需考察样本集D所有可能的簇划分,这是一个NP难问题。因此,k均值算法采用了贪心策略,通过迭代优化来近似求解(1)式。算法流程为:


    输入:样本集D=\{x_1,x_2,...,x_m \};聚类簇数k

    过程:从D中随机选择k个样本最为初始均值向量\{\mu_1,\mu_2,...,\mu_k \}

    repeat

            令 C_i = \phi (1 \leqslant i \leqslant k)

            for j = 1,2,..,m do

                    计算样本x_j与各均值向量\mu_i (1 \leqslant i \leqslant k)的距离:d_{ji} = ||x_j - \mu_i||_2;

                    根据距离最近的均值向量确定 x_j的簇标记:\lambda_j = arg min_{i \in \{1,2,...,k\}} d_{ji};

                    将样本x_j划入相应的簇:C_{\lambda j}= C_{\lambda j} \cup {x_j}

            end for

            for i=1,2,..,k do

                    计算新均值向量:\mu_i^{'} = \frac{1}{|C_i|}\sum_{x \in C_i} x

                    if \mu_i ^{'} \neq \mu_i then

                            将当前均值向量\mu_i更新为\mu_i^{'}

                    else

                            保持当前均值不变

                    end if

            end for

    until 当前均值向量均未更新

    输出:簇划分C=\{C_1,C_2,...,C_k\}


    二、案例讲解

    用西瓜数据集4.0解释上述算法:

     

    编号密度含糖率
    10.697    0.460
    20.7740.376
    30.6340.264
    40.6080.318
    50.5560.215
    60.4030.237
    70.4810.149
    80.4370.211
    90.6660.091
    100.2430.267
    110.2450.057
    120.3430.099
    130.6390.161
    140.6570.198
    150.3600.370
    160.5930.042
    170.7190.103
    180.3590.188
    190.3390.241
    200.2820.257
    210.7480.232
    220.7140.346
    230.4830.312
    240.4780.437
    250.5250.369
    260.7510.489
    270.5320.472
    280.4730.376
    290.7250.445
    300.4460.459

     假定聚类簇数为3,算法开始时随机选取三个样本x_6,x_{12},x_{27}做为初始均值向量,即

    \mu_1=(0.403;0.237), \mu_2=(0.343,0.099),\mu_3=(0.532,0.472)

    考察样本x_1=(0.697;0.460),它与当前均值向量\mu_1的距离为:

    \mu_1 = \sqrt{(0.697-0.403)^2+(0.460-0.237)^2} = 0.369

    \mu_2= \sqrt{(0.697-0.343)^2+(0.460-0.099)^2}=0.506

    \mu_3= \sqrt{(0.697-0.532)^2+(0.460-0.472)^2}=0.166

    因此将x_1划入簇C_3中。类似地,对样本集中的所有样本考察一遍后,可得当前簇划分为

    C_1=\{x_5,x_6,x_7,x_8,x_9,x_{10},x_{13},x_{14},x_{15},x_{17},x_{18},x_{19},x_{20},x_{23} \}

    C_2=\{x_{11},x_{12},x_{16} \}

    C_3=\{x_1,x_2,x_3,x_4,x_{21},x_{22},x_{24},x_{25},x_{26},x_{27},x_{28},x_{29},x_{30} \}

    于是从C_1,C_2,C_3分别求出新得均值向量

    \mu_1^{'}= (0.473,0.214), \mu_2^{'}=(0.394,0.066),\mu_3^{'}=(0.623,0.388)

    更新当前均值向量后,不断重复上述过程。最终在第五轮迭代产生得结果与第四轮迭代相同,于是算法终止,得到最终的簇划分。

    三、代码实现

    1. import matplotlib.pyplot as plt
    2. from sklearn.cluster import KMeans
    3. import pandas as pd
    4. xigua = pd.read_csv('D:/Machine_Learning/西瓜数据集4.0.csv', encoding='gbk')
    5. data = xigua.values[:, [1,2]]
    6. print(data.shape)
    7. model = KMeans(n_clusters=3, random_state=10).fit(data) #默认为k-means++
    8. label = model.predict(data)
    9. print(label)
    10. plt.scatter(data[:,0], data[:,1], c=label)
    11. plt.show()

    得到的结果如下:

     

  • 相关阅读:
    flink中interval join的flinkSQL实现以及状态的TTL过期时间
    如何更好的管理个人财务?使用极空间部署私有记账系统Firefly III
    python调用外部exe程序 等待程序执行完后后 往下运行 直接往下运行
    【校招VIP】前端专业课网络之OSI七层模型
    数学建模笔记
    小说阅读软件阅读界面设计
    机器学习——聚类算法
    Flink 命令行提交、展示和取消作业
    这一次,彻底梳理各种布局问题
    图片翻译成中文怎么弄?分享三个图片翻译小技巧
  • 原文地址:https://blog.csdn.net/Vicky_xiduoduo/article/details/126262545