算法模型-RMF

算法模型-RMF算法模型 RMF 原文链接 https blog csdn net u0 article details https www jianshu com p 4

大家好,欢迎来到IT知识分享网。

算法模型-RMF

一、RFM模型概述

1、R值:最近一次消费(Recency)

  • 1、客户R值呈规律性的“波浪形”分布,时间越长,波浪越小;
  • 2、最近一年内用户占比50%(真的很巧);

数据分析:这个数据是比较理想了的。说明每引入2个客户,就有一位用户在持续购买。说明店铺复购做的比较好,R值在不断的变为0。

2、F值:消费频率(Frequency)

  • 1、购买1次(新客户)占比为65.5%,产生重复购买(老客户)的占比为34.4%;
  • 2、购买3次及以上(成熟客户)的占比为17%,购买5次及以上(忠实客户)的占比为6%。

3、M值:消费金额(Monetary)

所以我认为用店铺的累计购买金额和平均客单价替代传统的M值能更好的体现客户消费金额的差异。

二、基于RFM模型的实践应用

1、基于RFM模型进行客户细分

店铺的客户基数:在店铺客户一定的情况下选择的维度越多,细分出来每一组的用户越少。
对于店铺基数不大(5万以下客户数)的店铺而言,选择1-2个维度进行细分即可。
对于客户超过50万的大卖家而言可以选择2-3个指标。

店铺的商品和客户结构:如果在店铺的商品层次比较单一,客单价差异幅度不大的情况下,
购买频次(F值)和消费金额(M值)高度相关的情况下,可以只选择比较容易操作的购买频次(F值)代替消费金额(M值)。
对于刚刚开店还没形成客户粘性的店铺,则可以放弃购买频次(F值),直接用最后一次消费(R值)或者消费金额(M值)。

2、RFM模型评分

主要有三个部分:

  • 1、确定RFM三个指标的分段和每个分段的分值;
  • 2、计算每个客户RFM三个指标的得分;
  • 3、计算每个客户的总得分,并且根据总得分筛选出优质的客户

Alt text

三、R语言实现RMF

1、RMF模型说明

RMF模型是客户管理中,常被用来衡量客户价值和客户创利能力的重要方法。它主要考量三个指标:

  • 最近一次消费-Recency:近期购买的客户倾向于再度购买
  • 消费频率-Frequency:经常购买的客户再次购买概率高
  • 消费金额-Monetary:消费金额较多的客户再次消费可能性更大

或者进一步针对不同的业务场景,对R、F、M赋予不同权重Wr、Wf、Wm,得到每个用户的得分:W=WrR+WfF+Wm*M。
根据最终得分W排序,再划分等级,采用不用的营销策略。

RFM模型其实很简单,其重点应该是在:

2、R语言实现RMF

用来做分析的数据应该是一段时间里累计的客户的消费记录,每笔记录至少需要客户名称消费时间消费金额三个要素。

用R生成模拟随机消费记录数据。客户编号为1000-1999共100人,消费记录10000条,
消费记录产生时间在2014-01-01到2015-12-29之间。



观察数据结构:

str(sales) 'data.frame': 10000 obs. of 4 variables: $ 用户ID : int 1017 1583 1351 1013 1720 1938 1770 1319 1896 1067 ... $ 消费金额: num 157 201 228 199 302 173 131 218 191 232 ... $ 消费时间: Date, format: "2014-01-01" ... $ 距离时间: num 1565 1565 1565 1565 1565 ... head(sales) 用户ID 消费金额 消费时间 距离时间 1 1017 157 2014-01-01 1565 2 1583 201 2014-01-01 1565 3 1351 228 2014-01-01 1565 4 1013 199 2014-01-01 1565 5 1720 302 2014-01-01 1565 6 1938 173 2014-01-01 1564 

客户编号为1000-1999共100人,消费记录10000条,消费记录产生时间在2014-01-01到2015-12-29之间。

根据上述消费记录,得到Recency、Frequency、Monetary的值。

  • 总消费金额
sales$距离时间 <- round(as.numeric(difftime(Sys.Date(),sales[,3],units = "days"))) names(salesM) <- c("用户ID","总消费") 
  • 消费次数
salesF <- aggregate(sales[,2],list(sales$用户ID),length) names(salesF) <- c("用户ID","消费次数") 
  • 最近一次消费时间
saleR <- aggregate(sales[,4],list(sales$用户ID),min) names(salesR) <- c("用户ID","最近消费时间") test1<- merge(salesF,salesR,"用户ID") salesRFM<- merge(salesM,test1,"用户ID") head(salesRFM) 用户ID 总消费 消费次数 最近消费时间 1 1000 1281 8 855 2 1001 1442 8 1019 3 1002 919 5 887 4 1003 1437 7 893 5 1004 1461 8 917 6 1005 964 7 970 
salesRFM0 <- salesRFM salesRFM0$rankR <- cut(salesRFM$Recency,5,labels=F) salesRFM0$最近消费时间 <- cut(salesRFM$Recency,5,labels=F) salesRFM0$rankR <- cut(salesRFM$最近消费时间,5,labels=F) salesRFM0$rankR <- 6- salesRFM0$rankR salesRFM0$rankF <- cut(salesRFM0$消费次数,5,labels=F) salesRFM0$rankM <- cut(salesRFM0$总消费,5,labels=F) salesRFM0$rankRMF <- 0.5*rankR + 0.3*rankF+ 0.2*rankM salesRFM0$rankRMF <- 0.5*salesRFM0$rankR+0.3*salesRFM0$rankF+0.2*salesRFM0$rankM 
> head(salesRFM0) 用户ID 总消费 消费次数 最近消费时间 rankR rankF 1 1000 1281 8 855 5 2 2 1001 1442 8 1019 4 2 3 1002 919 5 887 5 1 4 1003 1437 7 893 5 2 5 1004 1461 8 917 5 2 6 1005 964 7 970 4 2 rankM rankRMF 1 2 3.5 2 2 3.0 3 1 3.0 4 2 3.5 5 2 3.5 6 1 2.8 

对Receny、Frequency、Monetary标准化后,以权重权重0.5,0.3,0.2来求客户最终得分,客户最终得分在0-1之间。

> salesRFM1$rankF <- (salesRFM1$消费次数-min(salesRFM1$消费次数))/(max(salesRFM1$消费次数)-min(salesRFM1$消费次数)) > salesRFM1$rankM <- (salesRFM1$总消费)-min(salesRFM1$总消费))/(max(salesRFM1$总消费)-min(salesRFM1$总消费)) Error: unexpected ')' in "salesRFM1$rankM <- (salesRFM1$总消费)-min(salesRFM1$总消费))" > salesRFM1$rankM <- (salesRFM1$总消费-min(salesRFM1$总消费))/(max(salesRFM1$总消费)-min(salesRFM1$总消费)) > salesRFM1$rankRMF <- 0.5*salesRFM1$rankR+03*salesRFM1$rankF+0.2*salesRFM1$rankM > head(salesRFM1) 用户ID 总消费 消费次数 最近消费时间 rankR 1 1000 1281 8 855 0. 2 1001 1442 8 1019 0. 3 1002 919 5 887 0. 4 1003 1437 7 893 0. 5 1004 1461 8 917 0. 6 1005 964 7 970 0. rankF rankM rankRMF 1 0. 0. 1. 2 0. 0. 1. 3 0. 0. 0. 4 0. 0. 1. 5 0. 0. 1. 6 0. 0. 1.0 

四、python实现RMF

1、RFM算法步骤:

1.1、计算RFM各项分值
1.2、归总RFM分值

2、根据RFM分值对客户分类

# encoding: utf-8 # 导入包 import pandas as pd 写入excel设置问题 import xlsxwriter # 定义RFM函数 def RFM(aggData): """ :param aggData: 输入数据集,数据集字段要包含recency,frequency,monetary等三个字段 :return:返回数据集结果 """ # 计算R_S bins = aggData.recency.quantile(q=[0, 0.28, 0.38, 0.46, 0.53, 0.57, 0.77, 1], interpolation='nearest') bins[0] = 0 labels = [7, 6, 5, 4, 3, 2, 1] R_S = pd.cut(aggData.recency, bins, labels=labels) # 计算F_S bins = aggData.frequency.quantile(q=[0, 0.29, 0.45, 0.60, 0.71, 0.76, 0.90, 1], interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5, 6, 7] F_S = pd.cut(aggData.frequency, bins, labels=labels) # 计算M_S bins = aggData.monetary.quantile(q=[0, 0.20, 0.26, 0.45, 0.55, 0.76, 0.85, 1], interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5, 6, 7] M_S = pd.cut(aggData.monetary, bins, labels=labels) # 赋值 aggData['R_S'] = R_S aggData['F_S'] = F_S aggData['M_S'] = M_S # 计算FRM值 aggData['RFM'] = R_S.astype(int)*1 + F_S.astype(int)*1 + M_S.astype(int)*1 # 根据RFM分值对客户分类 #分五类 bins = aggData.RFM.quantile(q=[0, 0.2, 0.4, 0.6, 0.8, 1],interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5] aggData['level'] = pd.cut(aggData.RFM,bins, labels=labels) return aggData # 主函数 if __name__ == '__main__': # 读取数据 aggData = pd.read_csv('C:\\Users\\xiaohu\\Desktop\\月刊数据\\4月份用户价值数据.csv') # 调用模型函数 result=RFM(aggData) # 打印结果 print(result) # 计算每个类别的数据量 c1=list(result["level"].value_counts()) # 计算每个类别所占的百分比 c2 = list(result["level"].value_counts()/len(result)*100) c3=(list(map(lambda x:str(round(x,3))+"%",c2))) c=pd.DataFrame({ 
   "level":range(1,len(c1)+1),"数量":c1,"百分比":c3}) print(c) # 写出csv result.to_csv('C:\\result5_50_四月份.csv',index=False) 

3、RFM+kmeans算法

# 导入包 from __future__ import division import pandas as pd from sklearn.cluster import KMeans python画图显示中文参数设置 设置中文显示 from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei'] font_size =11 # 字体大小 fig_size = (8, 6) # 图表大小 # 更新字体大小 mpl.rcParams['font.size'] = font_size # 更新图表大小 mpl.rcParams['figure.figsize'] = fig_size # 定义RFM函数 def RFM(aggData): """ :param aggData: 输入数据集,数据集字段要包含recency,frequency,monetary等三个字段 :return:返回数据集结果 """ # 计算R_S bins = aggData.recency.quantile(q=[0, 0.31, 0.38, 0.46, 0.53, 0.57, 0.77, 1], interpolation='nearest') bins[0] = 0 labels = [7, 6, 5, 4, 3, 2, 1] R_S = pd.cut(aggData.recency, bins, labels=labels) # 计算F_S bins = aggData.frequency.quantile(q=[0, 0.29, 0.45, 0.60, 0.71, 0.76, 0.90, 1], interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5, 6, 7] F_S = pd.cut(aggData.frequency, bins, labels=labels) # 计算M_S bins = aggData.monetary.quantile(q=[0, 0.20, 0.26, 0.45, 0.55, 0.76, 0.85, 1], interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5, 6, 7] M_S = pd.cut(aggData.monetary, bins, labels=labels) # 赋值 aggData['R_S'] = R_S aggData['F_S'] = F_S aggData['M_S'] = M_S # 计算FRM值 aggData['RFM'] = R_S.astype(int) + F_S.astype(int) + M_S.astype(int) #分五类 bins = aggData.RFM.quantile(q=[0, 0.2, 0.4, 0.6, 0.8, 1],interpolation='nearest') bins[0] = 0 labels = [1, 2, 3, 4, 5] aggData['level'] = pd.cut(aggData.RFM,bins, labels=labels) return aggData # 读取数据 aggData = pd.read_csv('C:\\Users\\xiaohu\\Desktop\\用户价值分析\\用户价值分析RFM模型\\source\\RFM_Data_50.csv') # print(aggData) aggData2=RFM(aggData) print(aggData2) # 选择recency,frequency,monetary这三列 data=aggData2.loc[:,['recency','frequency','monetary']] print(data) # 定义数据标准化函数 Min-max 标准化 def Normalization(df): return df.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x))) # 调用函数进行数据标准化(0-1)之间 zsredfile=Normalization(data) # 对列进行重命名 names = ['ZR','ZF','ZM'] zsredfile.columns = names print(zsredfile) 选择最佳的K值 """ 一般我们可以 通过迭代的方式选出合适的聚类个数 ,即让k值从1到K依次执行一遍, 再查看每一次k值对应的簇内离差平方和之和的变化, 如果变化幅度突然由大转小时,那个k值就是我们选择的合理个数 """ K = range(1,15) GSSE = [] for k in K: print(K) SSE = [] kmeans = KMeans(n_clusters=k, random_state=10) kmeans.fit(zsredfile) labels = kmeans.labels_ centers = kmeans.cluster_centers_ for label in set(labels): SSE.append(np.sum(np.sum((zsredfile[['ZR', 'ZF','ZM']].loc[labels == label,] - centers[label, :])  2))) GSSE.append(np.sum(SSE)) # 绘制K的个数与GSSE的关系 plt.plot(K, GSSE, 'b*-') plt.xlabel('聚类个数') plt.ylabel('簇内离差平方和') plt.title('选择最优的聚类个数') plt.show() #选择最优的聚类个数为5 seed(123) #调用sklearn的库函数 num_clusters = 5 kmeans = KMeans(n_clusters=num_clusters, random_state=1) kmeans.fit(zsredfile) # 聚类结果标签 data['cluster'] = kmeans.labels_ # 聚类中心 centers = kmeans.cluster_centers_ cluster_center = pd.DataFrame(kmeans.cluster_centers_) # 绘制散点图 plt.scatter(x = zsredfile.iloc[:,0], y = zsredfile.iloc[:,1], c = data['cluster'], s=50, cmap='rainbow') plt.scatter(centers[:,0], centers[:,1], c='k', marker = '*', s = 180) plt.xlabel('ZR') plt.ylabel('ZF') plt.title('聚类效果图') # 图形显示 plt.show() #查看RFM模型8个类别中的用户数量以及占比多少 result=data aggData2['cluster']=result["cluster"] # 计算每个类别的数据量 c1 = list(result["cluster"].value_counts()) # 计算每个类别所占的百分比 c2 = list(result["cluster"].value_counts() / len(result) * 100) c3 = (list(map(lambda x: str(round(x, 3)) + "%", c2))) c = pd.DataFrame({ 
   "level": range(1, len(c1) + 1), "数量": c1, "百分比": c3}) print(c) # 写出csv aggData2.to_csv('C:\\Users\python_result_kmeans_50.csv', index=False) cluster_center.to_csv('C:\\Users\\cluster_center.csv') 

4、RFM+层次聚类

#加载相关库  import numpy as np import pandas as pd from sklearn.cluster import DBSCAN from sklearn.cluster import Birch from sklearn import metrics from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline from sklearn.externals import joblib import time import datetime #加载数据集及提取数列 customdata = pd.read_csv(r'C:\\Users\\xiaohu\\Desktop\\RFM\\out_custom_label.csv') new_custom_data = customdata[["R_S","F_S","M_S"]] new_custom_data = new_custom_data.astype(np.float32) new_custom_data = new_custom_data.values #数据标准化 new_custom_data = StandardScaler().fit_transform(new_custom_data) #模型训练 Birch_model = Birch(threshold=0.85, branching_factor=500, n_clusters=None,compute_labels=True, copy=True).fit(new_custom_data) #提取分类结果 label = Birch_model.labels_ label = pd.DataFrame(label) label.columns = ['cluster.label'] outresult = pd.concat([customdata, label], axis = 1) cluster_center = pd.DataFrame(Birch_model.subcluster_centers_) n_clusters = np.unique(label).size print("n_clusters : %d" % n_clusters) #结果输出 outresult.to_csv('C:\\Users\\birch_outresult.csv') cluster_center.to_csv('C:\\Users\\cluster_center.csv') 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112435.html

(0)
上一篇 2026-01-18 12:26
下一篇 2026-01-18 12:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信