跳转至

16 - 聚类算法进阶

聚类算法进阶图

🎯 本章概述

本章深入探讨聚类算法的高级主题,包括密度聚类、层次聚类、谱聚类等。


🔍 DBSCAN 深入

核心概念

Text Only
已在 03-无监督学习.md 中介绍,这里补充更多细节

参数选择:
- eps: 邻域半径
  * 太小:大量噪声点
  * 太大:所有点聚为一类

- min_samples: 核心点最小邻居数
  * 通常设为维度数+1
  * 越大,核心点越少,聚类越稀疏

参数选择方法

Python
from sklearn.neighbors import NearestNeighbors
import numpy as np

# k-距离图选择eps
def plot_k_distance(X, k=4):
    neigh = NearestNeighbors(n_neighbors=k)
    neigh.fit(X)
    distances, _ = neigh.kneighbors(X)

    # 第k近邻的距离排序
    k_distances = np.sort(distances[:, k-1])

    plt.plot(k_distances)
    plt.ylabel(f'{k}-distance')
    plt.xlabel('Points (sorted)')
    plt.show()

    # 拐点处的距离作为eps
    return k_distances

# 使用
k_distances = plot_k_distance(X, k=4)
# 选择拐点处的值作为eps

OPTICS (Ordering Points To Identify Clustering Structure)

Text Only
DBSCAN的改进:
- 不需要指定全局eps
- 可以处理不同密度的簇
- 生成可达距离图

核心概念:
- 核心距离: 成为核心点所需的最小半径
- 可达距离: 点到最近核心点的距离
Python
from sklearn.cluster import OPTICS

optics = OPTICS(min_samples=5, xi=0.05, min_cluster_size=0.05)
labels = optics.fit_predict(X)

# 可视化可达距离
plt.plot(optics.reachability_[optics.ordering_])
plt.title('Reachability Plot')
plt.show()

🌳 层次聚类进阶

链接准则比较

Text Only
已在 03-无监督学习.md 中介绍,这里详细对比

单链接 (Single Linkage):
- 优点:可以处理非球形簇
- 缺点:链式效应,对噪声敏感

全链接 (Complete Linkage):
- 优点:紧凑的球形簇
- 缺点:倾向于打破大簇

平均链接 (Average Linkage):
- 平衡单链接和全链接
- 计算复杂度高

Ward链接:
- 最小化簇内方差
- 适合球形、等大小簇

BIRCH (Balanced Iterative Reducing and Clustering)

Text Only
适合大规模数据的层次聚类

特点:
- 单次扫描数据
- 使用CF树 (Clustering Feature Tree)
- 内存高效

CF向量:
- N: 子簇中点的数量
- LS: 线性和
- SS: 平方和
Python
from sklearn.cluster import Birch

birch = Birch(n_clusters=3, threshold=0.5, branching_factor=50)
birch.fit(X)
labels = birch.predict(X)

🎵 谱聚类 (Spectral Clustering)

核心思想

Text Only
将数据映射到特征空间,在特征空间进行聚类

步骤:
1. 构建相似度图(邻接矩阵)
2. 计算拉普拉斯矩阵
3. 特征分解,取前k个特征向量
4. 在特征向量构成的空间进行K-Means

算法详解

Python
from sklearn.cluster import SpectralClustering
from sklearn.metrics.pairwise import rbf_kernel

# 方法1:使用sklearn
sc = SpectralClustering(
    n_clusters=3,
    affinity='rbf',  # 或 'nearest_neighbors'
    gamma=1.0,
    assign_labels='kmeans'
)
labels = sc.fit_predict(X)

# 方法2:手动实现
def spectral_clustering(X, n_clusters, gamma=1.0):
    # 1. 构建相似度矩阵 (RBF核)
    W = rbf_kernel(X, gamma=gamma)

    # 2. 计算度矩阵
    D = np.diag(W.sum(axis=1))

    # 3. 计算归一化拉普拉斯矩阵
    D_inv_sqrt = np.diag(1.0 / np.sqrt(W.sum(axis=1)))
    L_sym = np.eye(len(X)) - D_inv_sqrt @ W @ D_inv_sqrt

    # 4. 特征分解
    eigenvalues, eigenvectors = np.linalg.eigh(L_sym)

    # 5. 取前k个特征向量
    X_embedded = eigenvectors[:, 1:n_clusters+1]

    # 6. K-Means聚类
    from sklearn.cluster import KMeans
    kmeans = KMeans(n_clusters=n_clusters)
    labels = kmeans.fit_predict(X_embedded)

    return labels

应用场景

Text Only
适合:
- 非凸形状的簇
- 簇大小不均衡
- 有噪声的数据

不适合:
- 大规模数据(计算复杂度高)
- 高维数据(需要降维预处理)

🎯 高斯混合模型 (GMM) 进阶

模型选择

Python
from sklearn.mixture import GaussianMixture
import numpy as np

# 使用BIC选择最佳组件数
n_components_range = range(1, 10)
bics = []

for n_components in n_components_range:
    gmm = GaussianMixture(n_components=n_components, random_state=42)
    gmm.fit(X)
    bics.append(gmm.bic(X))

# 选择BIC最小的模型
best_n = n_components_range[np.argmin(bics)]
print(f"最佳组件数: {best_n}")

# 可视化BIC曲线
plt.plot(n_components_range, bics)
plt.xlabel('Number of Components')
plt.ylabel('BIC')
plt.show()

协方差类型

Text Only
'full': 每个组件有自己的协方差矩阵
'tied': 所有组件共享协方差矩阵
'diag': 每个组件有自己的对角协方差矩阵
'spherical': 每个组件有自己的单一方差

📊 聚类评估进阶

内部指标

Python
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score

# 轮廓系数 (-1到1,越大越好)
sil_score = silhouette_score(X, labels)

# Calinski-Harabasz指数 (越大越好)
ch_score = calinski_harabasz_score(X, labels)

# Davies-Bouldin指数 (越小越好)
db_score = davies_bouldin_score(X, labels)

稳定性评估

Python
from sklearn.metrics import adjusted_rand_score
import numpy as np

def clustering_stability(X, clusterer, n_bootstrap=10):
    """评估聚类稳定性"""
    labels_original = clusterer.fit_predict(X)
    scores = []

    for _ in range(n_bootstrap):
        # Bootstrap采样
        indices = np.random.choice(len(X), size=len(X), replace=True)
        X_resampled = X[indices]
        labels_resampled = clusterer.fit_predict(X_resampled)

        # 比较引导样本上的聚类与原始聚类的一致性
        score = adjusted_rand_score(labels_original[indices], labels_resampled)
        scores.append(score)

    return np.mean(scores), np.std(scores)

🎯 高级主题

半监督聚类

Text Only
利用少量标签信息指导聚类

方法:
1. 约束K-Means: must-link/cannot-link约束
2. 种子K-Means: 使用标签初始化
3. 约束GMM: 带约束的EM算法
Python
from sklearn.semi_supervised import LabelSpreading

# 先进行半监督学习
label_spread = LabelSpreading(kernel='knn', alpha=0.2)
label_spread.fit(X, y_partial)  # y_partial包含-1(未标记)
labels = label_spread.transduction_

流聚类 (Streaming Clustering)

Text Only
MiniBatchKMeans:
- 每次使用小批量数据更新
- 适合大规模、流式数据
Python
from sklearn.cluster import MiniBatchKMeans

mbk = MiniBatchKMeans(n_clusters=3, batch_size=100)

# 增量训练
for batch in stream_data():
    mbk.partial_fit(batch)

labels = mbk.predict(X)

💡 聚类算法选择指南

Text Only
数据规模:
- 小数据 (<1000): 所有方法
- 中数据 (1K-100K): K-Means, DBSCAN, 层次聚类
- 大数据 (>100K): MiniBatchKMeans, BIRCH

簇形状:
- 球形: K-Means, GMM
- 任意形状: DBSCAN, 谱聚类, 单链接层次聚类
- 不同密度: OPTICS, 谱聚类

其他考虑:
- 需要概率: GMM
- 需要层次结构: 层次聚类
- 有噪声: DBSCAN, 谱聚类
- 需要稳定性: 多次运行取平均

🎯 总结

Text Only
聚类算法演进:
K-Means → 层次聚类 → DBSCAN → 谱聚类 → GMM

关键要点:
1. 没有 universally best 算法
2. 理解数据特点选择算法
3. 多种评估指标综合判断
4. 可视化验证结果

实践建议:
- 先用K-Means和DBSCAN探索
- 使用多种评估指标
- 可视化结果验证
- 考虑领域知识

下一步:学习 17-图神经网络.md,进入深度学习新领域!