深入实战:在 Scikit-Learn 中比较不同聚类算法的性能表现

在机器学习的广阔天地里,当你刚开始接触这个领域时,最先遇到的往往是回归和分类问题。这两者都属于典型的监督学习,因为我们的目标是教会模型如何根据已有的标签来预测结果。但是,当我们拿到的数据集没有任何标签时,该怎么办呢?这就是无监督学习大显身手的时候了。

在无监督学习中,我们最重要的任务之一就是聚类——即根据数据内部的相似性,将未标记的数据划分为不同的组或“簇”。这对于在看似混乱的数据集中发现隐藏的模式至关重要。然而,聚类算法并非只有一种,面对不同的数据分布,选择哪种算法往往能决定项目的成败。

在今天的文章中,我们将以一个经典的“玩具数据集”为例,深入探讨并比较几种最主流的聚类算法。我们将一起学习如何使用 Scikit-Learn 库来实战这些算法,并观察它们在不同数据形态下的表现。你将看到,即使是相同的数据,不同的算法可能会给出截然不同的解释。同时,我们会融合 2026 年最新的开发理念,探讨如何用 AI 辅助工作流和现代工程化思维来提升我们的数据科学实践。

我们将探索的算法清单

为了让你全面了解聚类技术的多样性,我们将重点讨论以下四种在工业界和学术界广泛使用的算法,并结合最新的技术视角进行解读:

  • K-Means 聚类:最经典、最常用的基于质心的算法。
  • 层次聚类:通过构建树状图来发现数据的层次结构。
  • DBSCAN 聚类:基于密度的算法,能够发现任意形状的簇并识别噪声。
  • OPTICS 聚类:DBSCAN 的改进版,对参数更不敏感,适用于变化密度的数据。

现代开发范式:在 2026 年如何更高效地编写代码

在我们深入具体的算法之前,让我们先停下来思考一下“工具”的进化。回顾 2024 年之前,编写聚类代码往往需要我们在 Jupyter Notebook 和 IDE 之间频繁切换,手动调整参数,甚至还需要去 StackOverflow 上搜索报错信息。但在 2026 年,Vibe Coding(氛围编程) 已经成为了新的常态。

在我们的工作流中,Agentic AI 不再仅仅是一个辅助工具,而是成为了我们的“结对编程伙伴”。比如,当我们需要对 DBSCAN 的 INLINECODEb84f484e 参数进行网格搜索时,我们不再需要手写繁琐的 INLINECODEea77f419 循环,而是可以直接告诉 AI:“请为这段代码生成一个基于 Silhouette Score(轮廓系数)的参数优化器,并使用 Plotly 绘制交互式热力图。”

代码示例 0:AI 辅助的现代化实验环境配置

在这个例子中,我们将展示如何搭建一个符合 2026 年标准的实验环境。我们使用了最新的类型提示和日志配置,这不仅能让我们利用静态类型检查工具(如 MyPy)减少错误,还能让 AI 更好地理解我们的代码意图,从而提供更精准的建议。

# 导入必要的库
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import logging
from typing import Tuple, Optional

# 配置现代化日志系统,便于后续的可观测性分析
logging.basicConfig(
    level=logging.INFO,
    format=‘%(asctime)s - %(levelname)s - %(message)s‘
)
logger = logging.getLogger(__name__)

def load_and_preprocess_data(dataset_name: str = ‘iris‘) -> Tuple[np.ndarray, Optional[pd.DataFrame]]:
    """
    加载数据并进行标准化预处理。
    在 2026 年,我们把数据标准化视为一种强制性的安全措施,
    就像开车系安全带一样,以确保基于距离的算法不会因特征尺度不同而失效。
    """
    try:
        if dataset_name == ‘iris‘:
            df = sns.load_dataset(‘iris‘)
            x = df.drop(‘species‘, axis=1)
            # 数据标准化:这是生产环境中的关键一步
            from sklearn.preprocessing import StandardScaler
            scaler = StandardScaler()
            X_scaled = scaler.fit_transform(x.values)
            logger.info(f"成功加载并标准化 {dataset_name} 数据集")
            return X_scaled, df
        else:
            raise ValueError("暂不支持该数据集")
    except Exception as e:
        logger.error(f"数据加载失败: {e}")
        raise

# 执行加载
X, df_raw = load_and_preprocess_data()

算法一:K-Means 聚类与工程化挑战

K-Means 可以说是聚类算法界的“Hello World”。它的核心思想非常直观:迭代地将数据点分配给最近的质心,然后更新质心的位置,直到收敛。但在生产环境中,我们遇到的问题远比教科书复杂。

技术洞察与陷阱:你可能已经注意到,K-Means 对初始质心的选择非常敏感。虽然 k-means++ 算法缓解了这个问题,但在高维数据中,K-Means 仍然会遭遇“维度灾难”。此外,在大规模数据集上,标准的 K-Means 可能会成为性能瓶颈。在 2026 年,我们通常会选择使用 Mini-Batch K-Means,它不仅能处理流式数据,还能在保持几乎相同聚类质量的前提下,大幅减少计算时间。

#### 代码示例 1:寻找最佳的 K 值(结合 Silhouette 分析)

单纯依靠肘部法则往往不够客观。我们将结合轮廓系数来定量评估聚类质量。这就像是给聚类结果打分,分数越高,说明簇内的点越紧密,簇间的距离越远。

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

# 初始化存储列表
wcss = []
silhouette_scores = []

# 我们尝试从 2 到 10 个聚类的情况
# 注意:K=1 时轮廓系数无意义,所以从 2 开始
K_range = range(2, 11)

for i in K_range:
    # 使用 k-means++ 初始化,n_init=‘auto‘ 是 sklearn 1.4+ 的最佳实践
    kmeans = KMeans(n_clusters=i, init=‘k-means++‘, random_state=42, n_init=‘auto‘)
    kmeans.fit(X)
    
    # 记录 WCSS (惯性)
    wcss.append(kmeans.inertia_)
    
    # 计算轮廓系数
    # 返回的是所有样本点的平均轮廓系数,范围在 [-1, 1] 之间
    score = silhouette_score(X, kmeans.labels_)
    silhouette_scores.append(score)

# 绘制对比图
fig, ax1 = plt.subplots(figsize=(12, 6))

# 绘制 WCSS (左轴)
color = ‘tab:red‘
ax1.set_xlabel(‘Number of Clusters‘)
ax1.set_ylabel(‘WCSS‘, color=color)
ax1.plot(K_range, wcss, color=color, marker=‘o‘, label=‘WCSS (Elbow)‘)
ax1.tick_params(axis=‘y‘, labelcolor=color)

# 创建第二个 y 轴绘制轮廓系数
ax2 = ax1.twinx()  
color = ‘tab:blue‘
ax2.set_ylabel(‘Silhouette Score‘, color=color)  
ax2.plot(K_range, silhouette_scores, color=color, marker=‘x‘, linestyle=‘--‘, label=‘Silhouette Score‘)
ax2.tick_params(axis=‘y‘, labelcolor=color)

plt.title(‘Elbow Method vs Silhouette Score Analysis‘)
fig.tight_layout()  
plt.show()

结果解读:当你运行这段代码时,你会发现肘部法则和轮廓系数往往能互相印证。对于 Iris 数据集,你通常会在 K=3 处看到 WCSS 的拐点和 Silhouette 的峰值。在我们的项目中,我们倾向于优先参考 Silhouette Score,因为它提供了更数学化的评估标准。

算法二:层次聚类与可解释性

层次聚类试图在不同层次上构建聚类树。虽然它计算复杂度高(O(n^3)),但在 2026 年,随着我们越来越关注 AI 的可解释性(XAI),层次聚类的树状图再次焕发了生机。

实战见解:在生物信息学或供应链分析中,我们不仅想知道“属于哪一类”,还想知道“为什么这一类聚在一起”。树状图完美地展示了数据的分裂合并过程。对于中小型数据集(比如几千个客户分群),没有任何工具比树状图更能直观展示数据结构的。

#### 代码示例 2:绘制增强版树状图

我们将结合 Scipy 和 Matplotlib 绘制一个带有颜色标记的树状图,这能帮助我们更清晰地识别出自然的簇边界。

from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.cluster import AgglomerativeClustering

# 使用 ‘ward‘ 方法最小化方差
linked = linkage(X, ‘ward‘)

plt.figure(figsize=(15, 8))
# 设置阈值截断,以便在图中看到分类的效果(以 Iris 为例,这里设为较大值仅展示形态)
dendrogram(linked,
            orientation=‘top‘,
            distance_sort=‘descending‘,
            show_leaf_counts=True,
            truncate_mode=‘lastp‘, # 仅显示最后 p 个聚类,防止图过于庞大
            p=15,
            show_contracted=True)
plt.title(‘Hierarchical Clustering Dendrogram (Truncated)‘)
plt.xlabel(‘Cluster Size‘)
plt.ylabel(‘Distance (Ward)‘)
plt.axhline(y=15, color=‘r‘, linestyle=‘--‘) # 示例切断线
plt.show()

算法三与四:基于密度的聚类与复杂场景下的决断

K-Means 和层次聚类在面对像“月亮形”或“环形”这样复杂形状的数据时往往会失效。这时,DBSCAN 就派上用场了。而在 2026 年,随着数据来源的多样化(如物联网传感器数据),密度的变化更加剧烈,OPTICS 的地位也日益提升。

#### 代码示例 3:复杂分布与 DBSCAN 实战

让我们生成一个更具挑战性的数据集——两个交错的月亮。这模拟了现实中两个不规则的类别。

from sklearn.cluster import DBSCAN
from sklearn import datasets
import numpy as np

# 生成复杂的玩具数据
X_moons, _ = datasets.make_moons(n_samples=500, noise=0.08, random_state=42)

# DBSCAN 对参数非常敏感。这里我们手动调优后的参数
# eps: 邻域半径
# min_samples: 核心点所需的最小邻居数
# 技巧:可以通过计算 K-距离图来确定 eps

# 尝试一组参数
params = {‘eps‘: 0.15, ‘min_samples‘: 5}
db = DBSCAN(**params)
labels = db.fit_predict(X_moons)

# 统计噪声点的数量(标签为 -1)
n_noise = list(labels).count(-1)
print(f"估计的噪声点数量: {n_noise}")

# 可视化
plt.figure(figsize=(10, 6))
unique_labels = set(labels)
colors = [plt.cm.Spectral(each) for each in range(len(unique_labels))]

for k, col in zip(unique_labels, colors):
    if k == -1:
        # 黑色用于噪声
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = X_moons[class_member_mask]
    plt.plot(xy[:, 0], xy[:, 1], ‘o‘, markerfacecolor=tuple(col),
             markeredgecolor=‘k‘, markersize=6 if k == -1 else 14)

plt.title(f‘DBSCAN on Moons (eps={params["eps"]})‘)
plt.show()

性能优化与替代方案:如果你发现 DBSCAN 在你的数据集上运行极慢,可能是因为它构建了全量距离矩阵。在 2026 年,对于超大规模数据集,我们推荐使用 HDBSCAN(Hierarchical DBSCAN),它通常比标准的 DBSCAN 更稳健,且能更好地处理变密度情况,是 Scikit-Learn 生态系统之外的最佳补充。

总结与未来展望:从算法到应用

在这篇文章中,我们一起经历了一场从基础到进阶的算法之旅。我们学习了如何从零开始加载数据,并应用了四种截然不同的聚类策略。

回顾一下我们的决策经验:

  • K-Means:作为首选快速验证工具,但务必先标准化数据。
  • 层次聚类:当数据量较小且需要展示层级关系给非技术人员看时。
  • DBSCAN / OPTICS:当你发现数据分布不规则,或者需要剔除异常值(如欺诈检测)时。

给 2026 年开发者的建议:在处理实际问题时,不要只依赖一种算法。最好的做法是建立一个“模型评估流水线”。利用 LLM 驱动的调试 工具,你可以快速分析为何某个算法表现不佳。例如,你可以将聚类结果截图投喂给 AI,询问:“为什么这个聚类结果看起来一团糟?”AI 可能会提示你检查特征缩放,或者建议尝试基于密度的算法。

希望这篇教程不仅教会了你如何使用 Scikit-Learn,更让你理解了如何像一名资深工程师一样思考:在正确的场景,选择正确的工具,并融入现代化的开发流程。 现在,打开你的 IDE,试着在你的数据集上应用这些策略吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/29489.html
点赞
0.00 平均评分 (0% 分数) - 0