k-means聚类
一、概述
当前人工智能技术实现的一种主要手段是机器学习,而机器学习能够解决的问题主要有三种:分类、聚类、回归,有监督的是分类,无监督的是聚类。所谓聚类,就是以一定的方法将一堆样本依它们本身的数据特性划分成不同的簇类,以达成不同的技术目的,k-means就是这样一种基础聚类算法。
二、算法原理
对给定的样本集,k-means基于迭代的思想,由聚集中心点划定簇集,簇集反过来确定新的聚集中心点,周而复始,最终获得最佳划分的簇集。k-means中的k即想要划定的簇数,它是一个超参数,需由人工事先指定。样本的簇集划归由它与各个聚集中心点的距离来确定,划归到距离最近的那一个,其中距离的计算一般采用欧氏距离;新划定的簇集则进一步计算质心作为新的聚集中心,质心即样本向量的均值 \(c=\left( \bar{x^{(1)}},\bar{x^{(2)}},...,\bar{x^{(n)}} \right)\)
算法描述
输入:样本集 \(T=\left\{ x_1,x_2,...,x_N \right\}\),簇数k.
输出:质心集合 \(C=\left\{ c_1,c_2,...,c_k \right\}\),划分样本集\(D=\left\{ D_1,D_2,...,D_k \right\}\).
(1) 任意选定k个样本作为初始聚集中心.
(2) 划分簇类
1)对T中数据,计算与各个聚集中心的距离.样本x与聚集中心c的距离为$$d=\sqrt{\sum_{i=1}{n}{(x-c{(i)}){2}}}$$
2)将样本划归到离得最近的聚集中心,形成簇类。
(3)计算质心作为聚集中心
对簇S,质心 $$c=\left( c{(1)},c,...,c^{(n)} \right)$$其中
\(c^{(i)}=\frac{1}{M}\sum_{s=1}^{M}{x_{s}^{(i)}}\),\(M=\left| S \right|\).
(4)重复(2)-(3)步,直至质心不发生偏移或达到指定的迭代次数.
三、示例
二维空间中,有如下样本点集合,使用k-means方法完成聚类。
样本集:
演算:
由样本的大体分布,指定簇数3,
(1)选定随机样本指定为初始聚集中心:C1——(1,1),C2——(8,8),C3——(18,18)。
(2)计算样本点与各聚集中心的距离,划分簇类。
样本(1,2)到C1的距离为
到C2和C3的距离分别为9.2和23.3,距离C1最近,因此归属到簇1;同样地,(2,1)、(2,2)、(2,3)、(3,2)、(3,3)归属到簇1;(9,8)、(8,9)、(9,9)、(9,10)、(10,9)归属到簇2;(18,19)、(19,18)、(19,19)、(19,20)归属到簇3。
(3)计算簇集质心作为新的聚集中心
对簇1,质心
\(\begin{align} \bar{x}&=\frac{1}{7}\left( 1+1+2+2+2+3+3 \right) \\ &=2 \end{align}\) \(\begin{align} \bar{y}&=\frac{1}{7}\left( 1+2+1+2+3+2+3 \right) \\ &=2 \end{align}\) 则C1的坐标为(2,2);同理,C2的坐标为(8.8,8.8),C3的坐标为(18.6,18.8)。
(4)再次计算样本点与各聚集中心的距离,划分簇类。
样本(1,1)、(1,2)、(2,1)、(2,2)、(2,3)、(3,2)、(3,3)到C1的距离最近,归属到簇1;
样本(8,8)、(9,8)、(8,9)、(9,9)、(9,10)、(10,9)到C2的距离最近,归属到簇2;
样本(18,18)、(18,19)、(19,18)、(19,19)、(19,20)到C3的距离最近,归属到簇3。
(5)再次计算簇集质心作为新的聚集中心,
簇1质心的坐标为(2,2),簇2质心的坐标为(8.8,8.8),簇3质心的坐标为(18.6,18.8)。
质心相对前次迭代未发生偏移,聚类结束。
(6)输出聚类结果
簇类1:{ (1,1),(1,2),(2,1),(2,2),(2,3),(3,2),(3,3)}
簇类2:{(8,8),(9,8),(8,9),(9,9),(9,10),(10,9)}
簇类3:{(18,18),(18,19),(19,18),(19,19),(19,20) }
四、python实现
'''
由sklearn实现kmeans聚类。
'''
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
# 初始化数据
data = np.array([(1,1),(1,2),(2,1),(2,2),(2,3),(3,2),(3,3),
(8,8),(9,8),(8,9),(9,9),(9,10),(10,9),
(18,18),(18,19),(19,18),(19,19),(19,20)])
# 定义kmeans模型
kmr = KMeans(n_clusters=3) # n_clusters为指定的簇数k
# 计算数据
fit_kmr = kmr.fit(data)
# 获取标签结果
rs_labels = fit_kmr.labels_
# 定义颜色列表
colors = ['b','r','c']
T = [colors[i] for i in rs_labels]
# 获取簇类中心点
rs_center_ids = fit_kmr.cluster_centers_
# 输出簇类
print('\n 聚类结果: \n')
ue = np.unique(rs_labels)
for i in range(ue.size):
CLS = []
for k in range(rs_labels.size):
if rs_labels[k] == ue[i]:
CLS.append(tuple(data[k]))
print('簇类{}:'.format(ue[i]),CLS)
# 结果可视化
plt.scatter(data[:,0],data[:,1],c=T,alpha=0.5) # 绘制数据点
plt.scatter(rs_center_ids[:,0],rs_center_ids[:,1],c='red') # 绘制质心
plt.show()
运行结果:
End.