本次实战以啤酒的理化与价格数据为基础,使用 Python 的 sklearn 库实现 KMeans 聚类,核心目标是通过轮廓系数选择最优聚类数 K,完成啤酒的无监督分类,全程贴合实际数据分析的流程,从数据读取到模型评估一步到位。

一、实战背景与数据说明

1. 分析背景

无监督聚类是机器学习中经典的无标签学习方法,KMeans 是最常用的聚类算法之一,但 KMeans 需要预先指定聚类数 K,轮廓系数是评估聚类效果的重要指标,可帮助我们客观选择最优 K 值,而非主观判断。

2. 数据介绍

本次使用data.txt啤酒数据集,共 20 条样本,包含1 个名称列 + 4 个特征列,特征均为数值型,适合直接用于 KMeans 聚类:

表格

列名 含义 数据类型
name 啤酒名称 字符串
calories 卡路里 数值
sodium 钠含量 数值
alcohol 酒精含量 数值
cost 价格 数值

二、实战环境与库依赖

本次实战基于 Python 环境,需安装以下核心库(pip 安装命令):

pip install pandas scikit-learn matplotlib

各库的作用:

  • pandas:数据读取与数据结构处理;
  • sklearn.cluster.KMeans:实现 KMeans 聚类算法;
  • sklearn.metrics:计算轮廓系数,评估聚类效果;
  • matplotlib:绘制轮廓系数随 K 值变化的趋势图,可视化选择最优 K。

三、实战步骤逐行讲解

整体流程:数据读取 → 特征选择 → 遍历 K 值 + 计算轮廓系数 → 可视化评估 → 选择最优 K,对应kmeans.py代码逐行解析。

步骤 1:导入所需库

import pandas as pd
from sklearn.cluster import KMeans
from sklearn import metrics
import matplotlib.pyplot as plt
  • 导入 pandas 用于数据处理,KMeans 为聚类核心模型;
  • sklearn.metrics中包含silhouette_score(轮廓系数) 评估函数;
  • matplotlib 用于绘制结果可视化图表。

步骤 2:读取数据集

beer = pd.read_table("data.txt", sep=" ", encoding='utf8', engine='python')
  • 使用pd.read_table读取文本文件,适配data.txt空格分隔格式(sep=" ");
  • 编码指定为 utf8,engine='python'解决空格分隔可能的解析问题;
  • 读取后赋值给beer,为 pandas 的 DataFrame 格式,可通过beer.head()查看前 5 行数据,beer.info()检查数据完整性(本次数据无缺失,可直接使用)。

步骤 3:选择聚类特征

X = beer[["calories", "sodium", "alcohol", "cost"]]
  • KMeans 仅支持数值型特征,因此排除字符串类型的name列,选择 4 个数值特征作为聚类输入;
  • 变量X为聚类的特征矩阵,形状为(20,4)(20 条样本,4 个特征)。

步骤 4:遍历 K 值并计算轮廓系数

scores = []
for k in range(2, 10):  # 寻找合适的K值
    labels = KMeans(n_clusters=k).fit(X).labels_
    score = metrics.silhouette_score(X, labels)  # 轮廓系数
    scores.append(score)
print(scores)

这是本次实战的核心步骤,目的是通过轮廓系数评估不同 K 值的聚类效果:

  1. 初始化空列表scores,用于存储不同 K 值对应的轮廓系数;
  2. 遍历 K 值:范围为 2~9(range(2,10)),聚类数 K 一般不小于 2,也不宜过大(本次仅 20 条样本,K 最大设为 9 足够);
  3. 训练 KMeans 模型:KMeans(n_clusters=k).fit(X)为指定 K 值训练模型,.labels_获取每个样本的聚类标签(即样本被分到哪个簇,标签为 0,1,2...k-1);
  4. 计算轮廓系数:metrics.silhouette_score(X, labels)传入特征矩阵和聚类标签,计算当前 K 值的轮廓系数;
  5. 存储结果:将每个 K 的轮廓系数添加到scores,最后打印查看数值。
轮廓系数核心解读
  • 取值范围:[-1,1],越接近 1 表示聚类效果越好,样本在簇内的相似度高,与其他簇的相似度低;
  • 接近 0:表示簇与簇之间有重叠,聚类边界不清晰;
  • 为负:表示样本被分到了错误的簇,聚类效果极差。

步骤 5:可视化轮廓系数趋势

plt.plot(list(range(2, 10)), scores)
plt.xlabel("Number of Clusters Initialized")
plt.ylabel("Silhouette Score")
plt.show()
  • plt.plot(x轴, y轴):x 轴为 K 值(2~9),y 轴为对应轮廓系数,绘制折线图;
  • 添加 x、y 轴标签,让图表更易读;
  • plt.show()显示图表,通过折线的峰值找到轮廓系数最大的 K 值,即为最优聚类数

四、实战结果分析与后续操作

1. 预期结果

运行代码后,首先会打印出 8 个数值(对应 K=2 到 K=9 的轮廓系数),例如典型结果(因 KMeans 初始质心随机,数值略有浮动):

[0.45, 0.52, 0.48, 0.40, 0.35, 0.30, 0.25, 0.20]

绘制的折线图中,K=3时轮廓系数达到峰值,说明将 20 种啤酒分为 3 类时,聚类效果最优。

2. 核心结论

轮廓系数的峰值对应的 K 值,是当前数据下 KMeans 的最优聚类数,本次实战中啤酒数据按 4 个特征分为 3 类时,簇内相似度最高、簇间差异最明显。

3. 后续拓展操作

实战并非到选完 K 值结束,还可基于最优 K 值做进一步分析,这也是实际工作中的必要步骤:

(1)训练最优 K 值的 KMeans 模型,获取最终聚类结果
# 假设最优K=3
k_opt = 3
kmeans = KMeans(n_clusters=k_opt).fit(X)
# 为原数据添加聚类标签列
beer['cluster_label'] = kmeans.labels_
# 查看每个簇的啤酒样本
for i in range(k_opt):
    print(f"第{i+1}簇的啤酒:")
    print(beer[beer['cluster_label']==i]['name'].tolist())
(2)分析每个簇的特征均值,总结簇的特点
# 按聚类标签分组,计算各特征的均值
cluster_analysis = beer.groupby('cluster_label')[["calories", "sodium", "alcohol", "cost"]].mean()
print(cluster_analysis)

例如可得到:簇 0 为 “高卡路里、高酒精、高价格” 的高端啤酒,簇 1 为 “低卡路里、低酒精” 的轻啤,簇 2 为 “中等特征、低价格” 的平民啤酒,完成对啤酒的特征化分类。

(3)解决 KMeans 初始质心随机的问题

KMeans 默认随机选择初始质心,可能导致每次运行结果略有浮动,可设置n_init='auto'(sklearn 默认),让模型多次运行选择最优质心,提升结果稳定性:

KMeans(n_clusters=k_opt, n_init='auto', random_state=42).fit(X)

设置random_state=42可让结果完全可复现。

五、实战注意事项与坑点

  1. 数据格式pd.read_table的分隔符需与数据匹配,data.txt是空格分隔,不可用逗号(sep=","),否则会解析失败;
  2. 特征类型:KMeans 不支持字符串特征,必须排除非数值列,否则会报类型错误;
  3. K 值范围:K 值不宜过大,当 K 值等于样本数时,轮廓系数为 1,但此时每个样本为一个簇,无实际聚类意义;
  4. 数据标准化:本次实战未做标准化,因 4 个特征的量纲差异不大(如 calories 是几十到一百多,cost 是 0.2~0.8),若特征量纲差异大(如一个特征是 1~10,另一个是 1~1000),需先做标准化 / 归一化(如sklearn.preprocessing.StandardScaler),否则量纲大的特征会主导聚类结果;
  5. 轮廓系数的局限性:轮廓系数适合评估球形簇的聚类效果,若数据的簇形状非球形(如月牙形),KMeans 本身效果差,轮廓系数也会偏低,此时可选择 DBSCAN 等聚类算法。

六、实战总结

本次 KMeans 实战是无监督聚类的经典落地流程,核心要点:

  1. 明确 KMeans 的痛点:需要手动指定 K 值,因此需通过轮廓系数等评估指标客观选择;
  2. 掌握完整流程:数据读取→特征选择→K 值遍历→模型评估→可视化选 K→结果分析;
  3. 理解评估指标:轮廓系数的取值意义,以及如何通过峰值选择最优 K;
  4. 贴合实际应用:聚类后不仅要得到标签,还要对簇进行特征分析,让聚类结果产生业务价值。

本次实战以啤酒数据为例,该流程可直接迁移到其他场景(如客户分群、商品分类、用户行为聚类等),只需替换数据集和特征列即可。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐