机器学习——KMeans聚类实战案例解析

发布于:2025-08-12 ⋅ 阅读:(12) ⋅ 点赞:(0)

机器学习——KMeans聚类算法(算法原理+超参数详解+实战案例)-CSDN博客https://blog.csdn.net/2302_78022640/article/details/150075553?spm=1001.2014.3001.5502

KMeans聚类实战案例解析

KMeans 是一种经典的无监督学习聚类算法,能够将数据自动划分为若干个簇,使得同一簇内的数据点尽可能相似,不同簇的数据点尽可能不同。本文以啤酒属性数据为例,详细讲解如何使用 KMeans 聚类,并通过轮廓系数(Silhouette Score)来选取最佳簇数。


K-Means 的核心思想是:

  1. 随机选择 K 个点作为初始聚类中心(质心,Centroid)

  2. 计算每个样本到各质心的距离,将样本分配到最近的质心所在的簇。

  3. 重新计算每个簇的质心(即簇内所有点的均值)。

  4. 重复步骤 2 和 3,直到簇不再变化或达到最大迭代次数。

其优化目标是最小化簇内的平方误差和(Sum of Squared Errors, SSE):

其中:

  • Ck :第 k 个簇

  • μk :第 k 个簇的质心


1. 数据准备

创建一个.txt文件

name calories sodium alcohol cost
Budweiser 144 15 4.7 0.43
Schlitz 151 19 4.9 0.43
Lowenbrau 157 15 0.9 0.48
Kronenbourg 170 7 5.2 0.73
Heineken 152 11 5.0 0.77
Old_Milwaukee 145 23 4.6 0.28
Augsberger 175 24 5.5 0.40
Srohs_Bohemian_Style 149 27 4.7 0.42
Miller_Lite 99 10 4.3 0.43
Budweiser_Light 113 8 3.7 0.40
Coors 140 18 4.6 0.44
Coors_Light 102 15 4.1 0.46
Michelob_Light 135 11 4.2 0.50
Becks 150 19 4.7 0.76
Kirin 149 6 5.0 0.79
Pabst_Extra_Light 68 15 2.3 0.38
Hamms 139 19 4.4 0.43
Heilemans_Old_Style 144 24 4.9 0.43
Olympia_Goled_Light 72 6 2.9 0.46
Schlitz_Light 97 7 4.2 0.47

首先,我们导入需要的库并读取数据。

数据存储在 data.txt 文件中

字段包含啤酒的卡路里(calories)、钠含量(sodium)、酒精度数(alcohol)和价格(cost)等指标。

import pandas as pd
from sklearn.cluster import KMeans
from sklearn import metrics

# 读取数据,使用空格作为分隔符
beer = pd.read_table("data.txt", sep=' ', encoding='utf8', engine='python')

# 选取用于聚类的特征列
x = beer[["calories","sodium","alcohol","cost"]]

2. 选择合适的聚类簇数 K

KMeans 需要预先设定簇的数量 K,但是选择合适的 K 往往需要一定的探索。本文使用轮廓系数(Silhouette Score)来评估不同 K 值对应的聚类质量。

  • 轮廓系数取值范围为 -1 到 1。

  • 越接近 1 表示聚类效果越好,簇内紧密且簇间分离明显。

  • 约为 0 表示样本可能处于两个簇的边界,聚类不明确。

  • 趋近于 -1 表示聚类效果很差,可能样本被错误分配。

代码如下:

scores = []
for k in range(2, 10):
    labels = KMeans(n_clusters=k).fit(x).labels_  # 训练模型并获取每个样本的簇标签
    score = metrics.silhouette_score(x, labels)  # 计算轮廓系数
    scores.append(score)

print(scores)

通过这段代码,我们可以得到不同簇数下的轮廓系数列表,方便选择得分最高的 K


3. 绘制轮廓系数趋势图

将不同簇数对应的轮廓系数可视化,便于直观判断:

import matplotlib.pyplot as plt

plt.plot(list(range(2,10)), scores, marker='o')
plt.xlabel("Number of Clusters (K)")
plt.ylabel("Silhouette Score")
plt.title("KMeans 聚类簇数选择 - 轮廓系数曲线")
plt.show()

通过曲线图,可以看到某个 K 值对应的轮廓系数达到峰值,即为较优的聚类簇数。

可以看到 k = 2 时,轮廓系数达到峰值,即为较优的聚类簇数。


4. 以最佳 K 值进行聚类

假设轮廓系数最高时 K=2,我们使用 K=2 对数据进行聚类,并将结果写回数据集:

km = KMeans(n_clusters=2).fit(x)
beer['cluster'] = km.labels_  # 保存每个样本的簇标签

5. 聚类结果评估

再次计算聚类结果的轮廓系数,评估最终聚类的效果:

score = metrics.silhouette_score(x, beer['cluster'])
print(f"最终聚类的轮廓系数为: {score}")

轮廓系数越接近 1 表明聚类越合理。


6. 总结与扩展

  • 通过轮廓系数指标,自动寻找合适的聚类簇数,有效避免了盲目设定 K

  • KMeans 对数值型特征表现良好,适合对啤酒数据这类属性进行划分。

  • 若数据量较大或者维度较高,可以先做标准化或降维处理。

  • 聚类结果可以用来发现不同类别的啤酒特征差异,辅助市场分析和产品定位。

以下是提升 K-means 算法轮廓系数的优化方法:

优化方向 具体措施 作用原理
数据预处理优化 1. 标准化 / 归一化特征(Z-score/Min-Max)
2. 去除噪声和异常值(Z-score/IQR/ 孤立森林)
3. 特征选择与降维(PCA / 方差选择法)
消除特征尺度差异,减少异常值干扰,缓解维度灾难,使距离度量更合理
k 值选择优化 1. 计算不同 k 值的轮廓系数,选择最大值对应的 k
2. 结合业务场景约束确定 k
避免 k 过小(簇内松散)或 k 过大(簇间重叠),找到最优簇数量
初始质心优化 采用 K-means++ 初始化:
1. 随机选第一个质心
2. 按距离概率选择后续质心(距离越远概率越高)
使初始质心更分散,减少局部最优陷阱,提升簇间分离度
距离度量优化 1. 连续型数据:欧氏距离(球形分布)、马氏距离(消除相关性)
2. 高维稀疏数据:余弦相似度
3. 离散型数据:汉明距离 / Jaccard 系数
选择适配数据类型的距离度量,避免相似度计算失真
迭代策略优化 1. 增加最大迭代次数(如从 100 增至 500)
2. 收紧收敛阈值(如从 1e-4 降至 1e-6)
确保算法充分收敛,提升簇内紧凑性
抗噪声算法变种 1. K-medians(用中位数代替均值)
2. 加权 K-means(降低噪声样本权重)
减少异常值对质心的影响,提升聚类稳定性
聚类后处理优化 1. 合并距离过近的簇(基于簇中心距离)
2. 拆分 SSE 过大的松散簇
3. 手动调整低轮廓系数样本的归属
优化簇结构,修正错误分配,进一步提升簇内紧凑性和簇间分离度