广告

Python聚类方法与sklearn实战教程:面向数据分析师的完整案例与代码实现

1. 数据准备与算法选择

1.1 数据集与特征工程

在进行聚类分析之前,数据清洗与特征工程是奠定结果可解释性的基础。通常需要处理缺失值、离群点以及特征尺度不一致的问题,统一标准化或归一化可以显著提升大多数聚类算法的稳定性与可重复性。

对于数据分析师而言,选择合适的<输入特征是关键一步。高维度数据往往需要经过降维或特征选择,以减少冗余并提升簇的可分离性。常见做法包括标准化、PCA降维、特征缩放等。

from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split# 生成一个可控的聚类数据集作为案例
X, y = make_blobs(n_samples=500, centers=4, cluster_std=0.6, random_state=42)# 特征标准化:对大多数聚类算法更稳定
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

在实践中,数据分布与簇形状会影响算法的选择,因此初步探索阶段建议先对数据分布进行可视化检查(如二维投影)并尝试不同的距离度量。

1.2 常用评估指标概览

聚类的评估通常依赖于内部评估指标,如轮廓系数、Davies-Bouldin 指数与Calinski-Harabasz 指数等。轮廓系数越高越好,Davies-Bouldin 越低越好,Calinski-Harabasz 越高越好。

在实际案例中,不同算法的对比往往需要统一的评估基线,以便判断簇结构的一致性与稳定性。下面的代码演示了如何计算轮廓系数来比较不同簇数量下的聚类效果。

from sklearn.metrics import silhouette_score
import numpy as npdef evaluate_silhouette(X, labels):# 忽略噪声标签 -1(如 DBSCAN 的输出)mask = labels != -1if np.sum(mask) <= 1:return float('nan')return silhouette_score(X[mask], labels[mask])# 假设 X_scaled 已经准备好,labels 来自某个聚类算法
# score = evaluate_silhouette(X_scaled, labels)

1.3 代码示例:从数据准备到初步评估

以下代码片段展示了从数据生成、标准化到初步评估的一个连续流程,帮助你快速上手 Python 聚类方法与 sklearn 的实践。

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import numpy as np# 已有 X_scaled
k = 4
kmeans = KMeans(n_clusters=k, random_state=42)
labels = kmeans.fit_predict(X_scaled)score = silhouette_score(X_scaled, labels)
print("KMeans silhouette score:", score)

2. 常用聚类算法与 sklearn 实践

2.1 K-Means 与 MiniBatchKMeans

K-Means 是最常用的聚类算法之一,简单、速度快、便于解释,但对初始中心敏感且对簇形状有假设:簇应尽量接近圆形且性状相对均匀。

MiniBatchKMeans 适用于大规模数据场景,以小批量更新中心来提升速度,同时保持可接受的聚类质量。实际使用时可以通过调整 n_clusters、batch_size 等参数实现折中。

from sklearn.cluster import KMeans, MiniBatchKMeans# K-Means 示例
kmeans = KMeans(n_clusters=4, random_state=42).fit(X_scaled)
labels_kmeans = kmeans.labels_
inertia = kmeans.inertia_# MiniBatchKMeans 示例
mb_kmeans = MiniBatchKMeans(n_clusters=4, batch_size=100, random_state=42)
labels_mbk = mb_kmeans.fit_predict(X_scaled)
inertia_mb = mb_kmeans.inertia_

2.2 层次聚类(Agglomerative Clustering)

层次聚类通过逐步合并簇来形成“树状结构”。链接方式(如 ward、average、complete)决定了合并的准则,Ward 链接常用于最小化簇内方差

聚类结果易于直观解读,且不要求事先给定簇数量,便于探索不同层级的簇结构。对小型数据集,层次聚类可以提供稳定的可视化分辨率。

Python聚类方法与sklearn实战教程:面向数据分析师的完整案例与代码实现

from sklearn.cluster import AgglomerativeClusteringagg = AgglomerativeClustering(n_clusters=4, affinity='euclidean', linkage='ward')labels_agg = agg.fit_predict(X_scaled)

2.3 DBSCAN 与高斯混合模型

DBSCAN 是一种基于密度的聚类方法,能发现任意形状的簇且对离群点鲁棒,但对参数 eps 与 min_samples 的选择较为敏感。

高斯混合模型(Gaussian Mixture Model, GMM)把数据视为若干高斯分布的混合体,适合具有混合分布的数据,提供 soft clustering(每个样本对簇的属于度),便于更丰富的后续分析。

from sklearn.cluster import DBSCAN
from sklearn.mixture import GaussianMixture# DBSCAN 示例
db = DBSCAN(eps=0.5, min_samples=5).fit(X_scaled)
labels_db = db.labels_# GMM 示例
gmm = GaussianMixture(n_components=4, covariance_type='full', random_state=42)
gmm.fit(X_scaled)
labels_gmm = gmm.predict(X_scaled)

3. 面向数据分析师的完整案例:从数据加载到结果解读

3.1 数据集准备与特征工程

在正式案例中,我们通常从可控数据出发,以便清晰展示聚类过程与结果解读。下面的示例使用 make_blobs 生成四簇结构的数据,并进行标准化处理。

标准化是多种聚类算法的通用前置步骤,尤其是对距离敏感的算法尤为重要。

from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScalerX, y_true = make_blobs(n_samples=600, centers=4, cluster_std=0.6, random_state=0)scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

3.2 应用多种聚类方法并比较

为了得到对比视角,我们对 K-Means、DBSCAN、Agglomerative Clustering 以及 Gaussian Mixture 进行并行分析,并使用<轮廓系数作为统一评估标准。

需要注意:DBSCAN 可能输出多于一个簇,甚至将部分样本标记为噪声 (-1),这在解释结果时需要额外关注。

from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN
from sklearn.mixture import GaussianMixture
from sklearn.metrics import silhouette_score
import numpy as npdef run_and_score(method, X, **kwargs):if method == 'kmeans':model = KMeans(n_clusters=4, random_state=42, **kwargs).fit(X)labels = model.labels_elif method == 'agg':model = AgglomerativeClustering(n_clusters=4, **kwargs).fit(X)labels = model.labels_elif method == 'dbscan':model = DBSCAN(**kwargs).fit(X)labels = model.labels_elif method == 'gmm':model = GaussianMixture(n_components=4, random_state=42, **kwargs)model.fit(X)labels = model.predict(X)score = silhouette_score(X, labels) if len(set(labels)) > 1 else float('nan')return score, labelsmethods = [('kmeans', {}),('agg', {'linkage': 'ward'}),('dbscan', {'eps': 0.5, 'min_samples': 5}),('gmm', {})
]results = {}
for name, opts in methods:s, lab = run_and_score(name, X_scaled, **opts)results[name] = {'silhouette': s, 'labels': lab}print(results)

3.3 结果解读与可视化

对比结果时,轮廓系数越高代表簇之间的分离度越好,需要结合数据分布与业务场景进行解释。可视化有助于直观理解簇结构,我们可以将前两维进行散点图展示,并按不同算法的标签进行着色。

在本案例中,K-Means 与 GMM 往往在规则簇分布下表现较好,而 DBSCAN 能够捕捉到一些非球形簇但对参数更敏感;层次聚类提供多粒度解读,便于检验簇间层次关系。

import matplotlib.pyplot as pltdef plot_clusters(X, labels, title):plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=20)plt.title(title)plt.xlabel('Feature 1')plt.ylabel('Feature 2')plt.colorbar()plt.show()# 以 KMeans 为例进行可视化
plot_clusters(X_scaled, results['kmeans']['labels'], 'KMeans Clustering')

4. 参数调优与模型选择的策略

4.1 簇数量的确定方法

一个常见的起点是通过<Elbow 方法观察平方误差(inertia)随簇数量的变化趋势,找拐点处的明确下降变缓的位置作为候选簇数量。

此外,轮廓分析也可以用于在不同簇数下比较分离度,选择最大轮廓系数对应的簇数量。结合两者,可以提高选型的鲁棒性。

inertias = []
silhouettes = []
K = range(2, 8)
for k in K:km = KMeans(n_clusters=k, random_state=42).fit(X_scaled)inertias.append(km.inertia_)labels = km.labels_silhouettes.append(silhouette_score(X_scaled, labels))print(list(zip(K, inertias)))
print(list(zip(K, silhouettes)))

4.2 密度参数与距离度量的调整

对于 DBSCAN,eps(邻域半径)与 min_samples决定了簇的形状与数量。通常需要通过网格搜索或基于数据密度直方图来粗粒度地设定,再结合轮廓分析进行微调。

距离度量的选择也会影响聚类结果,欧氏距离常用但并非通用。对于带有相关性特征的数据,可以考虑对距离度量进行加权或使用曼哈顿距离等替代。

# 简单的网格搜索示例(仅示意,不是完整实现)
eps_values = [0.3, 0.5, 0.7]
min_samples_values = [3, 5, 7]
best = {'eps': None, 'min_samples': None, 'score': -np.inf}
for eps in eps_values:for ms in min_samples_values:db = DBSCAN(eps=eps, min_samples=ms).fit(X_scaled)labels = db.labels_if len(set(labels)) > 1:score = silhouette_score(X_scaled, labels)if score > best['score']:best = {'eps': eps, 'min_samples': ms, 'score': score}
print("Best DBSCAN params:", best)

4.3 跨方法对比与稳定性分析

在实际数据分析工作流中,跨方法对比是评估簇结构稳健性的关键,可以通过将同一数据集在多种算法下的标签进行对比,观察簇分离度的持续性与簇内一致性。

另外,重复实验与随机性控制(如设置 random_state、固定数据分割等)有助于降低偶然因素的影响,提升复现性。

from sklearn.metrics import adjusted_rand_score# 假设有 results 字典中多种方法的标签labels_k = results['kmeans']['labels']labels_gmm = results['gmm']['labels']labels_db = results['dbscan']['labels']# 计算两两之间的对比一致性ari_kl = sklearn.metrics.adjusted_rand_score(labels_k, labels_gmm)ari_kd = sklearn.metrics.adjusted_rand_score(labels_k, labels_db)print("ARI(KMeans, GMM):", ari_kl, "ARI(KMeans, DBSCAN):", ari_kd)

广告

后端开发标签