k-means聚类算法的python实现和sklearn的聚类器
k-means聚类算法的python实现和sklearn的聚类器
k-means聚类算法的python实现和sklearn的聚类器
文章目录k-means聚类算法的python实现和sklearn的聚类器1. 标准k-means聚类算法
2. sklearn.cluster.KMeans
[var1]
k-means是一个迭代算法,需要人为指定聚类数量。因为实现简单、对大样本有很好的拓展性被广泛采用。
算法初始化阶段首先随机选取不重复的kkk个点作为 初始的聚类中心(称为Centroid)。不断重复执行以下两个步骤:
给每个点xix_ixi?分配所属类别lil_ili?
li=argminj{d(xi,μj)}l_i=\mathop{argmin}_{j}\{d(x_i,\mu_j)\}li?=argminj?{d(xi?,μj?)}
根据分配结果重新计算每个聚类的均值
μj=1{li=j}xi1{li=j}\mu_j=\frac{1\{l_i=j
\}x_i}{1\{l_i=j\}}μj?=1{li?=j}1{li?=j}xi??
实现代码如下,实际上实现k-means算法的代码只有def k_means(dist, xy, k,centroids=None):的几行。
# k-means 聚类算法
import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
plt.rcParams.update({
'savefig.dpi': 600,
'mathtext.fontset':'cm',
'font.sans-serif':'SimHei',
'axes.unicode_minus': False
})
def k_means(dist, xy, k,centroids=None):
# 随机不重复地选取 k 个点作为初始聚类中心
if not centroids:
centroids = np.random.choice(np.arange(dist.shape[0]),k,replace=False)
index = np.arange(dist.shape[0])
while True:
# 给每个点分配所属类别
groupid = np.argmin(dist[:,centroids], axis=-1)
# 生成类别索引
groups = [np.where(groupid == id,True,False) for id in range(len(centroids))]
# 重新计算每一类的均值
kmeans = np.array([np.mean(xy[group],axis=0) for group in groups])
# 重新选定聚类中心
centroids_new = np.argmin(la.norm(xy[:,None,:] - kmeans,ord=2,axis=-1)**2,axis=0)
# 如果聚类中心不再变化,算法结束
if np.all(centroids == centroids_new):
return centroids,[index[group] for group in groups]
centroids = centroids_new
def get_dist():
X,Y = np.meshgrid(np.arange(10),np.arange(10))
xy = np.vstack((X.ravel(),Y.ravel())).T
dist = la.norm(xy[:,None,:] - xy,ord=2, axis=-1)
return dist, np.array(xy)
_, xy = get_dist()
X,Y = xy[:,0],xy[:,1]
fig,ax = plt.subplots()
ax.scatter(X.ravel(),Y.ravel(),marker='o',facecolor='white',edgecolor='k')
plt.show()
def cluster_diagram(centroids, groups, cmap=['r','g','b','k'],centroids_marker='D'):
# 'D' -- 'diamond'
fig, ax = plt.subplots()
for i in range(len(centroids)):
group,center = groups[i],centroids[i]
ax.scatter(X[group],Y[group],marker='o',facecolor='white',edgecolor=cmap[i])
ax.scatter(X[center],Y[center],marker=centroids_marker,facecolor='white',edgecolor=cmap[i],linewidth=2)
plt.show()
def main():
dist, xy = get_dist()
centroids, groups = k_means(dist,xy,4)
# centroids, groups = k_means(*get_dist(),4,centroids=[54,55,64,65])
print(centroids, *groups,sep='\n')
cluster_diagram(centroids,groups)
# sklearn.cluster.KMeans
kmeans = KMeans(4)
kmeans.fit(xy)
print(kmeans.labels_,kmeans.cluster_centers_,sep='\n')
if __name__ == '__main__':
main()
首先生成了坐标系上的100100100个点坐标和相应的距离矩阵。这里是点的坐标分布:
经过k_means函数聚类后画出聚类结果图。这里是聚类结果:(选取最中间的四个点[54,55,64,65]可以得到最均匀的聚类结果)
最后调用了sklearn.cluster.KMeans,和它的结果对比。
我的函数k_means():
聚类中心:[22 27 72 77]
所属类别:
[ 0 1 2 3 4 10 11 12 13 14 20 21 22 23 24 30 31 32 33 34 40 41 42 43
44]
[ 5 6 7 8 9 15 16 17 18 19 25 26 27 28 29 35 36 37 38 39 45 46 47 48
49]
[50 51 52 53 54 60 61 62 63 64 70 71 72 73 74 80 81 82 83 84 90 91 92 93
94]
[55 56 57 58 59 65 66 67 68 69 75 76 77 78 79 85 86 87 88 89 95 96 97 98
99]
skleaern.cluster.KMeans:
聚类中心:
[[2. 2.]
[2. 7.]
[7. 7.]
[7. 2.]]
所属类别:
[0 0 0 0 0 3 3 3 3 3 0 0 0 0 0 3 3 3 3 3 0 0 0 0 0 3 3 3 3 3 0 0 0 0 0 3 3
3 3 3 0 0 0 0 0 3 3 3 3 3 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 1 1 1 1
1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2]
[var1]
第一节的代码用到了sklearn.cluster.KMeans,这里搬运一个官方文档给出的示例代码:
>>> from sklearn.cluster import KMeans
>>> import numpy as np
>>> X = np.array([[1, 2], [1, 4], [1, 0],
... [10, 2], [10, 4], [10, 0]])
>>> kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
>>> kmeans.labels_
# 给出每个点所属类别的向量
array([1, 1, 1, 0, 0, 0], dtype=int32)
>>> kmeans.predict([[0, 0], [12, 3]])
# 预测类别
array([1, 0], dtype=int32)
>>> kmeans.cluster_centers_
# 聚类中心
array([[10., 2.],
[ 1., 2.]])
k-means聚类算法的python实现和sklearn的聚类器相关教程