数据挖掘实战:基于KMeans算法对超市客户进行聚类分群(文末送书)

news2024/12/26 9:19:27

 

🤵‍♂️ 个人主页:@艾派森的个人主页

✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+


目录

一、研究背景

二、算法原理

三、实验步骤

3.1加载数据集

3.2数据预处理

3.3确定聚类参数k

3.4 kmeans聚类

3.5聚类结果

 四、总结

完整代码

文末推荐

文末福利


一、研究背景

        超市作为零售业的主要形式之一,在现代都市生活中扮演着重要角色。随着社会经济的发展和消费者需求的变化,超市经营者越来越意识到了客户细分的重要性。不同的客户群体有着不同的购物习惯、消费行为和偏好,了解并满足不同客户群体的需求,可以帮助超市提供更加个性化的服务和商品推荐,从而提升客户的满意度和忠诚度,促进超市的经营发展。

        为了实现客户细分,研究者和业界常常采用聚类分析的方法。KMeans算法作为一种常见的聚类算法,具有计算效率高、易于理解和实现的优点,被广泛应用于客户细分领域。

        因此,本实验旨在使用KMeans算法对超市客户进行聚类分群,从而识别出不同的客户群体,并分析这些群体的特征和行为习惯。通过这种客户细分的方式,超市经营者可以更好地了解其客户群体,优化产品陈列和推广策略,提供更加个性化的购物体验,增加客户的购买频率和客单价,从而实现超市业务的增长和盈利能力的提升。

二、算法原理

        k-means算法是一种简单的迭代型聚类算法,采用距离作为相似性指标,从而发现给定数据集中的K个类,且每个类的中心是根据类中所有值的均值得到,每个类用聚类中心来描述。对于给定的一个包含n个d维数据点的数据集X以及要分得的类别K,选取欧式距离作为相似度指标,聚类目标是使得各类的聚类平方和最小,即最小化。

  结合最小二乘法和拉格朗日原理,聚类中心为对应类别中各数据点的平均值,同时为了使得算法收敛,在迭代过程中,应使最终的聚类中心尽可能的不变。

K-means是一个反复迭代的过程,算法分为四个步骤:

1)选取数据空间中的K个对象作为初始中心,每个对象代表一个聚类中心;

2)对于样本中的数据对象,根据它们与这些聚类中心的欧氏距离,按距离最近的准则将它们分到距离它们最近的聚类中心(最相似)所对应的类;

3)更新聚类中心:将每个类别中所有对象所对应的均值作为该类别的聚类中心,计算目标函数的值;

4)判断聚类中心和目标函数的值是否发生改变,若不变,则输出结果,若改变,则返回2)。

三、实验步骤

3.1加载数据集

首先导入本次实验用到的第三方库和数据集

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font='SimHei')
import warnings
warnings.filterwarnings('ignore')

# 读取数据
data = pd.read_csv('Mall_Customers.csv')
data.head()

使用shape属性查看数据大小

使用info函数查看数据基本信息

3.2数据预处理

这里我们需要将性别变量进行编码转化

3.3确定聚类参数k

方法1:肘部法则

        肘部法则(Elbow Method)是一种常用于确定KMeans聚类算法中参数K的方法。该方法通过绘制不同K值对应的聚类误差(通常是SSE,Sum of Squared Errors)的折线图,来寻找一个“肘点”,该点对应的K值即为较为合适的聚类数。

以下是使用肘部法则确定K的步骤:

  1. 选择一定范围的K值:首先,确定一个K值的范围,一般从较小的K开始,例如1到10或者更大的范围,具体根据问题的复杂程度而定。

  2. 计算聚类误差(SSE):对于每一个K值,使用KMeans算法进行聚类,并计算每个数据点到其所属簇中心的距离之和的平方,即SSE。SSE是衡量聚类效果的指标,表示样本点与其所属簇中心的紧密程度。

  3. 绘制肘部法则图:将不同K值对应的SSE绘制成折线图(K-SSE曲线图)。横坐标为K值,纵坐标为对应的SSE值。

  4. 寻找“肘点”:观察K-SSE曲线图,通常会出现一个明显的拐点,即曲线从下降阶段转为平缓下降或持平阶段的位置。这个拐点所对应的K值,即为肘部法则确定的较为合适的聚类数。

        请注意,肘部法则并不是一个绝对准确的方法,有时候K-SSE曲线可能没有明显的肘点,或者存在多个肘点。在实际应用中,我们可以结合领域知识和业务需求,综合考虑选择最合适的K值。另外,还可以尝试其他聚类评估指标(如轮廓系数、DBI等)来辅助确定最佳的K值。

from sklearn.cluster import KMeans
new_df = data.drop('CustomerID',axis=1)
# 肘部法则
loss = []
for i in range(2,10):
    model = KMeans(n_clusters=i).fit(new_df)
    loss.append(model.inertia_)
    
plt.plot(range(2,10),loss)
plt.xlabel('k')
plt.ylabel('loss')
plt.show()

 

方法2:轮廓系数

        轮廓系数(Silhouette Coefficient)是一种用于评估聚类质量的指标,可以帮助确定KMeans聚类算法中最佳的聚类数K。它结合了聚类的紧密度(簇内样本距离平均值)和分离度(不同簇之间样本距离平均值),从而提供一个综合的聚类效果评估。

轮廓系数的计算过程如下:

  1. 对于每个数据点,首先计算它与同簇其他数据点的平均距离,称为a(簇内紧密度)。

  2. 然后,对于每个数据点,计算它与其他簇中所有数据点的平均距离,找到其中最近的一个平均距离,称为b(簇间分离度)。

  3. 计算每个数据点的轮廓系数:s = (b - a) / max(a, b)

  4. 对于整个数据集,计算所有数据点的轮廓系数的平均值,作为整个聚类的轮廓系数。

轮廓系数的取值范围在-1到1之间:

  • 如果轮廓系数接近于1,则表示簇内样本紧密度高,簇间分离度较好,聚类效果较好。
  • 如果轮廓系数接近于-1,则表示簇内样本紧密度较低,簇间分离度不好,聚类效果较差。
  • 如果轮廓系数接近于0,则表示簇内外样本的距离相差不大,聚类效果一般。

        通常来说,较高的轮廓系数意味着更好的聚类效果。在使用轮廓系数确定K值时,我们可以尝试不同的K值,计算对应的轮廓系数,选择轮廓系数最大的K值作为最佳的聚类数。但是,需要注意的是,轮廓系数也有一定的局限性,特别是在数据分布不均匀或者聚类间有重叠的情况下,可能不适用于评估聚类效果。因此,综合考虑多种评估指标和领域知识,能够更全面地确定最佳的聚类数。

# 轮廓系数
from sklearn.metrics import silhouette_score
score = []
for i in range(2,10):
    model = KMeans(n_clusters=i).fit(new_df)
    score.append(silhouette_score(new_df, model.labels_, metric='euclidean'))
    
plt.plot(range(2,10),score)
plt.xlabel('k')
plt.ylabel('silhouette_score')
plt.show()

通过两种方法的结合,我们观察出最佳的聚类个数应该为k=6。

3.4 kmeans聚类

from sklearn.metrics import silhouette_score
kmeans = KMeans(n_jobs = -1, n_clusters = 6, init='k-means++')
kmeans.fit(new_df)
print(silhouette_score(new_df, kmeans.labels_, metric='euclidean'))
0.45206493204632353

将聚类结果进行可视化展示

clusters = kmeans.fit_predict(data.iloc[:,1:])
new_df["label"] = clusters
fig = plt.figure(figsize=(21,10))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(new_df.Age[new_df.label == 0], new_df["Annual Income (k$)"][new_df.label == 0], new_df["Spending Score (1-100)"][new_df.label == 0], c='blue', s=60)
ax.scatter(new_df.Age[new_df.label == 1], new_df["Annual Income (k$)"][new_df.label == 1], new_df["Spending Score (1-100)"][new_df.label == 1], c='red', s=60)
ax.scatter(new_df.Age[new_df.label == 2], new_df["Annual Income (k$)"][new_df.label == 2], new_df["Spending Score (1-100)"][new_df.label == 2], c='green', s=60)
ax.scatter(new_df.Age[new_df.label == 3], new_df["Annual Income (k$)"][new_df.label == 3], new_df["Spending Score (1-100)"][new_df.label == 3], c='orange', s=60)
ax.scatter(new_df.Age[new_df.label == 4], new_df["Annual Income (k$)"][new_df.label == 4], new_df["Spending Score (1-100)"][new_df.label == 4], c='black', s=60)
ax.scatter(new_df.Age[new_df.label == 5], new_df["Annual Income (k$)"][new_df.label == 5], new_df["Spending Score (1-100)"][new_df.label == 5], c='purple', s=60)
ax.view_init(30, 185)
plt.show()

3.5聚类结果

查看各聚类类别的个数

data['label'] = clusters
print(data['label'].value_counts())
data.head()

 分析各类别的变量差异

avg_df = data.groupby(['label'], as_index=False).mean()
plt.figure(figsize=(10,8))
plt.subplot(2,2,1)
sns.barplot(x='label',y='Age',data=avg_df)
plt.subplot(2,2,2)
sns.barplot(x='label',y='Gender',data=avg_df)
plt.subplot(2,2,3)
sns.barplot(x='label',y='Spending Score (1-100)',data=avg_df)
plt.subplot(2,2,4)
sns.barplot(x='label',y='Annual Income (k$)',data=avg_df)
plt.show()

通过图表我们可得出以下结论: 

各细分市场的主要特点

簇类0:  

低收入,低消费能力。  

平均年龄在40岁左右,性别以女性为主。  

簇类1:

中等收入,中等消费能力。

平均年龄在55岁左右,性别以女性为主。

簇类2:

低收入,高消费能力。

平均年龄在25岁左右,性别以女性为主。

簇类3:

高收入,高消费能力。

平均年龄在30岁左右,性别以女性为主。

簇类4:

中等收入,中等消费能力。

平均年龄在30岁左右,性别以女性为主。

簇类5:

高收入,低消费能力。

平均年龄在40岁左右,性别以男性为主。

 四、总结

        本实验基于KMeans算法对超市客户进行了聚类分群。通过对客户购物数据进行聚类,我们成功将客户分为不同的群体。每个群体代表了具有相似购物行为和偏好的客户群体。通过实验结果,我们发现了客户群体之间的明显差异和共性。不同群体的客户在购买频率、购物金额和购买种类等方面有所区别。这为超市提供了重要的市场细分信息,帮助超市经营者更好地了解不同客户群体的需求和喜好,制定有针对性的营销策略和商品推荐,提高客户满意度和忠诚度。此外,实验还揭示了超市客户的购物行为规律,为超市优化商品陈列和促销策略提供了指导。通过针对不同客户群体推出个性化的促销活动,超市可以更有效地吸引客户,提升销售额和利润。

完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font='SimHei')
import warnings
warnings.filterwarnings('ignore')

# 读取数据
data = pd.read_csv('Mall_Customers.csv')
data.head()
data.shape
data.info()
data['Gender'].replace(to_replace={'Female':0,'Male':1},inplace=True)
data.head()
from sklearn.cluster import KMeans
new_df = data.drop('CustomerID',axis=1)
# 肘部法则
loss = []
for i in range(2,10):
    model = KMeans(n_clusters=i).fit(new_df)
    loss.append(model.inertia_)
    
plt.plot(range(2,10),loss)
plt.xlabel('k')
plt.ylabel('loss')
plt.show()
# 轮廓分数
from sklearn.metrics import silhouette_score
score = []
for i in range(2,10):
    model = KMeans(n_clusters=i).fit(new_df)
    score.append(silhouette_score(new_df, model.labels_, metric='euclidean'))
    
plt.plot(range(2,10),score)
plt.xlabel('k')
plt.ylabel('silhouette_score')
plt.show()
from sklearn.metrics import silhouette_score
kmeans = KMeans(n_jobs = -1, n_clusters = 6, init='k-means++')
kmeans.fit(new_df)
print(silhouette_score(new_df, kmeans.labels_, metric='euclidean'))
clusters = kmeans.fit_predict(data.iloc[:,1:])
new_df["label"] = clusters
fig = plt.figure(figsize=(21,10))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(new_df.Age[new_df.label == 0], new_df["Annual Income (k$)"][new_df.label == 0], new_df["Spending Score (1-100)"][new_df.label == 0], c='blue', s=60)
ax.scatter(new_df.Age[new_df.label == 1], new_df["Annual Income (k$)"][new_df.label == 1], new_df["Spending Score (1-100)"][new_df.label == 1], c='red', s=60)
ax.scatter(new_df.Age[new_df.label == 2], new_df["Annual Income (k$)"][new_df.label == 2], new_df["Spending Score (1-100)"][new_df.label == 2], c='green', s=60)
ax.scatter(new_df.Age[new_df.label == 3], new_df["Annual Income (k$)"][new_df.label == 3], new_df["Spending Score (1-100)"][new_df.label == 3], c='orange', s=60)
ax.scatter(new_df.Age[new_df.label == 4], new_df["Annual Income (k$)"][new_df.label == 4], new_df["Spending Score (1-100)"][new_df.label == 4], c='black', s=60)
ax.scatter(new_df.Age[new_df.label == 5], new_df["Annual Income (k$)"][new_df.label == 5], new_df["Spending Score (1-100)"][new_df.label == 5], c='purple', s=60)
ax.view_init(30, 185)
plt.show()
data['label'] = clusters
print(data['label'].value_counts())
data.head()
avg_df = data.groupby(['label'], as_index=False).mean()
avg_df
plt.figure(figsize=(10,8))
plt.subplot(2,2,1)
sns.barplot(x='label',y='Age',data=avg_df)
plt.subplot(2,2,2)
sns.barplot(x='label',y='Gender',data=avg_df)
plt.subplot(2,2,3)
sns.barplot(x='label',y='Spending Score (1-100)',data=avg_df)
plt.subplot(2,2,4)
sns.barplot(x='label',y='Annual Income (k$)',data=avg_df)
plt.show()

文末推荐

《硅基物语-我是灵魂画手》

内容简介:

        一本将 AI 绘画讲透的探秘指南,通过丰富的实践案例操作,通俗易懂地讲述 AI 绘画的生成步骤,生动展现了 AI 绘画的魔法魅力。从历史到未来,跨越百年时空;从理论到实践,讲述案例操作;从技术到哲学,穿越多个维度;从语言到绘画,落地实战演练。AI 绘画的诞生,引发了奇点降临,点亮了 AGI(通用人工智能),并涉及 Prompt、风格、技术细节、多模态交互、AIGC 等一系列详细讲解。让您轻松掌握生图技巧,创造出独特的艺术作品,书写属于自己的艺术时代。

编辑推荐:

        用ChatGPT Midjourney画出人类的灵魂与梦想,用Stable Diffusion D-ID画出青春绚丽的渴望。激活每个人隐藏的绘画天赋,让任何人都能成为绘画大师。

文末福利

《硅基物语-我是灵魂画手》免费包邮送出3本!

  •  抽奖方式:评论区随机抽取3位小伙伴免费送出!
  • 参与方式:关注博主、点赞、收藏、评论区评论“人生苦短,拒绝内卷!”(切记要点赞+收藏,否则抽奖无效,每个人最多评论三次!
  • 活动截止时间:2023-08-04 20:00:00
  •  当当购买链接:http://product.dangdang.com/29601870.html

 名单公布时间:2023-08-04 21:00:00  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/821022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3 分钟全面了解 API Moke

一、什么是密闭服务? Google 测试团队的博客中,有一篇博文介绍的正是《Hermetic Servers(密闭服务)》。如下图所示,当被测试系统依赖了 Another Backend,这种依赖即产生了 “不可控” 因素。 怎么定义密闭…

ECharts:一款超实用的基于JavaScript的数据可视化图表库

一、ECharts的简单介绍 ECharts是一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级…

MapBox 做聚合图点位聚合效果实现教程

最近收到一个需求,要对 5000的点位进行展示。直接展示的话满屏幕都是点,效果太丑,于是想到了聚合,聚合有很多种方案。首先你可以手动的些代码来计算某个范围内的点的数量然后再把聚合的结果展示在这个范围的某个位置。这针对于简单…

使用java.io.BufferedReader的readLine()函数读入一行文本

说明 可以使用java.io.BufferedReader的readLine()函数读入一行文本,返回的字符串不包含回车和换行字符。 https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/io/BufferedReader.html#readLine() 代码示例 读取控制台的输入 使用下面的代码来验…

TSINGSEE青犀视频汇聚平台EasyCVR多种视频流播放协议介绍

众所周知,TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入,包括主流标准协议GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。今天我们来说一说,EasyCVR平台支持分…

年度最强大模型顶会来袭!喊话中国数百万AI开发者,速来!

能硬核 生态共创”“产业共振 智能涌现”“产教融合 人才共育”“携手飞桨 创新加速”2023年全球AI浪潮迭起,大语言模型热度空前,生成式人工智能为千行百业高质量发展带来更多想象空间。作为前沿科技风向标、汇聚全球开发者的顶级盛会,WAVE S…

Java on VS Code 7 月更新|反编译器支持升级、代码补全性能提升、AI 相关更新及更多

作者:Nick Zhu 排版:Alan Wang 大家好,欢迎来到 Visual Studio Code for Java 的7月更新!在这篇博客中,我们将为您提供有关反编译器支持的重要更新。此外,我们将分享更多最近代码补全性能提升的进展&#x…

B079-项目实战--支付模块 定时任务 项目总结

目录 概述示例jar包配置类任务详情 项目应用封装的工具类QuartzUtils封装IQuartzSrvice和QuartzServiceImpl封装参数QuartzJobInfo编写任务逻辑MainJob调用第三方支付前添加定时任务异步回调后移除定时任务 订单支付整体流程 概述 优势:Tmer不支持持久化&#xff0…

亚马逊水基灭火器UL8测试报告ISO17025实验室办理

在跨境电商平台上销售的境外电商,在美国市场中需要提供相关的安全规范报告。其中,美国相关部门要求,如果商家未能提交UL(Underwriters Laboratories)标准的检测报告,将会被责令停止销售。而为了在亚马逊、T…

【论文精读】用于多文档摘要生成的层次Transformer方法

前言 论文分享 来自2019ACL的多文档摘要生成方法论文,作者来自英国爱丁堡大学,引用数310 Hierarchical Transformers for Multi-Document Summarization 代码地址hiersumm 多文档摘要抽取的难点在于没有合适的数据集,同时过长的文档文本也导…

Makefile模板和工程模板(消息队列和共享内存)的使用

一、 Makefile模板 #指定生成的文件名 OJB_OUT test#指定每一个c文件对应的.o文件 OBJS a.o b.o main.o#指定编译器 CC gcc#指定需要的库 ULDFLAGS ########################################### #以下的内容不需要修改 ########################################### all:…

行业追踪,2023-08-01

自动复盘 2023-08-01 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

leetcode-143-重排链表

题意描述: 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要…

cmake+pybind11打包c++库成python wheel安装包

目录 写在前面准备1、pybind11获取源码编译安装 2、conda demo官方源码修改CMakeLists.txt编译生成安装测试 参考完 写在前面 1、本文内容 有时候我们需要用c代码,供python调用,本文提供将c库封装成python接口的方法,并将库打包成可通过pip安…

Apikit 自学日记:API 异常监控-创建 API 监控

如何在apikit中,创建 API 监控呢? 创建并开启监控API 一、手动创建监控API Eolink API 网络监控平台支持从 Eolink API Management(API管理产品)中导入API信息,或者手动创建监控API。 进入API监控页面,点击…

23款奔驰S450 4MATIC升级原厂流星雨智能数字大灯,让智能照亮您前行的路

凭借智能数字大灯 (DIGITAL LIGHT),您可体验根据其他道路使用者和周围环境进行优化调节的理想照明条件。这款包含130万像素模块大灯,进一步扩展了几何多光束 LED 大灯的功能。其高分辨率的照明可有针对性地点亮各个区域。解锁车辆时,大灯将通…

快速制作美容行业预约小程序

随着科技的不断进步,移动互联网的快速发展,小程序成为了很多行业迅速发展的利器。对于美容行业来说,一款美容预约小程序不仅可以方便用户进行预约,还可以提升美容店铺的服务质量和管理效率。下面,我们来介绍一下如何快…

23 设计模式(详细介绍附DEMO)

设计模式在Java中的应用与实现 🚀🚀🚀1.创建型模式1. 工厂方法模式(Factory Pattern)2.抽象工厂模式(Abstract Factory Pattern)3. 单例模式(Singleton Pattern)4.原型模…

rfid资产盘点管理系统软件

很多企业开始规划固定资产的总结,或者现在开始总结资产。面对众多不同种类的固定资产,总结已经成为一项工程量大、耗时长的任务。采用轻松的RFID固定资产管理系统后,可以大大提高这种总结工作的效率,获得比过去更清晰的资产清单和…

三菱plcCCLINK转profinet与西门子PLC通讯案例分析

用三菱PLC的控制系统需要和西门子的PLC控制系统交互数据,捷米JM-PN-CCLK 是自主研发的一款 PROFINET 从站功能的通讯网关。该产品主要功能是将各种 CCLINK 总线和 PROFINET 网络连接起来。 捷米JM-PN-CCLK总线中做为从站使用,连接到 CCLINK 总线中做为…