KMeans算法在RFM模型(用户分层模型)上的应用

2024-01-17 12:20

本文主要是介绍KMeans算法在RFM模型(用户分层模型)上的应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

KMeans在RFM模型上的应用

RFM模型到底是个啥,建议先参考百度百科以及知乎的解释。
KMeans算法又是个啥,一言以蔽之:无监督学习的聚类算法(也就是俗话讲的物以类聚,人以群分)。
废话不多说,开始上手

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
data = pd.read_excel('./consumption_data.xls', index_col='Id')
data.head()

解释下这个数据集:字段R表示最近一次消费(Recency),字段F表示消费频率(Frequency),字段M表示消费金额(Monetary)
- 字段R:最近一次消费指上一次购买的时间——用户上一次是什么时候下的单、用户上一次是什么时候订购的服务,或在线下门店中用户上一次进店购买是什么时候。
- 字段F:消费频率指的是顾客在限定的期间内所购买的次数。一般而言,最常购买的用户,也是满意度/忠诚度最高的顾客,同时也是对品牌认可度最高的用户。
- 字段M:消费金额是电商相关业务数据库的支柱,也可以用来验证“帕雷托法则”——公司80%的收入来自20%的顾客。M值带有时间范围,指的是一段时间(通常是1年)内的消费金额。对于一般电商店铺而言,M值对客户细分的作用相对较弱(因为客单价波动幅度不大)。

RFM
Id
1276232.61
2351507.11
3416817.62
4311232.81
51471913.05
data.shape
(940, 3)
data.index
Int64Index([  1,   2,   3,   4,   5,   6,   7,   8,   9,  10,...933, 934, 935, 936, 937, 938, 939, 940, 941, 942],dtype='int64', name='Id', length=940)

数据标准化

data_std = 1.0 * (data - data.mean()) / data.std()
data_std.head()
RFM
Id
10.764186-0.493579-1.158711
2-1.024757-0.6300790.622527
3-0.9502170.871423-0.341103
4-1.0247570.188922-1.158432
5-0.204824-0.3570791.189868
k =8  # k-1个簇
iteration = 500  # 聚类最大循环次数
inertia = []  # 簇内误差平方和
for i in range(1, k):model = KMeans(n_clusters=i, n_jobs=4, max_iter=iteration, random_state=1234)model.fit(data_std)inertia.append(model.inertia_)
font = {'family':'SimHei', 'size':'20'}
plt.rc('font', **font)
plt.figure(figsize=(20,6))
plt.plot(range(1, k), inertia)
plt.title('查看最佳k值', fontsize=20)
plt.xlabel('簇的数量')
plt.ylabel('簇内误差平方和')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RP58bDaK-1645165442623)(output_8_0.png)]

label = pd.Series(model.labels_)
labels = label.value_counts()
labels   #  每个类簇的样本数
1    218
2    189
5    182
6    173
0    144
4     28
3      6
dtype: int64
centers = pd.DataFrame(model.cluster_centers_)
centers    # 簇类中心
012
00.4882871.1539020.260323
1-0.206534-0.5461750.766205
20.496397-0.645968-0.674198
30.8635720.7121737.363321
44.025280-0.1377030.273264
5-0.643460-0.727579-0.853512
6-0.6929921.1964980.152670
# 拼接类簇的数目和簇类中心
output = pd.concat([labels, centers], axis=1)
output
0012
01440.4882871.1539020.260323
1218-0.206534-0.5461750.766205
21890.496397-0.645968-0.674198
360.8635720.7121737.363321
4284.025280-0.1377030.273264
5182-0.643460-0.727579-0.853512
6173-0.6929921.1964980.152670

KMeans追求的效果是:同一聚类内部距离最小化,不同聚类组间距离最大化

其实,聚类处理到这一步,已经可以有一些结论出来了。上面我们聚了7个类别,实际有的类别所包含的样本量比较少,例如类别3和类别4,所以可以重新把上面的步骤跑一遍,然后把k值设置更小一些。

output.columns = ['样本数', 'R', 'F', 'M']
output.columns
Index(['样本数', 'R', 'F', 'M'], dtype='object')
output
样本数RFM
01440.4882871.1539020.260323
1218-0.206534-0.5461750.766205
21890.496397-0.645968-0.674198
360.8635720.7121737.363321
4284.025280-0.1377030.273264
5182-0.643460-0.727579-0.853512
6173-0.6929921.1964980.152670
output.iloc[3]['F']
0.71217272223757799

详细标记原始数据每个样本的类别

model.labels_
array([2, 1, 6, 5, 1, 2, 5, 2, 2, 6, 5, 2, 1, 0, 1, 6, 4, 2, 5, 2, 5, 1, 6,2, 2, 0, 1, 1, 2, 3, 6, 2, 5, 1, 6, 6, 5, 1, 1, 2, 5, 6, 5, 5, 6, 1,2, 2, 6, 6, 1, 1, 1, 6, 2, 2, 1, 4, 1, 2, 5, 0, 6, 1, 1, 2, 1, 1, 2,1, 0, 0, 5, 2, 1, 5, 4, 6, 6, 1, 2, 2, 5, 2, 5, 6, 0, 2, 5, 0, 4, 5,6, 6, 2, 1, 6, 2, 6, 6, 5, 2, 4, 0, 0, 5, 5, 0, 0, 5, 2, 6, 1, 5, 2,2, 5, 2, 4, 0, 2, 1, 5, 2, 2, 2, 5, 2, 2, 0, 1, 2, 5, 5, 2, 2, 5, 2,4, 2, 1, 1, 5, 0, 2, 5, 5, 2, 0, 1, 6, 1, 6, 5, 2, 2, 1, 5, 1, 1, 1,0, 2, 2, 5, 5, 5, 5, 0, 5, 0, 6, 6, 1, 2, 1, 2, 2, 6, 5, 0, 5, 1, 2,2, 6, 2, 6, 6, 1, 2, 0, 4, 2, 1, 1, 1, 1, 5, 5, 5, 5, 2, 5, 5, 1, 2,2, 1, 1, 5, 5, 0, 6, 2, 5, 5, 2, 0, 2, 1, 6, 1, 5, 2, 3, 5, 1, 5, 6,2, 2, 1, 1, 1, 2, 2, 1, 5, 5, 5, 1, 1, 0, 5, 1, 5, 2, 5, 6, 6, 0, 1,5, 4, 2, 2, 2, 1, 0, 5, 6, 1, 1, 6, 2, 6, 2, 4, 1, 2, 2, 1, 6, 0, 6,1, 6, 5, 1, 1, 4, 2, 1, 2, 1, 0, 0, 1, 5, 6, 2, 5, 5, 1, 1, 5, 4, 5,4, 0, 6, 5, 0, 1, 1, 5, 1, 6, 2, 5, 6, 2, 1, 5, 1, 6, 4, 1, 0, 2, 5,1, 6, 6, 1, 2, 5, 1, 6, 5, 0, 4, 1, 0, 0, 2, 6, 3, 6, 5, 2, 1, 2, 0,5, 5, 1, 5, 0, 2, 5, 2, 6, 5, 0, 2, 6, 0, 5, 1, 6, 0, 2, 6, 2, 2, 0,1, 2, 2, 0, 6, 6, 1, 2, 6, 5, 2, 6, 2, 6, 5, 1, 5, 1, 1, 6, 5, 5, 6,5, 6, 0, 2, 0, 5, 1, 6, 2, 1, 6, 6, 2, 6, 0, 0, 0, 1, 6, 2, 6, 6, 1,6, 6, 6, 5, 4, 1, 5, 6, 5, 0, 0, 2, 1, 6, 0, 0, 1, 5, 1, 6, 0, 1, 0,1, 0, 2, 6, 6, 5, 6, 5, 0, 5, 2, 6, 5, 1, 2, 1, 6, 5, 1, 5, 6, 6, 5,6, 5, 0, 5, 0, 0, 6, 1, 0, 6, 0, 0, 5, 2, 0, 1, 0, 2, 1, 6, 1, 1, 6,3, 5, 2, 1, 1, 5, 5, 2, 6, 6, 1, 6, 5, 1, 0, 1, 0, 6, 1, 1, 1, 5, 1,1, 0, 5, 6, 0, 1, 0, 0, 1, 0, 5, 0, 5, 2, 1, 2, 6, 0, 3, 1, 2, 1, 2,5, 0, 2, 6, 0, 5, 1, 2, 0, 0, 6, 6, 1, 0, 5, 0, 1, 1, 6, 5, 1, 2, 5,0, 1, 1, 0, 2, 6, 1, 1, 0, 1, 5, 1, 1, 5, 5, 0, 0, 1, 1, 6, 6, 1, 0,2, 0, 6, 1, 6, 2, 1, 2, 5, 5, 6, 2, 2, 6, 0, 5, 2, 2, 6, 0, 5, 0, 6,5, 0, 0, 5, 5, 2, 1, 6, 0, 2, 0, 1, 5, 4, 2, 2, 5, 5, 2, 5, 1, 0, 1,2, 0, 6, 5, 4, 1, 1, 2, 0, 6, 6, 1, 5, 0, 6, 0, 1, 1, 5, 4, 1, 6, 0,2, 2, 1, 5, 1, 0, 2, 6, 2, 4, 0, 6, 5, 5, 0, 2, 1, 1, 5, 1, 6, 0, 1,6, 1, 4, 6, 6, 6, 1, 1, 1, 1, 0, 1, 5, 1, 5, 0, 2, 6, 5, 5, 2, 5, 1,0, 1, 1, 0, 1, 6, 1, 1, 1, 1, 4, 6, 1, 2, 1, 1, 2, 6, 2, 2, 6, 1, 2,5, 6, 6, 5, 5, 1, 1, 4, 0, 6, 5, 5, 5, 5, 1, 0, 1, 6, 5, 1, 0, 0, 5,2, 4, 2, 2, 2, 1, 6, 2, 5, 5, 5, 2, 1, 2, 5, 5, 0, 0, 6, 6, 2, 6, 1,0, 0, 6, 0, 2, 0, 0, 2, 6, 6, 0, 0, 1, 2, 6, 6, 5, 5, 6, 5, 6, 6, 2,1, 1, 5, 5, 1, 1, 2, 6, 2, 4, 2, 4, 6, 5, 0, 2, 6, 0, 6, 6, 5, 6, 1,0, 0, 5, 6, 1, 5, 5, 5, 5, 2, 2, 1, 6, 0, 6, 5, 6, 0, 2, 1, 0, 2, 1,2, 0, 1, 6, 2, 2, 0, 2, 5, 0, 1, 0, 0, 6, 5, 1, 1, 5, 2, 6, 1, 5, 2,5, 2, 2, 2, 1, 1, 0, 1, 1, 0, 6, 5, 5, 6, 5, 1, 0, 6, 2, 1, 0, 0, 2,0, 0, 6, 6, 1, 2, 1, 4, 0, 1, 6, 5, 1, 6, 2, 2, 0, 6, 6, 2, 1, 6, 1,6, 2, 4, 2, 2, 1, 2, 2, 0, 1, 6, 5, 2, 6, 6, 5, 1, 6, 1, 2, 5, 5, 2,6, 1, 2, 2, 0, 1, 6, 0, 0, 0, 1, 6, 3, 6, 1, 1, 5, 1, 2, 2])
data.index
Int64Index([  1,   2,   3,   4,   5,   6,   7,   8,   9,  10,...933, 934, 935, 936, 937, 938, 939, 940, 941, 942],dtype='int64', name='Id', length=940)
summary = pd.concat([data, pd.Series(model.labels_, index=data.index)], axis=1)
summary.head()
RFM0
Id
1276232.612
2351507.111
3416817.626
4311232.815
51471913.051
summary.columns = ['R', 'F', 'M', 'label']
summary.head()
RFMlabel
Id
1276232.612
2351507.111
3416817.626
4311232.815
51471913.051
summary.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 940 entries, 1 to 942
Data columns (total 4 columns):
R        940 non-null int64
F        940 non-null int64
M        940 non-null float64
label    940 non-null int32
dtypes: float64(1), int32(1), int64(2)
memory usage: 33.0 KB
# 类别0
dd = summary[summary['label'] == 0]
dd.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 144 entries, 13 to 929
Data columns (total 5 columns):
Id       144 non-null int64
R        144 non-null int64
F        144 non-null int64
M        144 non-null float64
label    144 non-null int64
dtypes: float64(1), int64(4)
memory usage: 6.8 KB
# 用户群0(label=0)
plt.figure(figsize=(12,9))
plt.subplot(311)
dd['R'].plot(kind='kde')
plt.legend()
plt.subplot(312)
dd['F'].plot(kind='kde')
plt.legend()
plt.subplot(313)
dd['M'].plot(kind='kde')
plt.legend()
plt.show()

output_24_0

分群0的特点

  • R 间隔多分布在0到15天左右
  • F 消费频率集中在10到25次
  • M 消费金额集中在500到2000左右
# 用户群1(label=1)
dd1 = summary[summary['label'] == 1]plt.figure(figsize=(12,9))
plt.subplot(311)
dd1['R'].plot(kind='kde')
plt.legend()
plt.subplot(312)
dd1['F'].plot(kind='kde')
plt.legend()
plt.subplot(313)
dd1['M'].plot(kind='kde')
plt.legend()
plt.show()

output_26_0

分群1的特点

  • R 间隔多分布在0到35天左右
  • F 消费频率集中在0到12次
  • M 消费金额集中在1000到2000左右

其他用户的分群同理,都可以整理出来。

那么问题来了,整理这些分群特点有什么用处呢?
用处就是可以把用户拆分成不同的用户包,支持后期对用户的精细化运营,例如给不同的用户群设置不同额度的优惠券,或者给不同的用户群推广不同价位的商品等等。

-------------------------------------END--------------------------------------------

这篇关于KMeans算法在RFM模型(用户分层模型)上的应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/kun_csdn/article/details/123002654
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/616019

相关文章

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

Mysql中的用户管理实践

《Mysql中的用户管理实践》:本文主要介绍Mysql中的用户管理实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录13. 用户管理13.1 用户 13.1.1 用户信息 13.1.2 创建用户 13.1.3 删除用户 13.1.4 修改用户

Python Flask 库及应用场景

《PythonFlask库及应用场景》Flask是Python生态中​轻量级且高度灵活的Web开发框架,基于WerkzeugWSGI工具库和Jinja2模板引擎构建,下面给大家介绍PythonFl... 目录一、Flask 库简介二、核心组件与架构三、常用函数与核心操作 ​1. 基础应用搭建​2. 路由与参

Spring Boot中的YML配置列表及应用小结

《SpringBoot中的YML配置列表及应用小结》在SpringBoot中使用YAML进行列表的配置不仅简洁明了,还能提高代码的可读性和可维护性,:本文主要介绍SpringBoot中的YML配... 目录YAML列表的基础语法在Spring Boot中的应用从YAML读取列表列表中的复杂对象其他注意事项总

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

CSS 样式表的四种应用方式及css注释的应用小结

《CSS样式表的四种应用方式及css注释的应用小结》:本文主要介绍了CSS样式表的四种应用方式及css注释的应用小结,本文通过实例代码给大家介绍的非常详细,详细内容请阅读本文,希望能对你有所帮助... 一、外部 css(推荐方式)定义:将 CSS 代码保存为独立的 .css 文件,通过 <link> 标签

Python使用Reflex构建现代Web应用的完全指南

《Python使用Reflex构建现代Web应用的完全指南》这篇文章为大家深入介绍了Reflex框架的设计理念,技术特性,项目结构,核心API,实际开发流程以及与其他框架的对比和部署建议,感兴趣的小伙... 目录什么是 ReFlex?为什么选择 Reflex?安装与环境配置构建你的第一个应用核心概念解析组件

C#通过进程调用外部应用的实现示例

《C#通过进程调用外部应用的实现示例》本文主要介绍了C#通过进程调用外部应用的实现示例,以WINFORM应用程序为例,在C#应用程序中调用PYTHON程序,具有一定的参考价值,感兴趣的可以了解一下... 目录窗口程序类进程信息类 系统设置类 以WINFORM应用程序为例,在C#应用程序中调用python程序

Java应用如何防止恶意文件上传

《Java应用如何防止恶意文件上传》恶意文件上传可能导致服务器被入侵,数据泄露甚至服务瘫痪,因此我们必须采取全面且有效的防范措施来保护Java应用的安全,下面我们就来看看具体的实现方法吧... 目录恶意文件上传的潜在风险常见的恶意文件上传手段防范恶意文件上传的关键策略严格验证文件类型检查文件内容控制文件存储

CSS3 布局样式及其应用举例

《CSS3布局样式及其应用举例》CSS3的布局特性为前端开发者提供了无限可能,无论是Flexbox的一维布局还是Grid的二维布局,它们都能够帮助开发者以更清晰、简洁的方式实现复杂的网页布局,本文给... 目录深入探讨 css3 布局样式及其应用引言一、CSS布局的历史与发展1.1 早期布局的局限性1.2