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

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

1. 标准k-means聚类算法

k-means是一个迭代算法,需要人为指定聚类数量。因为实现简单、对大样本有很好的拓展性被广泛采用。
算法初始化阶段首先随机选取不重复的 k k k个点作为 初始的聚类中心(称为Centroid)。不断重复执行以下两个步骤:

  • 给每个点 x i x_i xi分配所属类别 l i l_i li
    l i = a r g m i n j { d ( x i , μ j ) } l_i=\mathop{argmin}_{j}\{d(x_i,\mu_j)\} li=argminj{d(xi,μj)}
  • 根据分配结果重新计算每个聚类的均值
    μ j = 1 { l i = j } x i 1 { l i = 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()

首先生成了坐标系上的 100 100 100个点坐标和相应的距离矩阵。这里是点的坐标分布:
在这里插入图片描述

经过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]

2. sklearn.cluster.KMeans

第一节的代码用到了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.]])
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: k-means是一种常用的聚类算法Python中有多种库可以实现k-means聚类,比如scikit-learn、numpy等。 下面是一个使用scikit-learn库实现k-means聚类的示例代码: ```python from sklearn.cluster import KMeans import numpy as np # 生成数据 X = np.random.rand(100, 2) # 创建KMeans模型 kmeans = KMeans(n_clusters=3) # 进行聚类 kmeans.fit(X) # 获取聚类结果 labels = kmeans.labels_ # 获取聚类中心点 centers = kmeans.cluster_centers_ ``` 在上面的代码中,首先使用numpy库生成100个二维随机数据点。然后,创建了一个KMeans模型,并指定聚类数为3。最后,使用fit方法对数据进行聚类,获取聚类结果和聚类中心点。 需要注意的是,k-means算法依赖于初始随机点的选取,因此有可能会得到不同的聚类结果。为了避免这种情况,可以使用多次随机初始化来求解最优聚类结果。 ### 回答2: k-means聚类算法是一种基于距离度量的无监督学习算法,用于将一组数据点分成k个不同的类别。Python提供了许多库和工具来实现k-means聚类算法,其中最常用的是scikit-learn库。 首先,需要导入所需的库: ``` from sklearn.cluster import KMeans import numpy as np ``` 然后,准备要进行聚类的数据。将数据存储在一个numpy数组中,每行代表一个数据点,每列代表一个特征。假设我们有一个数据集X,其中包含100个数据点和2个特征: ``` X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) ``` 接下来,我们可以使用KMeans类来实现k-means聚类算法: ``` kmeans = KMeans(n_clusters=2) # 创建KMeans对象,设置聚类的个数为2 kmeans.fit(X) # 对数据进行聚类 ``` 通过fit()方法,k-means算法会将数据分成2个不同的类别。我们还可以通过以下代码获得每个数据点的标签: ``` labels = kmeans.labels_ ``` 最后,我们可以通过以下代码获得每个类别的质心: ``` centroids = kmeans.cluster_centers_ ``` 这是k-means聚类算法Python中的简单实现。可以根据实际情况调整n_clusters参数来确定聚类的个数,并通过labels_和cluster_centers_属性获取聚类的结果。需要注意的是,k-means聚类算法对初始质心的选择非常敏感,因此可以使用不同的初始化方法来改善聚类结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值