Skip to content

Scikit Learn - 聚类方法

聚类 (Clustering) 是一种基础的无监督机器学习任务,它涉及将一组对象(样本)分组,使得同一组(称为簇,Cluster)中的对象彼此之间比与其它组中的对象更相似。本章探讨了 Scikit-learn 的 sklearn.cluster 模块中提供的各种聚类算法。

聚类方法对于发现无标签数据中的内在结构和模式至关重要。它们有助于完成客户细分、异常检测和图像压缩等任务。

K-Means 算法旨在将 n 个观测值划分为 k 个簇,其中每个观测值属于与其最近的平均值(簇中心)所在的簇。它是一种迭代算法,用于最小化簇内平方和(惯量)。簇的数量 k 必须预先指定。

Scikit-learn 提供了 sklearn.cluster.KMeans。关键参数包括 n_clusters(簇的数量,k)、init(初始化方法,‘k-means++’ 是默认推荐选项)和 n_init(K-Means 算法使用不同簇中心种子运行的次数,取最佳结果)。sample_weight 参数允许在计算簇中心时为样本分配不同的权重。

优点:简单,对于大型数据集计算效率高。适用于相似大小的球形、良好分离的簇。

缺点:需要指定 k。对初始簇中心位置敏感(尽管 ‘k-means++’ 缓解了这个问题)。难以处理非球形簇、密度不同或大小不均匀的簇。

Affinity Propagation 通过在样本对之间发送消息来创建簇,直到收敛。与 K-Means 不同,它不需要预先指定簇的数量。它识别代表簇的“代表点”(exemplars)。

Scikit-learn 提供了 sklearn.cluster.AffinityPropagation。关键参数包括 damping 和 preference。一个显著的缺点是其时间复杂度通常为 O(N^2 * T),其中 N 是样本数,T 是迭代次数,这使得它不适用于非常大的数据集。

优点:无需指定 k。可以找到非平面几何形状的簇。

缺点:计算成本高。性能取决于消息传递参数。

Mean Shift 是一种基于簇中心的算法,旨在发现样本平滑密度中的“斑点”。它的工作原理是通过将簇中心候选点更新为给定区域(由 bandwidth 定义)内点的均值。这个过程迭代进行直到收敛。簇的数量是自动确定的。

Scikit-learn 提供了 sklearn.cluster.MeanShift。bandwidth 参数至关重要;它决定了搜索区域的大小。如果未设置,则使用 estimate_bandwidth 进行估计。

优点:不假定特定的簇形状。自动确定簇的数量。

缺点:性能对 bandwidth 参数敏感。对于大型特征空间计算成本可能很高。

Spectral Clustering(谱聚类)在数据相似度矩阵(或亲和矩阵)上使用其特征值(谱)进行降维,然后在降维后的空间(通常使用 K-Means)进行聚类。它对于找到非凸簇非常有用。

Scikit-learn 提供了 sklearn.cluster.SpectralClustering。关键参数包括 n_clusters 和 affinity(如何构建亲和矩阵,例如 ‘rbf’,‘nearest_neighbors’)。不建议用于非常多的簇。

优点:对非平面几何形状(例如,同心圆)有效。可以处理复杂的簇形状。

缺点:对于大型数据集计算成本可能很高。性能取决于亲和矩阵的选择。

Hierarchical Clustering(层次聚类)构建簇的层次结构,通常表示为一棵树(树状图,dendrogram)。主要有两种类型:

  • Agglomerative(凝聚式):一种“自下而上”的方法,每个观测值开始时自成一个簇,然后随着层次结构的向上移动,成对的簇被合并。
  • Divisive(分裂式):一种“自上而下”的方法,所有观测值开始时都在一个簇中,然后随着层次结构的向下移动,递归地进行分裂。

Scikit-learn 提供了 sklearn.cluster.AgglomerativeClustering 用于凝聚式层次聚类。关键参数包括 n_clusters(或用于截断树状图的 distance_threshold)、linkage(‘ward’,‘complete’,‘average’,‘single’)和 affinity(用于计算连接的度量)。

优点:生成树状图,有助于理解数据结构。如果使用 distance_threshold,则无需指定 k。

缺点:计算成本可能很高(通常根据连接方法和实现不同,为 O(N^2 log N) 或 O(N^3))。在合并/分裂早期做出的决定是不可逆的。

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

Section titled “DBSCAN (Density-Based Spatial Clustering of Applications with Noise)”

DBSCAN (基于密度的含噪声空间聚类) 将紧密排列的点分组(有许多附近邻居的点),并将孤立在低密度区域的点标记为离群点。它可以找到任意形状的簇,并且不需要指定 k。

Scikit-learn 提供了 sklearn.cluster.DBSCAN。关键参数是 eps(两个样本点之间被视为邻居的最大距离)和 min_samples(一个点被视为核心点所需的邻域中的样本数)。

优点:可以找到任意形状的簇。对离群点具有鲁棒性(将它们识别为噪声)。无需指定 k。

缺点:性能对 eps 和 min_samples 敏感。难以处理密度不均匀的簇。

OPTICS (Ordering Points To Identify the Clustering Structure)

Section titled “OPTICS (Ordering Points To Identify the Clustering Structure)”

OPTICS (识别聚类结构的有序点集) 与 DBSCAN 相似,但解决了其主要缺点之一:检测密度不均匀数据中有意义的簇。它创建数据库的增强排序,表示其基于密度的聚类结构。然后可以使用此排序来提取簇。

Scikit-learn 提供了 sklearn.cluster.OPTICS。关键参数包括 min_samples、max_eps 和 xi。它可以被视为 DBSCAN 的泛化。

优点:比 DBSCAN 更好地处理密度不均匀的簇。生成可达性图,有助于理解簇结构。

缺点:比 DBSCAN 更复杂,难以解释。参数调优可能具有挑战性。

BIRCH (Balanced Iterative Reducing and Clustering using Hierarchies)

Section titled “BIRCH (Balanced Iterative Reducing and Clustering using Hierarchies)”

BIRCH (使用层次结构进行平衡迭代归约和聚类) 专为非常大的数据集设计。它以增量和动态方式对传入的多维指标数据点进行聚类,以尝试利用可用资源(内存和时间)产生最佳质量的聚类结果。它构建一个称为聚类特征树(Clustering Feature Tree, CFT)的树结构。

Scikit-learn 提供了 sklearn.cluster.Birch。关键参数包括 threshold、branching_factor 和 n_clusters(如果不需要进行全局聚类或对 CF 子簇应用其他聚类算法,可以将其设置为 None)。

优点:对于大型数据集高效(单次扫描)。很好地处理离群点。

缺点:仅适用于数值数据。簇倾向于球形。对数据点的顺序敏感。

聚类算法的选择取决于数据集的特征和问题的目标。以下是简要比较:

算法关键参数可伸缩性 (n_samples)用例 / 几何形状
K-Meansn_clusters, init非常好球形、大小均匀的簇。
Affinity Propagationdamping, preference差 (O(N^2))簇数量多,非平面几何形状,k 未知时。
Mean Shiftbandwidth差到中等寻找斑点,k 未知时。
Spectral Clusteringn_clusters, affinity中等非平面几何形状,复杂形状,少量簇。
Hierarchical (Agglomerative)n_clusters/distance_threshold, linkage中等到差 (O(N^2) 到 O(N^3))层次结构,当 k 未知时 (使用阈值)。
DBSCANeps, min_samples好 (O(N log N) 或 O(N^2))非平面几何形状,大小不均匀,存在噪声。
OPTICSmin_samples, xi, max_eps好 (类似于 DBSCAN)密度不均匀,存在噪声。
BIRCHthreshold, branching_factor, n_clusters非常好大型数据集,流式数据,球形簇。

在 Digits 数据集上应用 K-Means 聚类示例

Section titled “在 Digits 数据集上应用 K-Means 聚类示例”

让我们在 digits 数据集上应用 K-Means。这个数据集包含手写数字的图片。我们将尝试在不使用真实标签的情况下对它们进行聚类,然后将簇分配与真实标签进行比较,看看 K-Means 对相似数字的分组效果如何。

import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import load_digits
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, adjusted_rand_score, silhouette_score
from scipy.stats import mode
# Load digits dataset
digits = load_digits()
X, y_true = digits.data, digits.target
print(f"Data shape: {X.shape}") # (1797 samples, 64 features)
# Scale the data for better K-Means performance
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Apply K-Means clustering
# We know there are 10 digits (0-9), so set n_clusters=10
kmeans = KMeans(n_clusters=10, random_state=42, n_init='auto')
clusters_pred = kmeans.fit_predict(X_scaled)
print(f"Shape of cluster centers: {kmeans.cluster_centers_.shape}") # (10 clusters, 64 features)
# Evaluate clustering performance (if ground truth is available for reference)
# 1. Map predicted cluster labels to true labels
labels_mapped = np.zeros_like(clusters_pred)
for i in range(10):
mask = (clusters_pred == i)
# Assign the most frequent true label in that cluster
if np.any(mask):
labels_mapped[mask] = mode(y_true[mask], keepdims=True)[0]
accuracy = accuracy_score(y_true, labels_mapped)
print(f"Accuracy (after mapping clusters to true labels): {accuracy:.4f}")
# 2. Use clustering-specific metrics
ari_score = adjusted_rand_score(y_true, clusters_pred)
print(f"Adjusted Rand Index (ARI): {ari_score:.4f}")
# Silhouette Score (does not use true labels, measures cluster cohesion and separation)
sil_score = silhouette_score(X_scaled, clusters_pred)
print(f"Silhouette Score: {sil_score:.4f}")
# Note: Accuracy here is for illustrative purposes, showing how well clusters align with true classes.
# ARI and Silhouette Score are more standard for evaluating clustering itself.

输出 (如果 n_init 不是 ‘auto’ 或 random_state 发生变化,结果可能会略有不同,因为 K-Means 初始化是随机的)

Section titled “输出 (如果 n_init 不是 ‘auto’ 或 random_state 发生变化,结果可能会略有不同,因为 K-Means 初始化是随机的)”
Data shape: (1797, 64)
Shape of cluster centers: (10, 64)
Accuracy (after mapping clusters to true labels): 0.7902
Adjusted Rand Index (ARI): 0.6570
Silhouette Score: 0.1880

这个示例演示了 K-Means 的应用和结果评估。K-Means 学习到的簇中心代表了每个发现的数字组的“平均”图片。将这些中心可视化(例如,将它们重塑为 8x8 图片)可以深入了解算法学习到的内容。有关更多评估信息,请参阅“聚类性能评估”章节。