3.3 聚类任务


文档摘要

3.3 聚类任务 3. Scikit-learn 实践应用领域:3.3 聚类任务详解 3.3.1 聚类任务概述 聚类 (Clustering) 是一种无监督学习 (Unsupervised Learning) 技术,旨在将数据集中的样本划分为若干个“簇”(cluster),使得同一簇内的样本彼此相似,而不同簇的样本彼此相异。在没有预先标记的类别信息的情况下,聚类算法通过数据自身的内在性质,发现数据分布的规律,并将相似的数据点归为一类。 聚类任务的核心目标: 簇内相似性 (Intra-cluster similarity): 同一簇内的样本尽可能相似。 簇间差异性 (Inter-cluster dissimilarity): 不同簇的样本尽可能相异。

3.3 聚类任务

3. Scikit-learn 实践应用领域:3.3 聚类任务详解

3.3.1 聚类任务概述

聚类 (Clustering) 是一种无监督学习 (Unsupervised Learning) 技术,旨在将数据集中的样本划分为若干个“簇”(cluster),使得同一簇内的样本彼此相似,而不同簇的样本彼此相异。在没有预先标记的类别信息的情况下,聚类算法通过数据自身的内在性质,发现数据分布的规律,并将相似的数据点归为一类。

聚类任务的核心目标:

  • 簇内相似性 (Intra-cluster similarity): 同一簇内的样本尽可能相似。

  • 簇间差异性 (Inter-cluster dissimilarity): 不同簇的样本尽可能相异。

聚类任务的应用场景广泛,例如:

  • 客户细分 (Customer Segmentation): 将客户根据购买行为、 demographics 等信息划分为不同的群体,以便进行精准营销和个性化服务。

  • 图像分割 (Image Segmentation): 将图像中的像素根据颜色、纹理等特征划分为不同的区域,用于目标识别、图像编辑等。

  • 文档聚类 (Document Clustering): 将文档根据主题内容划分为不同的类别,用于信息检索、主题发现等。

  • 异常检测 (Anomaly Detection): 将偏离正常数据模式的数据点识别为异常值,用于欺诈检测、设备故障预警等。

  • 生物信息学 (Bioinformatics): 基因表达数据聚类、蛋白质结构聚类等,用于发现生物学规律。

  • 社交网络分析 (Social Network Analysis): 社区发现,将社交网络中的用户划分为不同的社群。

Scikit-learn 在聚类任务中的优势:

Scikit-learn 提供了丰富的聚类算法实现,并且接口统一、易于使用。其优势包括:

  • 多种聚类算法: 涵盖了常用的 K-Means、层次聚类、DBSCAN、谱聚类、高斯混合模型等多种算法,满足不同场景的需求。

  • 简洁的 API 设计: 使用 fit(), predict(), fit_predict() 等统一的接口,方便模型训练和预测。

  • 完善的评估指标: 提供了轮廓系数、Calinski-Harabasz 指数、Davies-Bouldin 指数等多种聚类评估指标,帮助评估聚类效果。

  • 与其他 Scikit-learn 模块的良好集成: 可以方便地与其他模块(如数据预处理、降维、模型选择等)结合使用,构建完整的机器学习流程。

3.3.2 常用聚类算法及代码实践 (Scikit-learn)

以下将详细介绍 Scikit-learn 中几种常用的聚类算法,并提供代码示例和详细解释。我们将使用 sklearn.cluster 模块中的聚类算法,并结合 matplotlibseaborn 进行可视化展示。

3.3.2.1 K-Means 聚类

算法原理:

K-Means 算法是一种经典的基于距离的聚类算法。它的目标是将数据集划分为 k 个簇,使得每个数据点都属于距离其最近的均值(簇中心)对应的簇。算法步骤如下:

  1. 初始化簇中心: 随机选择 k 个数据点作为初始簇中心。

  2. 分配簇: 对于每个数据点,计算其与 k 个簇中心的距离,将其分配到距离最近的簇。

  3. 更新簇中心: 对于每个簇,计算所有属于该簇的数据点的均值,将均值作为新的簇中心。

  4. 迭代: 重复步骤 2 和 3,直到簇中心不再发生明显变化或达到最大迭代次数。

代码实践 (Python + Scikit-learn):

import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.datasets import make_blobs # 1. 生成模拟数据 n_samples = 300 n_clusters = 3 random_state = 42 X, y = make_blobs(n_samples=n_samples, centers=n_clusters, random_state=random_state) # 2. 创建 KMeans 聚类器 kmeans = KMeans(n_clusters=n_clusters, init='k-means++', max_iter=300, n_init=10, random_state=random_state) # 3. 训练模型并进行聚类预测 y_kmeans = kmeans.fit_predict(X) # 4. 可视化聚类结果 plt.figure(figsize=(8, 6)) plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis') # 5. 绘制簇中心 centers = kmeans.cluster_centers_ plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75, marker='x') plt.title('K-Means Clustering') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show()

代码详解:

  1. 导入库: 导入 numpy 用于数值计算,matplotlib.pyplot 用于绘图,KMeans 类从 sklearn.cluster 导入,make_blobs 用于生成模拟聚类数据。

  2. 生成模拟数据 make_blobs:

    • n_samples=300: 生成 300 个数据点。

    • centers=n_clusters=3: 生成 3 个簇。

    • random_state=42: 设置随机种子,保证结果可复现。

    • make_blobs 函数返回 X (特征数据) 和 y (真实簇标签,这里仅用于生成数据,K-Means 是无监督学习,实际应用中没有真实标签)。

  3. 创建 KMeans 聚类器 KMeans(...):

    • n_clusters=n_clusters: 指定簇的数量为 3。

    • init='k-means++': 初始化簇中心的方法。'k-means++' 是一种更智能的初始化方法,可以加速收敛并提高聚类效果,比随机初始化 'random' 更优。

    • max_iter=300: 最大迭代次数,防止算法运行时间过长。

    • n_init=10: K-Means 算法会多次运行(这里是 10 次)并选择 inertia (簇内平方和) 最小的结果,以避免陷入局部最优解。

    • random_state=random_state: 设置随机种子,保证结果可复现。

  4. 训练模型并预测 kmeans.fit_predict(X):

    • fit_predict(X) 方法:先使用数据 X 训练 KMeans 模型 (fit),然后直接对 X 进行聚类预测 (predict),返回每个数据点所属的簇标签 y_kmeans
  5. 可视化聚类结果 plt.scatter(...):

    • plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis'): 绘制散点图。

      • X[:, 0], X[:, 1]: 分别取特征矩阵 X 的第一列和第二列作为 x 和 y 坐标。

      • c=y_kmeans: 使用聚类标签 y_kmeans 作为颜色,不同簇的点显示不同颜色。

      • s=50: 点的大小。

      • cmap='viridis': 颜色映射方案。

  6. 绘制簇中心 plt.scatter(centers[:, 0], centers[:, 1], ...):

    • centers = kmeans.cluster_centers_: 获取 KMeans 模型训练后得到的簇中心坐标。

    • plt.scatter(...): 绘制簇中心点。

      • c='red': 簇中心颜色设置为红色。

      • s=200: 簇中心点的大小。

      • alpha=0.75: 透明度。

      • marker='x': 簇中心点的形状设置为叉号。

K-Means 参数详解:

  • n_clusters: 最重要的参数! 指定要聚类的簇的数量 k。需要根据实际问题和数据特点进行选择,通常需要尝试不同的 k 值并结合评估指标来确定最佳 k 值。

  • init: 簇中心初始化方法。

    • 'k-means++' (默认): 智能初始化方法,通常效果更好。

    • 'random': 随机初始化。

    • ndarray: 可以手动指定初始簇中心,形状为 (n_clusters, n_features)

  • max_iter: 单次 K-Means 运行的最大迭代次数。

  • n_init: K-Means 算法运行的次数,最终选择 inertia 最小的结果。

  • random_state: 随机种子,用于控制随机过程,保证结果可复现。

  • algorithm: K-Means 算法的实现方式,可选 'auto', 'full', 'elkan'。通常 'auto' 会自动选择最佳算法。

K-Means 优点:

  • 算法简单,易于理解和实现。

  • 计算速度快,对于大规模数据集也相对有效率。

  • 常用且有效。

K-Means 缺点:

  • 需要预先指定簇的数量 k。 k 值的选择对聚类结果影响很大,但实际应用中 k 值往往难以确定。

  • 对初始簇中心敏感。 不同的初始簇中心可能导致不同的聚类结果,容易陷入局部最优解。 n_init 参数可以缓解这个问题。

  • 对异常值敏感。 异常值会影响簇中心的计算,导致聚类结果偏差。

  • 只适用于球形簇结构。 对于非球形、复杂形状的簇结构,K-Means 效果较差。

  • 假设各簇数据密度和方差相似。

3.3.2.2 层次聚类 (Hierarchical Clustering)

算法原理:

层次聚类是一种树状结构的聚类方法,它通过在不同层次对数据集进行划分,形成树状的聚类结构(树状图 Dendrogram)。层次聚类分为两种类型:

  • 凝聚型层次聚类 (Agglomerative Hierarchical Clustering): 自底向上,初始时每个数据点作为一个簇,然后逐步合并最相似的簇,直到满足停止条件(例如簇的数量达到预设值或达到某个相似度阈值)。

  • 分裂型层次聚类 (Divisive Hierarchical Clustering): 自顶向下,初始时所有数据点属于同一个簇,然后逐步分裂簇,直到满足停止条件。

Scikit-learn 中主要实现了凝聚型层次聚类,通过 AgglomerativeClustering 类实现。

代码实践 (Python + Scikit-learn):

import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import AgglomerativeClustering from sklearn.datasets import make_blobs # 1. 生成模拟数据 (同 K-Means 示例) n_samples = 300 n_clusters = 3 random_state = 42 X, y = make_blobs(n_samples=n_samples, centers=n_clusters, random_state=random_state) # 2. 创建 AgglomerativeClustering 聚类器 hierarchical = AgglomerativeClustering(n_clusters=n_clusters, linkage='ward') # 3. 训练模型并进行聚类预测 y_hierarchical = hierarchical.fit_predict(X) # 4. 可视化聚类结果 (同 K-Means 示例) plt.figure(figsize=(8, 6)) plt.scatter(X[:, 0], X[:, 1], c=y_hierarchical, s=50, cmap='viridis') plt.title('Hierarchical Clustering (Agglomerative)') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show()

代码详解:

代码结构与 K-Means 示例基本相同,主要区别在于聚类器的创建和算法名称。

  1. 创建 AgglomerativeClustering 聚类器 AgglomerativeClustering(...):

    • n_clusters=n_clusters: 指定最终簇的数量为 3。

    • linkage='ward': 连接准则 (Linkage Criteria)。 用于衡量簇之间距离的方法。

      • 'ward' (默认): Ward 方差最小化,倾向于产生大小相似的簇。

      • 'average': 平均连接,簇间距离定义为两个簇中所有点对之间距离的平均值。

      • 'complete' (最大连接): 完全连接,簇间距离定义为两个簇中点对之间距离的最大值。

      • 'single' (单连接): 单连接,簇间距离定义为两个簇中点对之间距离的最小值,容易产生链状簇。

层次聚类参数详解:

  • n_clusters: 重要参数! 指定最终簇的数量。

  • linkage: 连接准则。 决定了簇之间距离的计算方法,影响聚类结果。

  • affinity: 距离度量方式,默认为 'euclidean' (欧氏距离)。 可选 'euclidean', 'l1', 'l2', 'manhattan', 'cosine', 'precomputed' 等。 当 linkage='ward' 时,affinity 必须为 'euclidean'

  • distance_threshold: 距离阈值。 可以替代 n_clusters 使用,当簇之间的距离超过阈值时停止合并,形成簇。 如果设置了 distance_threshold,则 n_clusters 必须为 None

层次聚类优点:

  • 无需预先指定簇的数量。 可以通过树状图 (Dendrogram) 可视化聚类过程,并根据树状图选择合适的簇的数量。

  • 可以发现簇之间的层次关系。 树状结构可以清晰地展示簇的合并过程和簇之间的嵌套关系。

  • 对簇的形状没有太多假设。 比 K-Means 更适用于非球形簇结构。

层次聚类缺点:

  • 计算复杂度较高。 时间复杂度通常为 O(N^3) 或 O(N^2 log N),对于大规模数据集效率较低。

  • 对噪声和异常值敏感。

  • 结果可能受连接准则影响较大。 需要根据数据特点选择合适的连接准则。

3.3.2.3 DBSCAN 聚类 (Density-Based Spatial Clustering of Applications with Noise)

算法原理:

DBSCAN 是一种基于密度的聚类算法,它将簇定义为密度相连的点的最大集合。DBSCAN 可以发现任意形状的簇,并且能够识别噪声点 (outliers)。

核心概念:

  • 核心点 (Core Point): 如果一个点在其半径 ε (eps) 范围内包含至少 min_samples 个点(包括自身),则该点称为核心点。

  • 边界点 (Border Point): 如果一个点不是核心点,但它在某个核心点的 ε 邻域内,则该点称为边界点。

  • 噪声点 (Noise Point): 既不是核心点也不是边界点的点,被认为是噪声点。

  • 密度直达 (Directly Density-Reachable): 如果点 p 在核心点 q 的 ε 邻域内,则称 p 从 q 密度直达。

  • 密度可达 (Density-Reachable): 对于点 p 和点 q,如果存在一个点链 p1, p2, ..., pn,其中 p1=q, pn=p,且 pi+1 从 pi 密度直达,则称 p 从 q 密度可达。

  • 密度相连 (Density-Connected): 对于点 p 和点 q,如果存在核心点 o,使得 p 和 q 都从 o 密度可达,则称 p 和 q 密度相连。

算法步骤:

  1. 标记所有点为未访问。

  2. 遍历每个未访问的点 p:

    • 如果 p 已被访问,则跳过。

    • 标记 p 为已访问。

    • 找出 p 的 ε 邻域内的所有点 Neighbors(p)。

    • 如果 Neighbors(p) 的数量少于 min_samples,则标记 p 为噪声点。

    • 如果 Neighbors(p) 的数量大于等于 min_samples,则标记 p 为核心点,并创建一个新的簇 C,将 p 添加到 C。

    • 递归地访问 Neighbors(p) 中的每个未访问的点 p':

      • 标记 p' 为已访问。

      • 找出 p' 的 ε 邻域内的所有点 Neighbors(p')。

      • 如果 Neighbors(p') 的数量大于等于 min_samples,则将 Neighbors(p') 中的点添加到 Neighbors(p)。

      • 如果 p' 不是噪声点 (即 p' 是核心点或边界点),则将 p' 添加到簇 C。

  3. 重复步骤 2,直到所有点都被访问。

代码实践 (Python + Scikit-learn):

import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import DBSCAN from sklearn.datasets import make_moons # 1. 生成非球形模拟数据 (月牙形) n_samples = 300 random_state = 42 X, y = make_moons(n_samples=n_samples, noise=0.05, random_state=random_state) # 2. 创建 DBSCAN 聚类器 dbscan = DBSCAN(eps=0.3, min_samples=5) # 3. 训练模型并进行聚类预测 y_dbscan = dbscan.fit_predict(X) # 4. 可视化聚类结果 plt.figure(figsize=(8, 6)) plt.scatter(X[:, 0], X[:, 1], c=y_dbscan, s=50, cmap='viridis') plt.title('DBSCAN Clustering') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show() # 5. 统计噪声点数量 n_noise = list(y_dbscan).count(-1) # DBSCAN 将噪声点标记为 -1 print(f"Number of noise points: {n_noise}")

代码详解:

  1. 导入库: 与之前示例类似,导入必要的库。 make_moons 用于生成月牙形数据,适合展示 DBSCAN 的优势。

  2. 生成非球形模拟数据 make_moons:

    • make_moons(n_samples=n_samples, noise=0.05, random_state=random_state): 生成月牙形数据, noise 参数控制噪声水平。
  3. 创建 DBSCAN 聚类器 DBSCAN(...):

    • eps=0.3: 邻域半径 ε (epsilon)。 定义了点的邻域大小。 需要根据数据密度进行调整,ε 值过大可能将多个簇合并,ε 值过小可能将簇分裂或将簇内点标记为噪声。

    • min_samples=5: 最小样本数 min_samples 定义了核心点的条件。 min_samples 值越大,簇的密度要求越高,噪声点会增多。

  4. 训练模型并预测 dbscan.fit_predict(X): 与之前类似。 DBSCAN 将噪声点标记为 -1

  5. 可视化聚类结果 plt.scatter(...): 与之前类似。

  6. 统计噪声点数量: 统计 y_dbscan 中值为 -1 的点的数量,即噪声点数量。

DBSCAN 参数详解:

  • eps: 重要参数! 邻域半径 ε。 需要根据数据密度调整。 可以尝试不同的 eps 值,并观察聚类结果和噪声点数量的变化。

  • min_samples: 重要参数! 最小样本数。 也需要根据数据密度调整。 min_samples 值越大,簇的密度要求越高。

  • metric: 距离度量方式,默认为 'euclidean'。 可选 'euclidean', 'manhattan', 'chebyshev', 'minkowski', 'cosine', 'precomputed' 等。

  • algorithm: 近邻搜索算法,可选 'auto', 'ball_tree', 'kd_tree', 'brute'。 通常 'auto' 会自动选择最佳算法。

  • leaf_size:algorithm'ball_tree''kd_tree' 时,控制树的叶子节点大小,影响搜索效率。

DBSCAN 优点:

  • 无需预先指定簇的数量。 DBSCAN 可以自动发现簇的数量。

  • 可以发现任意形状的簇。 适用于非球形簇结构。

  • 能够识别噪声点。 对噪声数据不敏感。

  • 聚类结果鲁棒性较好。 对参数选择相对不敏感。

DBSCAN 缺点:

  • 对参数 epsmin_samples 敏感。 参数选择对聚类结果影响较大,需要根据数据特点进行调整。

  • 对密度不均匀的数据集聚类效果较差。 当簇的密度差异很大时,DBSCAN 可能无法有效聚类。

  • 高维数据中,维度灾难会导致距离计算困难,影响聚类效果。

3.3.3 聚类评估指标 (Scikit-learn)

由于聚类是无监督学习,没有真实的标签信息,因此评估聚类效果相对困难。 常用的聚类评估指标分为两类:

  • 内部评估指标 (Intrinsic Evaluation Metrics): 仅使用聚类结果自身的信息进行评估,例如簇内紧凑度、簇间分离度等。

  • 外部评估指标 (Extrinsic Evaluation Metrics): 需要使用真实的标签信息进行评估,例如当聚类结果需要与已知的类别信息进行比较时。 在实际应用中,真实标签往往是未知的,因此内部评估指标更为常用。

Scikit-learn 中常用的聚类评估指标 (sklearn.metrics 模块):

3.3.3.1 轮廓系数 (Silhouette Coefficient)

原理:

轮廓系数综合考虑了簇的凝聚度和分离度。 对于每个样本点 i,计算:

  • a(i): 样本 i 到同簇其他样本的平均距离 (簇内不相似度)。

  • b(i): 样本 i 到其他簇的所有样本的平均距离的最小值 (簇间不相似度)。

轮廓系数 s(i) 定义为:

s(i) = (b(i) - a(i)) / max(a(i), b(i))

轮廓系数的取值范围为 [-1, 1]:

  • s(i) 接近 1: 样本 i 聚类效果好,簇内相似且簇间分离。

  • s(i) 接近 0: 样本 i 位于簇的边界上,聚类效果一般。

  • s(i) 接近 -1: 样本 i 可能被误分到错误的簇中,聚类效果差。

代码实践 (Python + Scikit-learn):

import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score from sklearn.datasets import make_blobs # 1. 生成模拟数据 (同 K-Means 示例) n_samples = 300 n_clusters = 3 random_state = 42 X, y = make_blobs(n_samples=n_samples, centers=n_clusters, random_state=random_state) # 2. 创建 KMeans 聚类器并训练 kmeans = KMeans(n_clusters=n_clusters, random_state=random_state) y_kmeans = kmeans.fit_predict(X) # 3. 计算轮廓系数 silhouette_avg = silhouette_score(X, y_kmeans) print(f"Silhouette Score for K-Means: {silhouette_avg:.4f}") # --- 尝试不同簇数量 --- silhouette_scores = [] for n_clusters in range(2, 6): # 尝试簇数量 2 到 5 kmeans = KMeans(n_clusters=n_clusters, random_state=random_state) y_kmeans = kmeans.fit_predict(X) silhouette_avg = silhouette_score(X, y_kmeans) silhouette_scores.append(silhouette_avg) print(f"Silhouette Score for {n_clusters} clusters: {silhouette_avg:.4f}") # 4. 绘制轮廓系数随簇数量变化的曲线 plt.figure(figsize=(8, 6)) plt.plot(range(2, 6), silhouette_scores, marker='o') plt.xlabel('Number of Clusters') plt.ylabel('Silhouette Score') plt.title('Silhouette Score vs. Number of Clusters') plt.xticks(range(2, 6)) plt.grid(True) plt.show()

代码详解:

  1. 导入库: 导入 silhouette_score 函数从 sklearn.metrics 模块。

  2. 生成模拟数据、创建 KMeans 聚类器、训练模型: 与之前示例相同。

  3. 计算轮廓系数 silhouette_score(X, y_kmeans):

    • silhouette_score(X, y_kmeans) 函数计算数据集 X 基于聚类标签 y_kmeans 的平均轮廓系数。
  4. 尝试不同簇数量并计算轮廓系数: 循环尝试不同的簇数量,计算对应的轮廓系数,并将结果存储在 silhouette_scores 列表中。

  5. 绘制轮廓系数曲线: 绘制轮廓系数随簇数量变化的折线图,可以帮助选择最佳的簇数量。 通常轮廓系数越高,聚类效果越好。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U