k-means聚类算法 python实现_k-means聚类算法的python实现和sklearn的聚类器

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的聚类器相关教程

你可能感兴趣的:(k-means聚类算法,python实现)