【机器学习】【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…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
