• K-Means聚类算法


    k均值聚类

    k均值聚类是最简单也最常用的聚类算法,它试图找到代表数据特定区域的簇中心每个簇中心设置为所分配的所有数据点的平均值,如果簇的分配不再变化,那么算法结束。

    无监督学习:给出的标签不具有先验意义

    make_blobs数据集上使用k均值聚类算法,并输出用训练的无监督学习模型产生的预测结果:

    from sklearn.datasets import make_blobs
    from sklearn.cluster import KMeans
    
    X, y = make_blobs(random_state=1)
    kmeans = KMeans(n_clusters=3)
    kmeans.fit(X)
    
    print(kmeans.predict(X))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    👇这个结果给出的仅是簇标签,无先验含义。如,通过k均值聚类分类出的人物肖像,需要查看肖像才知道是你的哪位朋友。

    [1 0 0 0 2 2 2 0 1 1 0 0 2 1 2 2 2 1 0 0 2 0 2 1 0 2 2 1 1 2 1 1 2 1 0 2 0
     0 0 2 2 0 1 0 0 2 1 1 1 1 0 2 2 2 1 2 0 0 1 1 0 2 2 0 0 2 1 2 1 0 0 0 2 1
     1 0 2 2 1 0 1 0 0 2 1 1 1 1 0 1 2 1 1 0 0 2 2 1 2 1]
    
    • 1
    • 2
    • 3

    给出其预测边界:

    mglearn.discrete_scatter(X[:, 0], X[:, 1], kmeans.labels_, markers='o')
    mglearn.discrete_scatter(
     kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], [0, 1, 2],
     markers='^', markeredgewidth=2)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    👆由于设置簇的个数为3,因此最终分为3簇,簇中心使用🔺表示。

    查看不同聚类中心个数对聚类结果的影响

    分别设置聚类中心个数为2个和5个:

    import matplotlib.pyplot as plt
    fig, axes = plt.subplots(1, 2, figsize=(10, 5))
    # 使用2个簇中心:
    kmeans = KMeans(n_clusters=2)
    kmeans.fit(X)
    assignments = kmeans.labels_
    mglearn.discrete_scatter(X[:, 0], X[:, 1], assignments, ax=axes[0])
    # 使用5个簇中心:
    kmeans = KMeans(n_clusters=5)
    kmeans.fit(X)
    assignments = kmeans.labels_
    mglearn.discrete_scatter(X[:, 0], X[:, 1], assignments, ax=axes[1])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    由于k均值聚类事先不知道聚类中心的个数,因此给出的聚类结果大概率会由于聚类中心个数的变化而改变。
    之前看过一篇半监督学习模式下的K-Means聚类方法,大意是事先知道聚类中心的个数并人为地设置好,再进行聚类。当然,聚类中心的个数也可以通过肘部法则求得。

    KMeans的局限

    • K均值聚类认为每个簇的半径大致相同。
    • K均值聚类还假设所有方向的簇都同等重要。
      因此改变簇的密度,会导致K均值效果下降。
    X_varied, y_varied = make_blobs(n_samples=200,
     cluster_std=[1.0, 2.5, 0.5],
     random_state=170)
    y_pred = KMeans(n_clusters=3, random_state=0).fit_predict(X_varied)
    mglearn.discrete_scatter(X_varied[:, 0], X_varied[:, 1], y_pred)
    plt.legend(["cluster 0", "cluster 1", "cluster 2"], loc='best')
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    分为三簇,但是K均值的效果下降。

    K均值无法识别非球形簇

    # 生成一些随机分组数据
    import numpy as np
    X, y = make_blobs(random_state=170, n_samples=600)
    rng = np.random.RandomState(74)
    # 变换数据使其拉长
    transformation = rng.normal(size=(2, 2))
    
    X = np.dot(X, transformation)
    # 将数据聚类成3个簇
    kmeans = KMeans(n_clusters=3)
    kmeans.fit(X)
    y_pred = kmeans.predict(X)
    # 画出簇分配和簇中心
    plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap=mglearn.cm3)
    plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
     marker='^', c=[0, 1, 2], s=100, linewidth=2, cmap=mglearn.cm3)
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    👆真实的簇与K均值分出来的簇。
    另一个例子:

    # 生成模拟的two_moons数据(这次的噪声较小)
    from sklearn.datasets import make_moons
    X, y = make_moons(n_samples=200, noise=0.05, random_state=0)
    # 将数据聚类成2个簇
    kmeans = KMeans(n_clusters=2)
    kmeans.fit(X)
    y_pred = kmeans.predict(X)
    # 画出簇分配和簇中心
    plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap=mglearn.cm2, s=60)
    plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
     marker='^', c=[mglearn.cm2(0), mglearn.cm2(1)], s=100, linewidth=2)
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    PCA、NMF和K-Means在人脸识别图像重建上的对比

    PCA:主成分分析。
    NMF:非负矩阵分解。
    可以理解为,二者都能够进行特征提取和数据降维,并都有助于数据可视化。

    from sklearn.datasets import fetch_lfw_people
    from sklearn.model_selection import train_test_split
    from sklearn.decomposition import PCA, NMF
    
    people = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
    image_shape = people.images[0].shape
    
    mask = np.zeros(people.target.shape, dtype=np.bool)
    for target in np.unique(people.target):
        mask[np.where(people.target == target)[0][:50]] = 1
    X_people = people.data[mask]
    y_people = people.target[mask]
    X_people = X_people / 255.
    
    X_train, X_test, y_train, y_test = train_test_split(
     X_people, y_people, stratify=y_people, random_state=0)
    nmf = NMF(n_components=100, random_state=0)
    nmf.fit(X_train)
    pca = PCA(n_components=100, random_state=0)
    pca.fit(X_train)
    kmeans = KMeans(n_clusters=100, random_state=0)
    kmeans.fit(X_train)
    X_reconstructed_pca = pca.inverse_transform(pca.transform(X_test))
    X_reconstructed_kmeans = kmeans.cluster_centers_[kmeans.predict(X_test)]
    X_reconstructed_nmf = np.dot(nmf.transform(X_test), nmf.components_)
    
    fig, axes = plt.subplots(3, 5, figsize=(8, 8),
     subplot_kw={'xticks': (), 'yticks': ()})
    fig.suptitle("Extracted Components")
    for ax, comp_kmeans, comp_pca, comp_nmf in zip(
     axes.T, kmeans.cluster_centers_, pca.components_, nmf.components_):
        ax[0].imshow(comp_kmeans.reshape(image_shape))
        ax[1].imshow(comp_pca.reshape(image_shape), cmap='viridis')
        ax[2].imshow(comp_nmf.reshape(image_shape))
    axes[0, 0].set_ylabel("kmeans")
    axes[1, 0].set_ylabel("pca")
    axes[2, 0].set_ylabel("nmf")
    fig, axes = plt.subplots(4, 5, subplot_kw={'xticks': (), 'yticks': ()},
     figsize=(8, 8))
    fig.suptitle("Reconstructions")
    for ax, orig, rec_kmeans, rec_pca, rec_nmf in zip(
     axes.T, X_test, X_reconstructed_kmeans, X_reconstructed_pca,
     X_reconstructed_nmf):
        ax[0].imshow(orig.reshape(image_shape))
        ax[1].imshow(rec_kmeans.reshape(image_shape))
        ax[2].imshow(rec_pca.reshape(image_shape))
        ax[3].imshow(rec_nmf.reshape(image_shape))
    axes[0, 0].set_ylabel("original")
    axes[1, 0].set_ylabel("kmeans")
    axes[2, 0].set_ylabel("pca")
    axes[3, 0].set_ylabel("nmf")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    在这里插入图片描述
    👆三种方法提取到的特征。
    在这里插入图片描述
    👆通过上述三种方法重建的图像。对于k均值,重建就是在训练集上找到最近的簇中心。

    利用KMeans做矢量化:可以用输入维度更多的簇来对数据编码

    对于two_moons数据集(上例中两个半月牙),由于只有两个维度,因此PCA和NMF失效(显然对二维数据作特征提取毫无意义,如果降低维度成为一维,那么将完全破坏原先的数据)。但是可以通过加入更多的簇中心(本例中n = 10),可以用k均值找到一种更具表现力的数据表示方法。

    X, y = make_moons(n_samples=200, noise=0.05, random_state=0)
    kmeans = KMeans(n_clusters=10, random_state=0)
    kmeans.fit(X)
    y_pred = kmeans.predict(X)
    plt.scatter(X[:, 0], X[:, 1], c=y_pred, s=60, cmap='Paired')
    plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=60,
     marker='^', c=range(kmeans.n_clusters), linewidth=2, cmap='Paired')
    plt.xlabel("Feature 0")
    plt.ylabel("Feature 1")
    print("Cluster memberships:\n{}".format(y_pred))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    👆设置200个样本点,组成两个半月牙。设置聚类的个数为10,来对数据进行聚类,结果如上图。此时,将到每个簇中心的距离作为特征,还可以得到一种更强有力的数据表示(通过kmeans构造了交叉项)。此时,应用线性模型,可以对两个月牙进行分类。

  • 相关阅读:
    4. RxJava过滤操作符
    牵手乌金石,共创财富梦—全国市场盛大启动
    大数据ClickHouse(十九):Flink 写入 ClickHouse API
    开放平台架构指南
    QT_C++_数据库
    awk入门教程
    【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(十六)
    nginx反向代理,负载均衡,动静分离配置
    【华为OD机试python】模拟消息队列【2023 B卷|100分】
    centos 普通用户操作 supervisor 报错
  • 原文地址:https://blog.csdn.net/fatfairyyy/article/details/126638175