机器学习——聚类

本文通过实例展示了KMeans聚类算法与层次聚类在不同数据分布下的表现,包括原始数据、旋转数据、方差不等数据及数量不等数据的聚类效果对比,并深入探讨了数据分布对聚类结果的影响。

kMeans:

import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import KMeans


def expand(a, b):
    d = (b - a) * 0.1
    return a-d, b+d


if __name__ == "__main__":
    N = 400
    centers = 4
    data, y = ds.make_blobs(N, n_features=2, centers=centers, random_state=2)
    data2, y2 = ds.make_blobs(N, n_features=2, centers=centers, cluster_std=(1,2.5,0.5,2), random_state=2)
    data3 = np.vstack((data[y == 0][:], data[y == 1][:50], data[y == 2][:20], data[y == 3][:5]))
    y3 = np.array([0] * 100 + [1] * 50 + [2] * 20 + [3] * 5)

    cls = KMeans(n_clusters=4, init='k-means++')
    y_hat = cls.fit_predict(data)
    y2_hat = cls.fit_predict(data2)
    y3_hat = cls.fit_predict(data3)

    m = np.array(((1, 1), (1, 3)))
    data_r = data.dot(m)
    y_r_hat = cls.fit_predict(data_r)

    matplotlib.rcParams['font.sans-serif'] = [u'SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False
    cm = matplotlib.colors.ListedColormap(list('rgbm'))

    plt.figure(figsize=(9, 10), facecolor='w')
    plt.subplot(421)
    plt.title(u'原始数据')
    plt.scatter(data[:, 0], data[:, 1], c=y, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data, axis=0)
    x1_max, x2_max = np.max(data, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(422)
    plt.title(u'KMeans++聚类')
    plt.scatter(data[:, 0], data[:, 1], c=y_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(423)
    plt.title(u'旋转后数据')
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data_r, axis=0)
    x1_max, x2_max = np.max(data_r, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(424)
    plt.title(u'旋转后KMeans++聚类')
    plt.scatter(data_r[:, 0], data_r[:, 1], c=y_r_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(425)
    plt.title(u'方差不相等数据')
    plt.scatter(data2[:, 0], data2[:, 1], c=y2, s=30, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data2, axis=0)
    x1_max, x2_max = np.max(data2, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(426)
    plt.title(u'方差不相等KMeans++聚类')
    plt.scatter(data2[:, 0], data2[:, 1], c=y2_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(427)
    plt.title(u'数量不相等数据')
    plt.scatter(data3[:, 0], data3[:, 1], s=30, c=y3, cmap=cm, edgecolors='none')
    x1_min, x2_min = np.min(data3, axis=0)
    x1_max, x2_max = np.max(data3, axis=0)
    x1_min, x1_max = expand(x1_min, x1_max)
    x2_min, x2_max = expand(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.subplot(428)
    plt.title(u'数量不相等KMeans++聚类')
    plt.scatter(data3[:, 0], data3[:, 1], c=y3_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.grid(True)

    plt.tight_layout(2, rect=(0, 0, 1, 0.97))
    plt.suptitle(u'数据分布对KMeans聚类的影响', fontsize=18)
    # https://github.com/matplotlib/matplotlib/issues/829
    # plt.subplots_adjust(top=0.92)
    plt.show()

实验结果:
在这里插入图片描述

AgglomerativeClustering:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
from sklearn.neighbors import kneighbors_graph
import sklearn.datasets as ds
import warnings


def extend(a, b):
    return 1.05*a-0.05*b, 1.05*b-0.05*a


if __name__ == '__main__':
    warnings.filterwarnings(action='ignore', category=UserWarning)
    np.set_printoptions(suppress=True)
    np.random.seed(0)
    n_clusters = 4
    N = 400
    data1, y1 = ds.make_blobs(n_samples=N, n_features=2, centers=((-1, 1), (1, 1), (1, -1), (-1, -1)),
                              cluster_std=(0.1, 0.2, 0.3, 0.4), random_state=0)
    data1 = np.array(data1)
    n_noise = int(0.1*N)
    r = np.random.rand(n_noise, 2)
    data_min1, data_min2 = np.min(data1, axis=0)
    data_max1, data_max2 = np.max(data1, axis=0)
    r[:, 0] = r[:, 0] * (data_max1-data_min1) + data_min1
    r[:, 1] = r[:, 1] * (data_max2-data_min2) + data_min2
    data1_noise = np.concatenate((data1, r), axis=0)
    y1_noise = np.concatenate((y1, [4]*n_noise))

    data2, y2 = ds.make_moons(n_samples=N, noise=.05)
    data2 = np.array(data2)
    n_noise = int(0.1 * N)
    r = np.random.rand(n_noise, 2)
    data_min1, data_min2 = np.min(data2, axis=0)
    data_max1, data_max2 = np.max(data2, axis=0)
    r[:, 0] = r[:, 0] * (data_max1 - data_min1) + data_min1
    r[:, 1] = r[:, 1] * (data_max2 - data_min2) + data_min2
    data2_noise = np.concatenate((data2, r), axis=0)
    y2_noise = np.concatenate((y2, [3] * n_noise))

    mpl.rcParams['font.sans-serif'] = [u'SimHei']
    mpl.rcParams['axes.unicode_minus'] = False

    cm = mpl.colors.ListedColormap(['r', 'g', 'b', 'm', 'c'])
    plt.figure(figsize=(14, 12), facecolor='w')
    plt.cla()
    linkages = ("ward", "complete", "average")
    for index, (n_clusters, data, y) in enumerate(((4, data1, y1), (4, data1_noise, y1_noise),
                                                   (2, data2, y2), (2, data2_noise, y2_noise))):
        plt.subplot(4, 4, 4*index+1)
        plt.scatter(data[:, 0], data[:, 1], c=y, cmap=cm)
        plt.title('Prime', fontsize=17)
        plt.grid(b=True, ls=':')
        data_min1, data_min2 = np.min(data, axis=0)
        data_max1, data_max2 = np.max(data, axis=0)
        plt.xlim(extend(data_min1, data_max1))
        plt.ylim(extend(data_min2, data_max2))

        connectivity = kneighbors_graph(data, n_neighbors=7, mode='distance', metric='minkowski', p=2, include_self=True)
        connectivity = 0.5 * (connectivity + connectivity.T)
        for i, linkage in enumerate(linkages):
            ac = AgglomerativeClustering(n_clusters=n_clusters, affinity='euclidean',
                                         connectivity=connectivity, linkage=linkage)
            ac.fit(data)
            y = ac.labels_
            plt.subplot(4, 4, i+2+4*index)
            plt.scatter(data[:, 0], data[:, 1], c=y, cmap=cm)
            plt.title(linkage, fontsize=17)
            plt.grid(b=True, ls=':')
            plt.xlim(extend(data_min1, data_max1))
            plt.ylim(extend(data_min2, data_max2))
    plt.suptitle(u'层次聚类的不同合并策略', fontsize=20)
    plt.tight_layout(0.5, rect=(0, 0, 1, 0.95))
    plt.show()

实验结果:
在这里插入图片描述

### 机器学习聚类算法的集合与综述 聚类算法是机器学习领域中的一个重要分支,其主要目标是将未知标签数据集中的样本分成不同的组别(簇),使得同一组内的样本相似度较高,而不同组之间的相似度较低[^3]。以下是对几种常见聚类算法的总结和介绍: #### 1. 基于传统方法的聚类算法 传统的聚类算法主要包括 K-Means、层次聚类(Hierarchical Clustering)、DBSCAN(Density-Based Spatial Clustering of Applications with Noise)等。这些算法在结构化数据上表现良好,并且实现相对简单。 - **K-Means**:K-Means 是一种基于划分的聚类算法,它通过迭代优化簇中心来最小化簇内样本的距离平方和。其实现可以通过 Python 的 `sklearn.cluster.KMeans` 模块完成[^4]。 ```python from sklearn.cluster import KMeans kmeans = KMeans(n_clusters=3) kmeans.fit(X) ``` - **层次聚类**:层次聚类分为凝聚型和分裂型两种,分别从单个点开始逐步合并或从整体开始逐步分裂。这种方法可以生成树状图(Dendrogram),帮助理解数据的层级关系。 - **DBSCAN**:DBSCAN 是一种基于密度的聚类算法,能够识别任意形状的簇,并对噪声数据具有较强的鲁棒性。其核心思想是通过邻域密度定义簇。 #### 2. 基于深度学习的聚类算法 随着深度学习的发展,基于深度学习的聚类算法逐渐成为研究热点。这类算法结合了神经网络的强大特征提取能力与聚类的目标函数优化。 - **自编码器聚类**:自编码器(Autoencoder)是一种无监督学习模型,通过压缩和重建输入数据来学习低维表示。自编码器聚类通常结合 K-Means 或其他传统聚类方法使用,以提升聚类效果[^1]。 - **变分自编码器聚类**:变分自编码器(VAE)引入了概率生成模型的思想,能够在隐空间中生成新的数据样本。变分自编码器聚类通过最大化后验概率来实现聚类目标。 - **深度聚类网络(Deep Clustering Network, DCN)**:DCN 结合了深度神经网络和聚类算法,通过端到端的方式优化特征表示和聚类分配。 - **生成对抗网络聚类(GAN-based Clustering)**:生成对抗网络(GAN)通过生成器和判别器的对抗训练生成逼真的数据样本。GAN 聚类则利用生成器生成的分布信息进行聚类分析。 #### 3. 大规模数据处理中的聚类算法 对于大规模数据集,传统的聚类算法可能无法满足性能需求。Spark 等分布式计算框架提供了多种高效的聚类算法实现[^2]。 - **K-Means on Spark**:Spark MLlib 提供了分布式版本的 K-Means 实现,能够处理海量数据集。 - **Bisecting K-Means**:二分 K-Means 是一种递归的聚类方法,每次将一个簇划分为两个子簇,直到达到指定的簇数。 - **Gaussian Mixture Model (GMM)**:GMM 是一种基于概率模型的聚类方法,假设数据由多个高斯分布组成。 #### 4. 总结 聚类算法的选择取决于具体应用场景和数据特性。传统聚类算法适合结构化数据,而基于深度学习的聚类算法更适合复杂特征的学习。大规模数据处理场景下,分布式聚类算法能够显著提升效率。 ```python from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.5, min_samples=5) dbscan.fit(X) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值