【机器学习】【KMeans聚类分析实战】用户分群聚类详解——SSE、CH 指数、SC全解析,实战电信客户分群案例
1.引言
在实际数据分析中,聚类算法常用于客户分群、图像分割等场景。如何确定聚类数 k 是聚类分析中的关键问题之一。本文将以“用户分群”为例,展示如何通过 KMeans 聚类,利用 SSE(误差平方和,也称 Inertia)、Calinski-Harabasz 指数(CH Score)和 Silhouette Score(轮廓系数)来判断最佳的聚类数。你将看到三幅图表,每个图表都揭示了不同的聚类评价指标,帮助你综合判断哪一个 k 值最合理。
2. 聚类概念
3. 聚类指标介绍
• SSE (Inertia):反映了所有样本与其所属簇中心距离平方和。随着聚类数 k 增加,SSE 会下降;但在某个 k 值之后,SSE 的下降速度会明显减缓,这就是所谓的“肘部”,通常这个拐点附近的 k 值较为合理。
• Calinski-Harabasz Score (CH Score):衡量类间离散度和类内紧凑度之比,数值越大表示聚类结果越好。通常在最佳 k 附近,CH Score 会达到峰值。
• Silhouette Score (轮廓系数):取值范围为 -1 到 1,值越高说明聚类结构越明显,即同一簇内部相似度高,而不同簇之间相似度低。最佳 k 往往对应于轮廓系数较高的值。
4. 代码详解
以下代码分为两个函数:
• dm01_聚类分析用户群:遍历 k=2~10,记录并绘制 SSE、CH Score 和 Silhouette Score 曲线。
• dm02_聚类分析用户群:固定 k=5 进行聚类,并将聚类结果可视化。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as snsfrom sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, calinski_harabasz_score
from sklearn.model_selection import train_test_splitdef dm01_聚类分析用户群():"""函数功能:1. 读取 data/customers.csv,取第 3 列和第 4 列作为特征 (Annual Income, Spending Score)。2. 通过循环 k in [2, 10]:- 训练 KMeans(k)- 记录 SSE (inertia_)- 记录 Silhouette Score- (可选) 记录 Calinski-Harabasz Score3. 绘制 SSE 曲线(肘部法)和 Silhouette Score 曲线,以辅助确定最优聚类数。"""# 1. 读取数据dataset = pd.read_csv('data/Clustering_Methods/customers.csv')dataset.info() # 查看数据的列、类型、缺失值等print('【前 5 行数据】:\n', dataset.head(5))# 2. 取特征列:假设第 3, 4 列分别为 Annual Income, Spending ScoreX = dataset.iloc[:, [3, 4]]print('【X 特征前 5 行】:\n', X.head(5))# 3. 通过循环不同的聚类数 k,记录 SSE 和 Silhouette Score (可选 CH)sse_list = [] # 存储 SSEsil_list = [] # 存储 Silhouette Scorech_list = [] # (可选)存储 Calinski-Harabasz Scorek_values = range(2, 11) # k 从 2 到 10for k in k_values:# 实例化 KMeansmy_kmeans = KMeans(n_clusters=k, max_iter=300, random_state=0)my_kmeans.fit(X) # 训练# SSE (Inertia) - 簇内误差平方和sse_list.append(my_kmeans.inertia_)# 预测标签labels = my_kmeans.predict(X)# Silhouette Score (轮廓系数)sil_value = silhouette_score(X, labels)sil_list.append(sil_value)# (可选) Calinski-Harabasz 指数ch_value = calinski_harabasz_score(X, labels)ch_list.append(ch_value)# 4. 绘制 SSE 曲线(肘部法)plt.figure(figsize=(15, 4))plt.subplot(1, 3, 1)plt.plot(k_values, sse_list, marker='o', color='red')plt.title('Elbow Method (SSE vs k)')plt.xlabel('Number of Clusters (k)')plt.ylabel('SSE (Inertia)')plt.grid(True)# 5. 绘制 Silhouette Score 曲线plt.subplot(1, 3, 2)plt.plot(k_values, sil_list, marker='o', color='blue')plt.title('Silhouette Score vs k')plt.xlabel('Number of Clusters (k)')plt.ylabel('Silhouette Score')plt.grid(True)# (可选) 绘制 Calinski-Harabasz Score 曲线plt.subplot(1, 3, 3)plt.plot(k_values, ch_list, marker='o', color='green')plt.title('Calinski-Harabasz Score vs k')plt.xlabel('Number of Clusters (k)')plt.ylabel('CH Score')plt.grid(True)plt.tight_layout()plt.show()print("\n【提示】可综合观察 SSE 肘部位置、Silhouette Score 高点以及 CH Score 峰值,来判断最优 k。")def dm02_聚类分析用户群():"""函数功能:1. 读取 data/customers.csv,取第 3 列和第 4 列作为特征 (Annual Income, Spending Score)。2. 使用 KMeans(k=5) 进行聚类 (可根据 dm01_函数观察后选择最优 k)。3. 可视化聚类结果,每个簇用不同颜色散点表示,并标注聚类中心。"""# 1. 读取数据dataset = pd.read_csv('data/Clustering_Methods/customers.csv')# 假设第 3, 4 列分别为 Annual Income, Spending ScoreX = dataset.iloc[:, [3, 4]]# 2. 实例化 KMeans,指定 n_clusters=5kmeans = KMeans(n_clusters=5, max_iter=300, random_state=0)kmeans.fit(X)# 3. 预测标签y_kmeans = kmeans.predict(X)# 4. 可视化# 每个簇用不同颜色散点plt.figure(figsize=(8, 5))plt.scatter(X.values[y_kmeans == 0, 0], X.values[y_kmeans == 0, 1],s=100, c='red', label='Cluster 0')plt.scatter(X.values[y_kmeans == 1, 0], X.values[y_kmeans == 1, 1],s=100, c='blue', label='Cluster 1')plt.scatter(X.values[y_kmeans == 2, 0], X.values[y_kmeans == 2, 1],s=100, c='green', label='Cluster 2')plt.scatter(X.values[y_kmeans == 3, 0], X.values[y_kmeans == 3, 1],s=100, c='cyan', label='Cluster 3')plt.scatter(X.values[y_kmeans == 4, 0], X.values[y_kmeans == 4, 1],s=100, c='magenta', label='Cluster 4')# 画出聚类中心(黑色大点)plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],s=300, c='black', marker='X', label='Centroids')plt.title('Customer Clusters')plt.xlabel('Annual Income (k$)')plt.ylabel('Spending Score (1-100)')plt.legend()plt.show()# 可选:查看聚类后的指标,如 SSE, Silhouette 等sse = kmeans.inertia_labels = kmeans.labels_sil_value = silhouette_score(X, labels)print(f"SSE: {sse:.2f}")print(f"Silhouette Score: {sil_value:.2f}")if __name__ == "__main__":print("=== 第一步: 评估不同 k 的聚类效果 ===")dm01_聚类分析用户群()print("\n=== 第二步: 以 k=5 聚类并可视化 ===")dm02_聚类分析用户群()
代码输出:
代码解释
1. dm01_聚类分析用户群 函数
• 数据读取与预览
读取 data/Clustering_Methods/customers.csv 文件,并用 info() 和 head() 查看数据基本情况。
• 特征选择
假设第 3 列和第 4 列分别为“年收入”和“消费得分”,并打印前5行数据。
• 遍历不同聚类数 k
在 k 从 2 到 10 的范围内,依次训练 KMeans 模型,并记录 SSE(inertia_)、Silhouette Score 和 Calinski-Harabasz 指数。
• 绘制图表
使用 3 个子图分别展示 SSE 曲线、轮廓系数曲线、CH 指数曲线,帮助你直观观察:
• SSE 曲线:观察“肘部”位置,即 SSE 降低变缓的 k 值;
• 轮廓系数曲线:观察 k 值下哪个聚类结果的轮廓系数最高;
• CH 指数曲线:查看哪个 k 值下类间分离度最佳。
综合这三个指标,你可以判断哪个 k 值可能是最优的。如果三个指标都在某个 k 值附近表现较好,则该 k 值值得选择。
2. dm02_聚类分析用户群 函数
• 使用 k=5 进行聚类
假设根据前一步的指标,k=5 是较优选择,直接训练 KMeans 模型。
• 结果可视化
对不同簇(Cluster 0 到 Cluster 4)用不同颜色绘制散点图,并用黑色大“X”标注聚类中心。图表标题、坐标轴均使用中文,便于理解。
• 输出指标
打印 SSE 和 Silhouette Score,帮助你验证模型效果。
结论
通过以上两个步骤,你可以:
• 先评估:利用多个聚类指标确定最佳聚类数 k(通过肘部法和峰值对比);
• 后可视化:固定 k 值进行聚类,并直观展示聚类结果及聚类中心。
如果你对聚类结果满意,模型就可以应用到后续的用户分群、个性化营销或其他业务场景中。
5.总结:
本文通过一个用户分群的案例详细介绍了如何使用 KMeans 聚类算法确定最佳聚类数 k,并结合 SSE、Silhouette Score 和 Calinski-Harabasz 指数辅助决策。希望这篇文章能帮助你理解聚类算法的关键指标以及如何通过图形直观地选择最佳 k 值。如果你觉得文章对你有帮助,请点赞、收藏、转发,并关注我的博客,分享更多数据科学的精彩内容!
参考文献:
1. Jain, A. K. (2010). Data clustering: 50 years beyond K-means. Pattern Recognition Letters, 31(8), 651-666.
2. Kaufman, L., & Rousseeuw, P. J. (2009). Finding Groups in Data: An Introduction to Cluster Analysis. Wiley-Interscience.
3. scikit-learn 官方文档 – Clustering: https://scikit-learn.org/stable/modules/clustering.html
这篇文章通过代码示例和详细注释,帮助读者学会如何利用多种聚类评价指标判断最佳聚类数,并进行结果可视化。希望你喜欢这篇文章,欢迎大佬们点赞,关注,收藏,转发,也欢迎各位读者在评论区讨论和交流!
相关文章:

【机器学习】【KMeans聚类分析实战】用户分群聚类详解——SSE、CH 指数、SC全解析,实战电信客户分群案例
1.引言 在实际数据分析中,聚类算法常用于客户分群、图像分割等场景。如何确定聚类数 k 是聚类分析中的关键问题之一。本文将以“用户分群”为例,展示如何通过 KMeans 聚类,利用 SSE(误差平方和,也称 Inertiaÿ…...
【C++】 时间库chrono计算程序运行时间
C 时间库chrono计算程序运行时间 本文总结了chrono库的引入方法以及计算程序片段运行时间的方法 一、chrono库的引入方法(注意事项) 首先chrono是属于std命名空间的。 所以在程序中应该这样包含头文件: #include <chrono> using n…...
PCL 边界体积层次结构(Boundary Volume Hierarchy, BVH)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 边界体积层次结构(Boundary Volume Hierarchy, BVH) 是一种高效的空间数据结构,广泛应用于计算机图形学、计算机视觉、机器人学、物理仿真等领域。它的核心思想是通过将空间递归地划分为层次化的包围体(通常是轴…...
算法随笔_58: 队列中可以看到的人数
上一篇:算法随笔_57 : 游戏中弱角色的数量-CSDN博客 题目描述如下: 有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同,heights[i] 表示第 i 个人的高度。 一个人能 看到 他右边另一个人…...

创建React项目的三个方式
创建React项目 创建一个React项目非常简单,通常有几种方法可以进行,下面是最常见的几种方法: 1. 使用 create-react-app (已经不被推荐了) create-react-app 是一个官方的脚手架工具,用于快速创建 React 项目。它会为你配置好很…...
QT闲记-工具栏
工具栏通常用来放置常用的操作按钮,如QPushButton,QAction等。可以放置在顶部,底部,左侧,右侧,并且支持拖曳,浮动。 1、创建工具栏 通常通过QMainWindow 提供的addToolBar()来创建,它跟菜单栏一样,如果需要工具栏,一般情况下,我们设置这个类的基类为QMainWindow。 …...

为什么继电器要加一个反向并联一个二极管
1 动感就是电流不突变 2 为什么有的继电器上面要反向并联一个二极管和电阻 1 并联二极管是为消除掉动感产生的高压 2 加上二极管是为了让继电器更快的断开(二极管选型的工作电流要大于动感电流,开关要够快) 3 公式:二极管压降0…...
【Leetcode 每日一题 - 扩展】1512. 好数对的数目
问题背景 给你一个整数数组 n u m s nums nums。 如果一组数字 ( i , j ) (i,j) (i,j) 满足 n u m s [ i ] n u m s [ j ] nums[i] nums[j] nums[i]nums[j] 且 i < j i < j i<j,就可以认为这是一组 好数对 。 返回好数对的数目。 数据约束 1 ≤ n …...
vue3 采用xlsx库实现本地上传excel文件,前端解析为Json数据
需求:本地上传excel 文件,但需要对excel 文件的内容进行解析,然后展示出来 1. 安装依赖 首先,确保安装了 xlsx 库: bash复制 npm install xlsx 2. 创建 Vue 组件 创建一个 Vue 组件(如 ExcelUpload.v…...

计算机视觉:经典数据格式(VOC、YOLO、COCO)解析与转换(附代码)
第一章:计算机视觉中图像的基础认知 第二章:计算机视觉:卷积神经网络(CNN)基本概念(一) 第三章:计算机视觉:卷积神经网络(CNN)基本概念(二) 第四章:搭建一个经典的LeNet5神经网络(附代码) 第五章࿱…...

FPGA DSP:Vivado 中带有 DDS 的 FIR 滤波器
本文使用 DDS 生成三个信号,并在 Vivado 中实现低通滤波器。低通滤波器将滤除相关信号。 介绍 用DDS生成三个信号,并在Vivado中实现低通滤波器。低通滤波器将滤除较快的信号。 本文分为几个主要部分: 信号生成:展示如何使用DDS&am…...

记录此刻:历时两月,初步实现基于FPGA的NVMe SSD固态硬盘存储控制器设计!
背景 为满足实验室横向项目需求,在2024年12月中下旬导师提出基于FPGA的NVMe SSD控制器研发项目。项目核心目标为:通过PCIe 3.0 x4接口实现单盘3000MB/s的持续读取速率。 实现过程 调研 花了半个月的时间查阅了一些使用FPGA实现NVME SSD控制器的论文、…...
【计算机网络】OSI模型、TCP/IP模型、路由器、集线器、交换机
一、计算机网络分层结构 计算机网络分层结构 指将计算机网络的功能划分为多个层次,每个层次都有其特定的功能和协议,并且层次之间通过接口进行通信。 分层设计的优势: 模块化:各层独立发展(如IPv4→IPv6,…...

正点原子[第三期]Arm(iMX6U)Linux系统移植和根文件系统构建-5.3 xxx_defconfig过程
前言: 本文是根据哔哩哔哩网站上“arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用: …...

250223-Linux/MacOS如何跳过Miniconda的条款阅读,直接安装Miniconda
你可以通过将 -b 参数传递给 Miniconda 的安装脚本,来跳过条款阅读并自动同意许可条款。这样安装会自动进行到下一步的选择项。下面是具体的安装命令: bash Miniconda3-latest-Linux-x86_64.sh -b这里的 -b 代表“批量模式”(batch mode&…...

点云的几何特征
点云的几何特征是基于一个点周围的邻域对该点周围几何形状的描述。例如,位于墙面上的一个点将具有较高的平面度planarity。 基于局部点云的特征值 λ1、λ2 和 λ3 以及特征向量 e1、e2 和e3计算得到的一系列几何特征,这些特征用于描述点云中点的局部几…...

月之暗面新发布: MUON 在 LLM 训练中的可扩展性
MUON 在 LLM 训练中的可扩展性 摘要 最近,基于矩阵正交化的 Muon 优化器(K. Jordan 等人,2024 年)在训练小型语言模型方面表现出色,但其在更大规模模型上的可扩展性尚未得到验证。我们确定了 Muon 放大的两个关键技术…...
10.Docker 仓库管理
Docker 仓库管理 Docker 仓库管理 Docker 仓库管理 Docker 仓库,类似于 yum 仓库,是用来保存镜像的仓库。为了方便的管理和使用 docker 镜像,可以将镜像集中保存至 Docker 仓库中,将制作好的镜像 push 到仓库集中保存,在需要镜像…...

Deepseek存算分离安全部署手册
Deepseek大火后,很多文章教大家部署Dfiy和ollamadeepseek,但是大部分都忽略了数据安全问题,本文重点介绍Deepseek存算分裂安全架设,GPU云主机只负责计算、CPU本地主机负责数据存储,确保数据不上云,保证私有…...

【Redis原理】底层数据结构 五种数据类型
文章目录 动态字符串SDS(simple dynamic string )SDS结构定义SDS动态扩容 IntSetIntSet 结构定义IntSet的升级 DictDict结构定义Dict的扩容Dict的收缩Dict 的rehash ZipListZipListEntryencoding 编码字符串整数 ZipList的连锁更新问题 QuickListQuickList源码 SkipListRedisOb…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...

RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...

使用ch340继电器完成随机断电测试
前言 如图所示是市面上常见的OTA压测继电器,通过ch340串口模块完成对继电器的分路控制,这里我编写了一个脚本方便对4路继电器的控制,可以设置开启时间,关闭时间,复位等功能 软件界面 在设备管理器查看串口号后&…...

HTML版英语学习系统
HTML版英语学习系统 这是一个完全免费、无需安装、功能完整的英语学习工具,使用HTML CSS JavaScript实现。 功能 文本朗读练习 - 输入英文文章,系统朗读帮助练习听力和发音,适合跟读练习,模仿学习;实时词典查询 - 双…...