美文网首页
第十六天 Kmean聚类

第十六天 Kmean聚类

作者: 未不明不知不觉 | 来源:发表于2018-12-22 20:35 被阅读23次

    我们前面说过, 聚类(clustering)是将数据集划分成组的任务,这些组叫作簇(cluster)。.其目标是划分数据,使得一个簇内的数据点非常相似且不同簇内的数据点非常不同。与分类算法类似,聚类算法为每个数据点分配(或预测)一个数字,表示这个点属于哪个簇

    k均值聚类

    k 均值聚类是最简单也最常用的聚类算法之一。它试图找到代表数据特定区域的簇中心(cluster center)。算法交替执行以下两个步骤:将每个数据点分配给最近的簇中心,然后将每个簇中心设置为所分配的所有数据点的平均值。如果簇的分配不再发生变化,那么算法结束。

    km.png

    簇中心用三角形表示,而数据点用圆形表示。颜色表示簇成员。我们指定要寻找三个簇,所以通过声明三个随机数据点为簇中心来将算法初始化(见图中“Initialization” /“初始化”)。然后开始迭代算法。首先,每个数据点被分配给距离最近的簇中心(见图中“Assign Points (1)” /“分配数据点(1)”)。接下来,将簇中心修改为所分配点的平均值(见图中“Recompute Centers (1)” /“重新计算中心(1)”)。然后将这一过程再重复两次。在第三次迭代之后,为簇中心分配的数据点保持不变,因此算法结束。

    使用sklearn进行k均值算法

    用 scikit-learn 应用 k 均值相当简单。下面我们将其应用于上图中的模拟数据。我们将KMeans 类实例化,并设置我们要寻找的簇个数 3。然后对数据调用 fit 方法 :

    from sklearn.datasets import make_blobs
    from sklearn.cluster import KMeans
    
    X,y = make_blobs(random_state=1)
    

    首先我们来查看生成的数据的可视化图形

    import matplotlib.pyplot as plt
    plt.scatter(x=X[:,0],y=X[:,1],c=y)
    

    得到下面的可视化图形

    我们可以看出来生成的数据为三个簇,那么们使用sklearn自带的kmean算法来对数据进行聚类

    X,y = make_blobs(random_state=1)
    kmeans = KMeans(n_clusters=3)
    kmeans.fit(X)
    labels = kmeans.labels_
    

    我们使用kmean算法得到的label来查看我们得到的聚类效果

    可以看出我们正确的分出了三个类,聚类效果很好。可以看到,聚类算法与分类算法有些相似,每个元素都有一个标签。但并不存在真实的标签,因此标签本身并没有先验意义

    我们可以尝试画出聚类后的数据的簇心

    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)
    

    我们得到下面的图片

    当然我们生成的数据是三个簇,kmeans算法也选的三个簇心,看起来有点碰巧了,我们可以选择不同的簇心数量来对数据进行聚类,例如选择2个簇心和5个簇心

    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])
    

    那么我们会得出下面的结果

    k均值的局限

    即使你知道给定数据集中簇的“正确”个数, k 均值可能也不是总能找到它们。每个簇仅由其中心定义,这意味着每个簇都是凸形(convex)。因此, 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")
    

    我们得到下面的聚类结果

    我们发现类0和类1都有一些远离簇的偏离点,k 均值还假设所有方向对每个簇都同等重要。图 3-28 显示了一个二维数据集,数据中包含明确分开的三部分。但是这三部分被沿着对角线方向拉长。由于 k 均值仅考虑到最近簇中心的距离,所以它无法处理这种类型的数据

    其他的例子

    • 在簇的平均值可被定义的情况下才能使用,可能不适用于某些应用;

    • 在 K-means 算法中 K 是事先给定的,这个 K 值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适;

    • 在 K-means 算法中,首先需要根据初始聚类中心来确定一个初始划分,然后对初始划分进行优化。这个初始聚类中心的选择对聚类结果有较大的影响,一旦初始值选择的不好,可能无法得到有效的聚类结果;

    • 该算法需要不断地进行样本分类调整,不断地计算调整后的新的聚类中心,因此当数据量非常大时,算法的时间开销是非常大的;

    • 若簇中含有异常点,将导致均值偏离严重(即:对噪声和孤立点数据敏感);

    • 不适用于发现非凸形状的簇或者大小差别很大的簇。

    bar状不规则形状

    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")
    

    得到下面的聚类结果

    半月形数据

    # 生成模拟的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.k均值聚类失效的例子

    相关文章

      网友评论

          本文标题:第十六天 Kmean聚类

          本文链接:https://www.haomeiwen.com/subject/auewkqtx.html