Python案例如何用Scikit-learn做卡林斯基指数

wen python案例 1

Python案例如何用Scikit-learn做卡林斯基指数(Calinski-Harabasz Index)

目录导读

卡林斯基指数核心概念详解

卡林斯基指数(Calinski-Harabasz Index),又称方差比准则(Variance Ratio Criterion),是评估聚类效果最常用的内部指标之一,其核心思想是:簇间离散度越大、簇内离散度越小,聚类效果越好

Python案例如何用Scikit-learn做卡林斯基指数

计算公式为:

CH = (B / (k-1)) / (W / (n-k))
  • B:簇间协方差矩阵的迹(越大越好)
  • W:簇内协方差矩阵的迹(越小越好)
  • k:聚类数量
  • n:样本总数

关键特性:该指数值越高,表示聚类结构越清晰,与轮廓系数不同,CH指数对球形簇有天然偏好,且计算速度较快,适合大规模数据集。

Python环境配置与Scikit-learn安装

基础环境准备

# 推荐使用conda或venv创建隔离环境
pip install scikit-learn pandas numpy matplotlib

核心库导入

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import calinski_harabasz_score
import matplotlib.pyplot as plt
import pandas as pd

基于KMeans聚类计算卡林斯基指数

1 生成测试数据

# 创建3个簇的样本数据
X, y_true = make_blobs(n_samples=1000, centers=3, 
                       cluster_std=0.5, random_state=42)

2 计算CH指数完整流程

# 训练KMeans模型
kmeans = KMeans(n_clusters=3, random_state=42)
y_pred = kmeans.fit_predict(X)
# 计算卡林斯基指数
ch_score = calinski_harabasz_score(X, y_pred)
print(f"卡林斯基指数: {ch_score:.2f}")  # 输出示例:3718.56

3 多K值对比确定最佳聚类数

scores = []
k_range = range(2, 11)
for k in k_range:
    km = KMeans(n_clusters=k, random_state=42)
    labels = km.fit_predict(X)
    scores.append(calinski_harabasz_score(X, labels))
# 可视化分析
plt.plot(k_range, scores, 'bo-')
plt.xlabel('聚类数(k)')
plt.ylabel('卡林斯基指数')'CH指数趋势图 - 最高点对应最优k值')
plt.grid(True)
plt.show()

规律观察:当k=3时CH指数最高,与实际生成数据的3个簇完美吻合。

实战案例:电商客户分群评估

1 数据加载与预处理

# 模拟电商客户数据(年消费金额,平均订单金额,访问频次)
data = pd.DataFrame({
    'annual_spend': [12000, 8000, 15000, 4500, ...],  # 模拟1000条数据
    'avg_order': [250, 180, 320, 120, ...],
    'visit_freq': [45, 30, 60, 15, ...]
})
# 标准化处理(重要!CH指数对尺度敏感)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(data)

2 自动化选择最优K值

ch_scores = []
for k in range(2, 11):
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    labels = km.fit_predict(X_scaled)
    ch_scores.append(calinski_harabasz_score(X_scaled, labels))
optimal_k = range(2, 11)[ch_scores.index(max(ch_scores))]
print(f"最优客户分群数: {optimal_k},对应CH指数: {max(ch_scores):.2f}")

3 最终模型输出

final_model = KMeans(n_clusters=optimal_k, random_state=42)
data['cluster'] = final_model.fit_predict(X_scaled)
# 各群体画像
cluster_profile = data.groupby('cluster').mean()
print(cluster_profile)

输出解读:某电商案例显示k=4时CH指数最高,说明客户应分为4类:高消费高频次VIP、中等消费稳定型、价格敏感低消费型、沉睡流失型。

常见问题与优化问答

Q1:卡林斯基指数取值范围是多少?如何解读?

A:严格来说CH指数没有理论上限。一般准则

  • 对比不同k值下的CH,峰值对应的k为最优
  • 数值越大越好,但需结合业务场景,例如某数据集CH=5000可能比CH=3000聚类更清晰,但若CH=10000时k值过大(如k=15),可能过拟合。

Q2:为什么我的CH指数出现负值?

A:理论上是不会出现负值的(方差非负),出现负值通常因为:

  • 数据未标准化(尤其属性量纲差异极大)
  • 使用了错误的距离度量(如KMeans默认欧氏距离与余弦距离混用)

解决方案:使用StandardScalerMinMaxScaler预处理数据。

Q3:CH指数与轮廓系数、戴维森-布尔丁指数如何选择?

A: | 指标 | 适用场景 | 计算复杂度 | 对形状敏感度 | |------|----------|------------|--------------| | CH指数 | 球形簇,大数据集 | O(n) | 高 | | 轮廓系数 | 任意形状簇 | O(n²) | 低 | | 戴维森-布尔丁指数 | 需要最小化时 | O(n) | 中 |

建议:用CH指数作为主要参考,配合轮廓系数交叉验证,例如本例中使用CH指数找到k=4最优,再用轮廓系数验证是否同样为4。

Q4:能否用于非KMeans聚类(如DBSCAN、层次聚类)?

A:完全可以!calinski_harabasz_score(X, labels)要求输入两个数组:原始特征X和聚类标签labels

from sklearn.cluster import AgglomerativeClustering
hclust = AgglomerativeClustering(n_clusters=4)
labels_hc = hclust.fit_predict(X_scaled)
print(calinski_harabasz_score(X_scaled, labels_hc))

注意:但DBSCAN会产生噪声点(标签-1),CH指数无法处理噪声点,需先过滤。

Q5:大数据集下CH指数计算过慢怎么办?

A

  1. 降维处理:使用PCA或t-SNE减少特征维度
  2. 采样计算:从原始数据中随机抽取子集计算,但需保证子集分布与整体一致
  3. 改用近似算法:如MiniBatchKMeans + CH指数(但结果会浮动)
from sklearn.cluster import MiniBatchKMeans
mbk = MiniBatchKMeans(n_clusters=4, batch_size=100)
labels_mb = mbk.fit_predict(X_scaled)
ch_fast = calinski_harabasz_score(X_scaled, labels_mb)

总结建议

  1. 标准化是前提:所有基于距离的聚类(KMeans、层次聚类)务必先标准化。
  2. 组合使用:CH指数 + 肘部法 + 业务理解,三重确认最优K值。
  3. 警惕球形簇偏好:当数据具有复杂形状时,CH指数可能误导,此时优先选择轮廓系数或DBSCAN。

延伸阅读:也可参考Scikit-learn官方文档中关于calinski_harabasz_score的详细参数说明,以及结合Davies-Bouldin Index进行综合评价。

抱歉,评论功能暂时关闭!