一、理论讲解

给定样本集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)

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

三、代码实现

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

xigua = pd.read_csv('D:/Machine_Learning/西瓜数据集4.0.csv', encoding='gbk')
data = xigua.values[:, [1,2]]
print(data.shape)
model = KMeans(n_clusters=3, random_state=10).fit(data) #默认为k-means++
label = model.predict(data)
print(label)
plt.scatter(data[:,0], data[:,1], c=label)
plt.show()

得到的结果如下:

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐