聚类算法之K-Means

1. K-Means

1.1 K-Means原理

K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本划分为 K K K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。

假设簇划分为 ( C 1 , C 2 , . . . , C K ) (C_1,C_2,...,C_K) (C1,C2,...,CK),则我们的目标是最小化平方误差:
E = ∑ i = 1 K ∑ x ∈ C i ∣ ∣ x − μ i ∣ ∣ 2 2 E=\sum_{i=1}^K\sum_{x \in C_i}||x-\mu_i||_2^2 E=i=1KxCixμi22
其中 μ i \mu_i μi是簇 C i C_i Ci的均值向量,有时也称为质心,表达式为:
μ i = 1 ∣ C i ∣ ∑ x ∈ C i x \mu_i=\frac {1} {|C_i|}\sum_{x \in C_i}x μi=Ci1xCix

1.2 K-means算法流程

输 入 : 样 本 集 D = { x 1 , x 2 , . . . , x M } , 聚 类 的 簇 树 K , 最 大 迭 代 次 数 N 输入:样本集D=\{x_1,x_2,...,x_M\},聚类的簇树K,最大迭代次数N D={ x1,x2,...,xM}KN

输 出 : 簇 划 分 C = { C 1 , C 2 , . . . , C K } 输出:簇划分C=\{C_1,C_2,...,C_K\} C={ C1,C2,...,CK}

  1. 从数据集 D D D随机选择 K K K个样本作为初始的 K K K个质心向量: { μ 1 , μ 2 , . . . , μ K } \{\mu_1,\mu_2,...,\mu_K\} { μ1,μ2,...,μK}
  2. 对于 n = 1 , 2 , . . . , N n=1,2,...,N n=1,2,...,N
    • 将簇划分 C C C初始化为 C t ≠ ∅ , t = 1 , 2 , . . . K C_t \not= \varnothing, \quad t=1,2,...K Ct=,t=1,2,...K
    • 对于 i = 1 , 2 , . . . , M i=1,2,...,M i=1,2,...,M,计算样本 x i x_i xi和各个质心向量 μ j ( j = 1 , 2 , . . . , K ) \mu_j(j=1,2,...,K) μj(j=1,2,...,K)的距离: d i j = ∣ ∣ x i − μ j ∣ ∣ 2 2 d_{ij}=||x_i-\mu_j||_2^2 dij=xiμj22,将最小的 d i j d_{ij} dij对应的类别 λ j \lambda_j λj标记给 x i x_i xi。此时更新 C λ j = C λ j ∪ { x i } C_{\lambda_j}=C_{\lambda_j} \cup \{x_i\} Cλj=Cλj{ xi}
    • 对于 j = 1 , 2 , . . . , K j=1,2,...,K j=1,2,...,K,对 C j C_j Cj中所有的样本点重新计算新的质心 μ j = 1 ∣ C j ∣ ∑ x ∈ C j x \mu_j=\frac {1} {|C_j|}\sum_{x \in C_j}x μj=Cj1xCjx
    • 如果所有的 K K K个质心向量都没有发生变化,则转到步骤3
  3. 输出簇划分 C = { C 1 , C 2 , . . . , C K } C=\{C_1,C_2,...,C_K\} C={ C1,C2,...,CK}

1.3 K-Means++

对于K-means算法, K K K个初始化的质心的位置选择对最后的聚类结果和运行时间都有较大影响,因此需要合适的选择 K K K个质心。K-means++算法就是对 K − m e a n s K-means Kmeans随机初始化质心的方法的优化。

K-means++初始化质心的优化策略:

  1. 从输入的数据集中随机选择一个点作为第一个聚类中心 μ 1 \mu_1 μ1
  2. 对于数据集中的每一个点 x i x_i xi,计算它与已选择的聚类中心中最近聚类中心距离 D ( x i ) = a r g m i n ∣ ∣ x i − μ j ∣ ∣ 2 2 , j = 1 , 2 , . . . , K s e l e c t e d D(x_i)=argmin||x_i-\mu_j||_2^2, \quad j=1,2,...,K_{selected} D(xi)=argminxiμj22,j=1,2,...,Kselected
  3. 选择一个新的数据点作为新的聚类中心,选择的原则是: D ( x ) D(x) D(x)较大的点,被选取作为聚类中心的概率较大
  4. 重复步骤2和步骤3直到选择 K K K个聚类质心
  5. 利用这 K K K个质心来作为初始化质心去运行K-Means算法

1.4 实例演示

import numpy as np 
import matplotlib.pyplot as plt 

from sklearn import cluster, datasets
from sklearn.preprocessing import StandardScaler

np.random.seed(0)

# 构建数据
n_samples = 1500
noisy_circles = datasets.make_circles(n_samples=n_samples, factor=0.5, noise=0.05)
noisy_moons = datasets.make_moons(n_samples=n_samples, noise=0.05)
blobs = datasets.make_blobs(n_samples=n_samples, random_state=8)

data_sets = [
    (
        noisy_circles,
        {
     
            "n_clusters": 2
        }
    ),
    (
        noisy_moons,
        {
     
            "n_clusters": 2
        }
    ), 
    (
        blobs, 
        {
     
            "n_clusters": 3
        }
    )
]
colors = ["#377eb8", "#ff7f00", "#4daf4a"]

plt.figure(figsize=(15, 5))

for i_dataset, (dataset, algo_params) in enumerate(data_sets):
    # 模型参数
    params = algo_params

    # 数据
    X, y = dataset
    X = StandardScaler().fit_transform(X)

    # 创建K-means
    k_means = cluster.KMeans(n_clusters=params["n_clusters"])

    # 训练
    k_means.fit(X)

    # 预测
    y_pred = k_means.predict(X)

    y_pred_colors = []

    for i in y_pred:
        y_pred_colors.append(colors[i])
    
    plt.subplot(1, 3, i_dataset+1)

    plt.scatter(X[:, 0], X[:, 1], color=y_pred_colors)

plt.show()

聚类算法之K-Means_第1张图片

1.5 K-Means小结

优点:

  1. 原理简单,实现容易,收敛速度快
  2. 聚类效果较优
  3. 算法的可解释较强
  4. 主要需要调参的参数仅是簇数 K K K

缺点:

  1. K K K值得选取不好把握
  2. 对于不是凸得数据集比较难收敛
  3. 如果各隐含类别得数据不平衡,则聚类效果不佳
  4. 采用迭代方法,得到得结果只是局部最优
  5. 对噪音和异常点比较敏感

你可能感兴趣的:(聚类,算法,kmeans)