使用Calinski-Harabasz指数确定最佳聚类数:原理与Python实战

1次阅读
没有评论

共计 2402 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

聚类评估指标扫盲

刚开始做聚类分析时,最头疼的问题就是:” 到底该分成几类?” 常见的 K -means 算法需要我们预先指定聚类数量 K,但现实中这个数字往往是个未知数。这时候就需要聚类评估指标来帮我们做决策,它们就像是聚类质量的 ” 裁判员 ”。

使用 Calinski-Harabasz 指数确定最佳聚类数:原理与 Python 实战

  • 轮廓系数 (Silhouette):衡量每个样本与自身簇和其他簇的距离关系,取值在[-1,1] 之间,越大越好
  • DBI(Davies-Bouldin):计算簇内距离与簇间距离的比值,越小表示聚类效果越好
  • CH 指数(Calinski-Harabasz):今天我们重点讲解的主角,通过方差比来评估聚类效果

CH 指数的数学原理

CH 指数的核心思想非常直观——好的聚类应该让同一簇内的点尽可能紧凑,不同簇之间尽可能分散。用统计学的语言来说,就是最大化组间离散度与组内离散度的比值。

计算公式如下:

$$
CH = \frac{BGSS/(k-1)}{WGSS/(n-k)}
$$

其中:
– BGSS(Between-Group Sum of Squares):组间平方和,反映簇与簇之间的离散程度
– WGSS(Within-Group Sum of Squares):组内平方和,反映簇内部的紧凑程度
– k:当前聚类数量
– n:样本总数

这个公式可以理解为:用组间离散度的 ” 平均值 ”(除以 k -1)除以组内离散度的 ” 平均值 ”(除以 n -k)。CH 值越大,说明聚类效果越好。

Python 实战:两种实现方式

方法一:直接调用 sklearn

from sklearn.metrics import calinski_harabasz_score
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris

# 加载数据集
iris = load_iris()
X = iris.data

# 尝试不同的 K 值
k_range = range(2, 10)
ch_scores = []

for k in k_range:
    kmeans = KMeans(n_clusters=k, random_state=42)
    labels = kmeans.fit_predict(X)
    score = calinski_harabasz_score(X, labels)
    ch_scores.append(score)
    print(f"K={k}, CH score={score:.2f}")

方法二:手动实现

import numpy as np

def manual_ch_score(X, labels):
    n_samples = X.shape[0]
    n_clusters = len(np.unique(labels))

    # 计算全局均值
    global_mean = np.mean(X, axis=0)

    # 计算 BGSS
    bgss = 0
    unique_labels = np.unique(labels)
    for label in unique_labels:
        cluster_points = X[labels == label]
        cluster_size = len(cluster_points)
        cluster_mean = np.mean(cluster_points, axis=0)
        bgss += cluster_size * np.sum((cluster_mean - global_mean) ** 2)

    # 计算 WGSS
    wgss = 0
    for label in unique_labels:
        cluster_points = X[labels == label]
        cluster_mean = np.mean(cluster_points, axis=0)
        wgss += np.sum((cluster_points - cluster_mean) ** 2)

    # 计算 CH 指数
    ch = (bgss / (n_clusters - 1)) / (wgss / (n_samples - n_clusters))
    return ch

可视化与结果解读

import matplotlib.pyplot as plt

plt.plot(k_range, ch_scores, 'bo-')
plt.xlabel('Number of clusters (k)')
plt.ylabel('Calinski-Harabasz Score')
plt.title('CH Score for Different k Values')
plt.show()

通过可视化曲线,我们可以清楚地看到 CH 分数随 K 值变化的趋势。通常情况下,我们会选择 CH 分数出现 ” 峰值 ” 对应的 K 值作为最佳聚类数。在 Iris 数据集上,这个峰值通常出现在 K = 3 处,这与数据集真实的 3 个类别一致。

CH 指数的适用场景与局限

CH 指数虽然好用,但也不是万能的。它的几个重要前提和局限需要特别注意:

  1. 凸分布假设:CH 指数最适合评估 ” 球形 ” 或 ” 凸 ” 分布的簇。对于流形或非凸结构的数据(如环形分布),CH 指数可能失效

  2. 数据标准化:如果特征量纲不统一,必须预先标准化处理,否则距离计算会偏向数值大的特征

  3. 多峰值问题:有时 CH 曲线会出现多个局部峰值,这时候需要结合业务知识或尝试其他指标共同判断

  4. 噪声敏感:当数据中存在大量噪声点时,CH 指数可能会给出偏高的 K 值建议,因为噪声会被误认为是小簇

实战避坑指南

  • 标准化先行:使用 CH 指数前务必做标准化(StandardScaler 或 MinMaxScaler)
  • 交叉验证:可以尝试不同的初始化方式,观察 CH 分数的稳定性
  • 多指标验证:不要只依赖 CH 指数,建议结合轮廓系数、DBI 等指标综合判断
  • 业务常识:最终的 K 值选择要结合实际业务场景,不能完全依赖数学指标

思考题

当数据中存在噪声点时,CH 指数可能会产生什么偏差?如何改进?这里提供两个思路:

  1. 可以先使用 DBSCAN 等密度聚类算法去除噪声点,再用 CH 指数评估
  2. 可以尝试鲁棒性更强的评估指标,如 Silhouette 系数

希望这篇笔记能帮助你理解和使用 CH 指数。记住,没有放之四海而皆准的评估指标,关键是根据数据特性和业务需求选择合适的工具。

正文完
 0
评论(没有评论)