数据挖掘实战:基于KMeans算法对超市客户进行聚类分群

简介: 数据挖掘实战:基于KMeans算法对超市客户进行聚类分群

一、研究背景


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


       为了实现客户细分,研究者和业界常常采用聚类分析的方法。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或者更大的范围,具体根据问题的复杂程度而定。


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


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


  1. 寻找“肘点”:观察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(簇内紧密度)。


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


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


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


轮廓系数的取值范围在-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()
目录
相关文章
|
4月前
|
存储 缓存 算法
前端算法:优化与实战技巧的深度探索
【10月更文挑战第21天】前端算法:优化与实战技巧的深度探索
40 1
|
5月前
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
83 2
|
5月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
85 4
|
6月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
226 1
|
6月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点展示了如何使用 Kotlin 实现 AES-256 的加密和解密,提供了详细的代码示例。
118 2
|
6月前
|
机器学习/深度学习 存储 算法
强化学习实战:基于 PyTorch 的环境搭建与算法实现
【8月更文第29天】强化学习是机器学习的一个重要分支,它让智能体通过与环境交互来学习策略,以最大化长期奖励。本文将介绍如何使用PyTorch实现两种经典的强化学习算法——Deep Q-Network (DQN) 和 Actor-Critic Algorithm with Asynchronous Advantage (A3C)。我们将从环境搭建开始,逐步实现算法的核心部分,并给出完整的代码示例。
454 1
|
6月前
|
机器学习/深度学习 算法 数据挖掘
【白话机器学习】算法理论+实战之决策树
【白话机器学习】算法理论+实战之决策树
111 0
|
6月前
|
消息中间件 存储 算法
这些年背过的面试题——实战算法篇
本文是技术人面试系列实战算法篇,面试中关于实战算法都需要了解哪些内容?一文带你详细了解,欢迎收藏!
|
6月前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
60 0
|
6月前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
58 0