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

使用Scikit-learn进行K-means聚类时出现请求簇数缺失的问题求助

关于Scikit-learn KMeans出现空簇的问题解答

嘿,我之前在项目里也碰到过一模一样的情况!来跟你拆解下这个问题:

为什么会出现指定4个簇却只得到3个非空簇?

这大概率是初始簇中心的选择导致的:

  • 默认的k-means++初始化虽然比随机初始化更优,但偶尔还是会选到一个离所有样本都非常远的初始点,在迭代过程中没有任何样本被分配到这个簇,最终就变成了空簇。
  • 另外也有可能你的数据集本身的分布特性更适合3个簇,强行指定4个簇时,算法找不到足够的样本支撑第4个簇的存在。

为什么Scikit-learn的KMeans不会自动处理空簇?

标准的KMeans算法流程里并没有“检测空簇并重新初始化中心”的步骤,Scikit-learn的实现严格遵循了这一标准流程,所以不会自动为空簇重新选择新的样本作为中心。不同的KMeans实现(比如一些统计软件)可能会有额外的处理逻辑,但sklearn默认没有这个功能。

解决办法

给你几个实用的方案:

1. 增加初始化次数

通过设置n_init参数让算法多跑几次不同的初始中心,降低碰到空簇的概率。新版本的sklearn默认n_init='auto',你可以手动设置一个更大的值,比如20:

from sklearn.cluster import KMeans
import pandas as pd

# 增加初始化次数,同时设置random_state保证可复现
kmeans = KMeans(n_clusters=4, n_init=20, random_state=42)
kmeans.fit(your_dataset)

# 查看每个簇的样本数量,确认是否还有空簇
label_counts = pd.Series(kmeans.labels_).value_counts()
print(label_counts)

2. 先评估最优簇数

如果不是必须要4个簇,建议先通过肘部法则或轮廓系数评估数据集的最优簇数,说不定3个簇才是最适合的:

from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# 肘部法则
inertias = []
range_n_clusters = range(2, 6)
for n in range_n_clusters:
    kmeans = KMeans(n_clusters=n, n_init=20, random_state=42)
    kmeans.fit(your_dataset)
    inertias.append(kmeans.inertia_)

plt.plot(range_n_clusters, inertias, 'bo-')
plt.xlabel('Number of clusters')
plt.ylabel('Inertia')
plt.title('Elbow Method')
plt.show()

# 轮廓系数
for n in range_n_clusters:
    kmeans = KMeans(n_clusters=n, n_init=20, random_state=42)
    labels = kmeans.fit_predict(your_dataset)
    score = silhouette_score(your_dataset, labels)
    print(f"n_clusters={n}, Silhouette Score={score:.2f}")

3. 手动处理空簇(如果必须要4个簇)

如果业务上一定需要4个簇,可以自己写代码检测空簇,然后选取离现有中心最远的样本作为新中心重新迭代。举个简单的示例逻辑:

import numpy as np
from sklearn.cluster import KMeans
import pandas as pd

def kmeans_with_empty_cluster_fix(X, n_clusters):
    kmeans = KMeans(n_clusters=n_clusters, n_init=1, random_state=42)
    kmeans.fit(X)
    
    # 检查是否有空簇
    unique_labels = np.unique(kmeans.labels_)
    while len(unique_labels) < n_clusters:
        # 找到离所有中心最远的样本
        distances = kmeans.transform(X)
        min_distances = np.min(distances, axis=1)
        farthest_idx = np.argmax(min_distances)
        
        # 替换空簇的中心
        empty_cluster_idx = set(range(n_clusters)) - set(unique_labels)
        kmeans.cluster_centers_[list(empty_cluster_idx)[0]] = X[farthest_idx]
        
        # 重新拟合
        kmeans.fit(X)
        unique_labels = np.unique(kmeans.labels_)
    
    return kmeans

# 使用这个函数
fixed_kmeans = kmeans_with_empty_cluster_fix(your_dataset, 4)
print(pd.Series(fixed_kmeans.labels_).value_counts())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:42:36