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

PCA降维后K-means聚类中心偏离集群问题求助

聚类异常问题排查与解决

问题背景

数据集包含约1200条观测值、25个特征,计划先通过PCA降维再执行K-means聚类,但出现两个异常:

  • 聚类中心显示位置远离对应集群
  • 调整k值后集群划分无有效变化

异常现象展示

k=3时的聚类可视化

k=3聚类可视化

k=2时的聚类中心结果

array([[-0.10621571, -0.33357351, -0.31757225, -0.41859302, -0.34180062,
        -0.40582209, -0.39882614, -0.41326583, -0.40258176, -0.27391731,
        -0.38387384, -0.373283  ,  0.30265487, -0.16514534, -0.38956931,
        -0.18097048, -0.38672061, -0.38919503, -0.3935108 , -0.26672966,
        -0.3337329 , -0.27723583, -0.29186106, -0.32065177, -0.29334765],
       [ 0.47938423,  1.50551998,  1.43330135,  1.88923921,  1.54265145,
         1.8316001 ,  1.80002522,  1.86519597,  1.81697549,  1.23627317,
         1.73254086,  1.68474116, -1.36597464,  0.74535178,  1.75824629,
         0.8167755 ,  1.74538923,  1.75655704,  1.77603542,  1.20383309,
         1.50623935,  1.25125068,  1.31725887,  1.44720019,  1.3239683 ]])

k=2时的聚类可视化

k=2聚类可视化

实现代码

kmeans = KMeans(n_clusters=2, random_state=0).fit(scores_data)
metadata['cluster'] = kmeans.labels_

# Apply PCA to the data to visualize the clusters in 2D
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scores_data)

plt.scatter(pca_result[:, 0], pca_result[:, 1], c=metadata['cluster'], s=50)

cluster_centers = kmeans.cluster_centers_
plt.scatter(cluster_centers[:, 0], cluster_centers[:, 1], c='red', marker='o')

# Add labels to the cluster centers
for i, center in enumerate(cluster_centers):
    plt.annotate(f"Cluster {i}", (center[0], center[1]), 
                 textcoords="offset points", 
                 xytext=(0,10), ha='center', fontsize=20)

plt.rcParams["figure.figsize"] = (16,11)
plt.show()

问题原因分析

  1. 聚类中心可视化逻辑错误:代码直接将25维的聚类中心取前两维绘制,但PCA仅对原始数据做了降维,高维聚类中心未经过同一PCA模型转换,导致坐标不在PCA的二维空间内,显示位置偏离实际集群。
  2. 数据未标准化:K-means是基于距离的算法,特征尺度差异大会让聚类结果被尺度大的特征主导。从k=2的聚类中心可看出,不同特征的数值范围差异明显(如第13个特征,两个中心值差4倍以上),未标准化的数据会导致K-means收敛到不合理的聚类,调整k值也无法得到有效变化。
  3. 流程不符合预期:原计划是先PCA降维再聚类,但实际代码先在高维数据上执行K-means,再用PCA降维可视化,流程顺序错误也会影响聚类效果的合理性。

解决办法

1. 修正聚类中心的可视化方式

将高维聚类中心通过同一PCA模型转换到二维空间:

# 先拟合PCA并转换原始数据
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scores_data)

# 执行K-means聚类
kmeans = KMeans(n_clusters=2, random_state=0).fit(scores_data)
metadata['cluster'] = kmeans.labels_

# 将聚类中心转换到PCA二维空间
cluster_centers_pca = pca.transform(kmeans.cluster_centers_)

# 可视化
plt.scatter(pca_result[:, 0], pca_result[:, 1], c=metadata['cluster'], s=50)
plt.scatter(cluster_centers_pca[:, 0], cluster_centers_pca[:, 1], c='red', marker='o')

for i, center in enumerate(cluster_centers_pca):
    plt.annotate(f"Cluster {i}", (center[0], center[1]), 
                 textcoords="offset points", 
                 xytext=(0,10), ha='center', fontsize=20)

plt.rcParams["figure.figsize"] = (16,11)
plt.show()

2. 对数据做标准化处理

在PCA或K-means之前,使用StandardScaler统一特征尺度:

from sklearn.preprocessing import StandardScaler

# 标准化数据
scaler = StandardScaler()
scaled_data = scaler.fit_transform(scores_data)

# 后续PCA和K-means使用标准化后的数据
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scaled_data)

kmeans = KMeans(n_clusters=2, random_state=0).fit(scaled_data)
metadata['cluster'] = kmeans.labels_

cluster_centers_pca = pca.transform(kmeans.cluster_centers_)

# 可视化代码同上

3. 调整为“先降维再聚类”的流程(可选)

如果严格按照原计划执行,可修改流程为:

# 标准化数据
scaler = StandardScaler()
scaled_data = scaler.fit_transform(scores_data)

# 先PCA降维
pca = PCA(n_components=2)
pca_data = pca.fit_transform(scaled_data)

# 在降维后的数据上执行K-means
kmeans = KMeans(n_clusters=2, random_state=0).fit(pca_data)
metadata['cluster'] = kmeans.labels_

# 直接使用二维聚类中心可视化
plt.scatter(pca_data[:, 0], pca_data[:, 1], c=metadata['cluster'], s=50)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], c='red', marker='o')

# 标注代码同上
plt.show()

4. 验证k值的有效性

标准化后可通过肘部法则或轮廓系数选择合适的k值:

from sklearn.metrics import silhouette_score

# 肘部法则
inertias = []
for k in range(1, 10):
    kmeans = KMeans(n_clusters=k, random_state=0).fit(scaled_data)
    inertias.append(kmeans.inertia_)

plt.plot(range(1,10), inertias)
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Elbow Method')
plt.show()

# 轮廓系数
sil_scores = []
for k in range(2, 10):
    kmeans = KMeans(n_clusters=k, random_state=0).fit(scaled_data)
    sil_scores.append(silhouette_score(scaled_data, kmeans.labels_))

plt.plot(range(2,10), sil_scores)
plt.xlabel('k')
plt.ylabel('Silhouette Score')
plt.title('Silhouette Score Method')
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:10:56