使用Sklearn的Kmeans聚类无法实现两组良好分离求排查
可能的问题及解决步骤
1. 初始化随机性影响聚类结果
KMeans的聚类效果受初始质心位置影响,即便默认的k-means++能优化初始化,仍可能因单次随机取值导致结果不佳。你代码中注释了random_state和init参数,建议:
- 固定
random_state(如random_state=42),确保结果可复现 - 增大
n_init参数(如n_init=10),让算法多次运行后选取最优结果 - 尝试切换
init方式(对比k-means++和random)
修改后代码示例:
scaled = MinMaxScaler().fit_transform(points) kmeans = KMeans(n_clusters=nb_clusters, random_state=42, n_init=10) kmeans.fit(scaled) labels = kmeans.labels_ centroids = kmeans.cluster_centers_
2. 数据缩放方式不匹配
MinMaxScaler将特征缩放到[0,1],但如果数据存在异常值、长尾分布,这种缩放会压缩有效特征差异,干扰KMeans的距离计算逻辑。可以尝试改用StandardScaler(标准化为均值0、方差1):
from sklearn.preprocessing import StandardScaler scaled = StandardScaler().fit_transform(points) # 后续KMeans代码不变
3. 确认簇数设置正确
确保nb_clusters的值与你期望的分组数一致(比如要分2组就设为2)。若不确定最优簇数,可通过以下方法验证:
- 肘部法则:绘制不同簇数下的惯性值(
inertia_)曲线,选取曲线拐点对应的簇数 - 轮廓系数:计算
sklearn.metrics.silhouette_score,取值越接近1说明聚类效果越好
肘部法则示例代码:
import matplotlib.pyplot as plt inertias = [] for k in range(1, 6): kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) kmeans.fit(scaled) inertias.append(kmeans.inertia_) plt.plot(range(1,6), inertias, 'bo-') plt.xlabel('簇数') plt.ylabel('惯性值') plt.show()
4. 特征不足或数据无聚类结构
若上述调整后效果仍差,可能是当前特征无法区分两组数据:
- 检查现有特征的有效性,尝试补充更多相关特征
- 换用更适配的聚类算法:比如数据密度不均时用DBSCAN,层次聚类适合有层级结构的数据
内容的提问来源于stack exchange,提问作者Vénon
相关产品推荐
相关产品推荐

