You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib点群自动检测与圈选问题及聚类数确定需求

解决KMeans聚类失效与自动识别聚类数问题

一、排查KMeans聚类失效的常见原因

  • 数据未标准化:KMeans基于欧氏距离计算,若特征维度的尺度差异过大,会被数值范围大的特征主导聚类结果。务必先对数据做标准化处理:
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    scaled_data = scaler.fit_transform(your_data)
    
  • 初始质心随机性影响:默认的k-means++初始化虽能降低随机性,但特殊分布数据可能仍受影响。增加初始化次数取最优结果:
    from sklearn.cluster import KMeans
    kmeans = KMeans(n_clusters=3, n_init=10, random_state=42)
    
  • 错误指定聚类数:如果硬设n_clusters=3但数据实际分布不符合,会导致聚类错乱,这就需要自动识别最优聚类数。

二、自动识别聚类数(含单一群体场景)

结合肘部法则、轮廓系数,搭配DBSCAN辅助判断,可覆盖无聚类(单一群体)的情况。

1. 肘部法则

计算不同k值下的SSE(平方误差和),曲线“肘部”对应最优k;若曲线从k=1到k=2下降平缓,说明数据为单一群体:

import matplotlib.pyplot as plt
sse = []
max_k = 10
for k in range(1, max_k+1):
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=42)
    kmeans.fit(scaled_data)
    sse.append(kmeans.inertia_)

plt.plot(range(1, max_k+1), sse)
plt.xlabel("聚类数k")
plt.ylabel("平方误差和(SSE)")
plt.title("肘部法则判断最优聚类数")
plt.show()

2. 轮廓系数判断

轮廓系数范围[-1,1],越接近1聚类效果越好。若k≥2时的最大系数低于阈值(如0.2),判定为单一群体:

from sklearn.metrics import silhouette_score

sil_scores = []
for k in range(2, max_k+1):
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=42)
    labels = kmeans.fit_predict(scaled_data)
    sil_scores.append(silhouette_score(scaled_data, labels))

# 确定最优聚类数
if max(sil_scores) < 0.2:
    optimal_k = 1
else:
    optimal_k = 2 + sil_scores.index(max(sil_scores))

3. DBSCAN辅助验证

DBSCAN无需指定聚类数,可直接检测聚类数量。若仅识别出1个核心聚类且噪声极少,判定为单一群体:

from sklearn.cluster import DBSCAN

dbscan = DBSCAN(eps=0.5, min_samples=5)  # eps和min_samples需根据数据调整
db_labels = dbscan.fit_predict(scaled_data)
unique_clusters = len(set(db_labels)) - (1 if -1 in db_labels else 0)
if unique_clusters == 1:
    optimal_k = 1

三、图表中圈选点群

确定最优k后,用凸包(Convex Hull)圈选每个聚类的边界:

from scipy.spatial import ConvexHull
import numpy as np

# 绘制结果
plt.figure(figsize=(8,6))
if optimal_k == 1:
    plt.scatter(your_data[:,0], your_data[:,1], c='steelblue', label='单一群体')
else:
    kmeans = KMeans(n_clusters=optimal_k, n_init=10, random_state=42)
    labels = kmeans.fit_predict(scaled_data)
    centroids = scaler.inverse_transform(kmeans.cluster_centers_)
    colors = ['#ff4444', '#00cc66', '#3366ff', '#ffaa00']
    
    for i in range(optimal_k):
        cluster_points = your_data[labels == i]
        plt.scatter(cluster_points[:,0], cluster_points[:,1], c=colors[i], label=f'聚类{i+1}')
        # 绘制凸包边界
        if len(cluster_points) >= 3:
            hull = ConvexHull(cluster_points)
            for simplex in hull.simplices:
                plt.plot(cluster_points[simplex, 0], cluster_points[simplex, 1], c=colors[i], linestyle='--')
        # 绘制质心
        plt.scatter(centroids[i,0], centroids[i,1], c='black', marker='x', s=120)

plt.legend()
plt.title("自动识别并圈选点群")
plt.show()

四、关键注意事项

  • 参数适配:DBSCAN的eps、min_samples需根据数据密度调整;标准化步骤可根据数据分布选择(如坐标点尺度一致可跳过);
  • 阈值灵活调整:轮廓系数的判定阈值需结合自身场景测试优化;
  • 多方法交叉验证:单一方法可能误判,建议结合肘部法则、轮廓系数、DBSCAN的结果综合确定最优聚类数。

内容的提问来源于stack exchange,提问作者Bast38

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:46:05