龙空技术网

使用K-Means将RFM原则应用于客户聚类

林小婵的店 575

前言:

目前朋友们对“kmeans算法的rfm”大体比较注意,兄弟们都想要知道一些“kmeans算法的rfm”的相关知识。那么小编在网摘上网罗了一些有关“kmeans算法的rfm””的相关内容,希望朋友们能喜欢,同学们一起来了解一下吧!

有很多方法可以对客户进行分类并按组划分。但是由于这是讨论数据问题的地方,所以让我们使用数据方法来回答这个问题。

当您有数据时——比如客户列表和他们购买的产品——您需要使用这些数据创建具有类似特征的组,您需要一种聚类方法。聚类是无监督机器学习技术组的一部分。我们称它为无监督的,因为计算机之前没有关于如何对实体进行分组的信息。实际上,它将通过分析彼此之间的距离来尝试创建具有相似实体的聚类。

让我们开始讨论我们的研究案例。访问UCI并下载在线零售数据集()。该数据集由8个属性和541,909实例组成,显示了2010年12月1日至2011年12月9日英国在线零售发生的所有交易。据UCI介绍,公司主要销售独特的全天候礼品,很多客户都是批发商。

我们的主要目标是使用聚类技术将这些客户按客户细分进行分组。这里,我们将使用K-Means。但是,如何对这些客户进行分组呢?使用哪些变量?我们可以尝试使用RFM(最近一次消费,消费频率,消费金额)方法来分析客户。这种方法是用来评估客户价值的,我们稍后会详细讨论。

所以首先要做的是加载我们的库和数据并做一些探索性的数据分析。Python代码如下:

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

data = pd.read_excel('data/retail.xlsx')

data.head()

稍后我们将详细讨论这些值。现在,我们已经查找了空值并删除了它们。让我们也花些时间研究数据集上的惟一值。您将看到,我们现在有来自37个国家的客户(我们删除了一些空条目——我们以前有38个国家)和4,372个惟一客户。Python代码如下:

data.isna().any()

data = data[pd.notnull(data['CustomerID'])]

data.isna().any()

data.nunique()

我们能做的就是describe()在数据集上提供的主要数字统计信息的帮助下进行检查。当你这样做时,注意一些有趣的事情:数量的最小值是负数。为什么?我老实说不知道。但是因为这个案例的负数没有任何意义,所以我们也将它们排除在外。

data.describe()

data = data[data.Quantity >= 0]

data.describe()

开始RFM

你还记得我说过我们将使用RFM来我们的客户吗?让我们现在开始。

根据维基百科,RFM代表三个维度:

Recency ——客户最近购买了什么?Frequency ——他们多久购买一次?Monetary Value ——他们花了多少钱?

对于RFM,我们可以做的一件事是为每个维度从1到5打分,这是我们最希望的行为。我们稍后再计算分数。我们首先需要创建一个由recency, the frequency 和the monetary value组成的新数据框架。

为了计算recency,我们将查看发票日期。因为我们最后一张发票的日期是2011-12-09,所以我们认为这是最近的一张。

为了计算Frequency ,我们将简单地计算每个客户的发票号码。对于Monetary Value,我们将单位价格乘以购买的数量,然后为每个客户求和。

Python实现如下:

import datetime as dt

print('Most recent invoice is from:')

print(data['InvoiceDate'].max())

lastDate = dt.datetime(2011,12,10)

data['InvoiceDate'] = pd.to_datetime(data['InvoiceDate'])

Most recent invoice is from:

2011-12-09 12:50:00

data['TotalPrice'] = data.UnitPrice * data.Quantity

rfmTable = data.groupby('CustomerID').agg({'InvoiceDate': lambda x: (lastDate - x.max()).days,

'InvoiceNo': lambda x: len(x),

'TotalPrice': lambda x: x.sum()})

rfmTable['InvoiceDate'] = rfmTable['InvoiceDate'].astype(int)

rfmTable.rename(columns={'InvoiceDate': 'recency',

'InvoiceNo': 'frequency',

'TotalPrice': 'monetary'}, inplace=True)

rfmTable.head()

现在,我们要计算分数。我们是这样做的:首先,我们在降序模式下按频率对数据进行排序。然后,我们将数据集上的客户数量除以5。我们为前面创建的每个段分配一个从5到1的数字。我们也来看看“monetary”和“recency”列。

注意:对于“recency”一栏,由于最近的订单更好,我们将按升序排序。

我将把分数添加到一个名为rfmTableScores的新数据集中 .Python代码如下:

# Create f_score

f_score = []

m_score = []

r_score = []

columns = ['frequency', 'monetary']

scores_str = ['f_score', 'm_score']

scores = [f_score, m_score]

for n in range(len(columns)):

# Order by column

rfmTable = rfmTable.sort_values(columns[n], ascending=False)

# Create new index

refs = np.arange(1,4340)

rfmTable['refs'] = refs

# Add score

for i, row in rfmTable.iterrows():

if row['refs'] <= 866:

scores[n].append(5)

elif row['refs'] > 866 and row['refs'] <= 866*2:

scores[n].append(4)

elif row['refs'] > 866*2 and row['refs'] <= 866*3:

scores[n].append(3)

elif row['refs'] > 866*3 and row['refs'] <= 866*4:

scores[n].append(2)

else:

scores[n].append(1)

# Create f_score column

rfmTable[scores_str[n]] = scores[n]

# For recency, we do the opposite: most recents are better, so we order as ascending

rfmTable = rfmTable.sort_values('recency', ascending=True)

# Recreate index

refs = np.arange(1,4340)

rfmTable['refs'] = refs

# Add score

for i, row in rfmTable.iterrows():

if row['refs'] <= 866:

r_score.append(5)

elif row['refs'] > 866 and row['refs'] <= 866*2:

r_score.append(4)

elif row['refs'] > 866*2 and row['refs'] <= 866*3:

r_score.append(3)

elif row['refs'] > 866*3 and row['refs'] <= 866*4:

r_score.append(2)

else:

r_score.append(1)

# Create f_score column

rfmTable['r_score'] = r_score

rfmTableScores = rfmTable.drop(['frequency', 'monetary', 'recency', 'refs'], axis=1)

rfmTableScores.head(5)

由于我们的分数在1到5之间,因此我们不需要缩放数字。

我们现在可以开始考虑这个机器学习模型了。K-Means模型只能对您在数据集上的信息进行聚类,但您必须选择所需的聚类数量。您可以使用K-Means模型本身做出此决定。为此,让我们创建聚类内的平方和(WCSS)以支持我们的决策。Python实现如下:

from sklearn.cluster import KMeans

wcss = []

for i in range(1,11):

kmeans = KMeans(n_clusters=i, init='k-means++', random_state=0)

kmeans.fit(rfmTableScores)

wcss.append(kmeans.inertia_)

plt.plot(range(1,11), wcss)

plt.title('Elbow graph')

plt.xlabel('Cluster number')

plt.ylabel('WCSS')

plt.show()

通过肘部法则生成的图显示最佳聚类数为4.这是线开始缓慢下降的点。现在,让我们构建机器学习模型。Python实现如下:

kmeans = KMeans(n_clusters=4, init='k-means++', random_state=0)

clusters = kmeans.fit_predict(rfmTableScores)

rfmTable['clusters'] = clusters

rfmTable.head()

我们已经完成了聚类过程。如您所见,由于R,F和M分数分析,聚类被分配给每个客户。

让我们绘制一个图表,显示聚类过程之前的数据点以及聚类过程之后的一些图表。所以你可以清楚地看到形成的聚类。Python代码如下:

from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(15,10))

ax = fig.add_subplot(111, projection='3d')

ax.scatter(rfmTable.recency, rfmTable.frequency, rfmTable.monetary, s=50)

ax.set_xlabel('Recency')

ax.set_ylabel('Frequency')

ax.set_zlabel('Monetary')

fig = plt.figure(figsize=(15,10))

dx = fig.add_subplot(111, projection='3d')

colors = ['blue', 'yellow', 'green', 'red']

for i in range(0,4):

dx.scatter(rfmTable[rfmTable.clusters == i].recency,

rfmTable[rfmTable.clusters == i].frequency,

rfmTable[rfmTable.clusters == i].monetary,

c = colors[i],

label = 'Cluster ' + str(i+1),

s=50)

dx.set_title('Clusters of clients')

dx.set_xlabel('Recency')

dx.set_ylabel('Frequency')

dx.set_zlabel('Monetary')

dx.legend()

c1 = rfmTable[rfmTable.clusters == 0]

c2 = rfmTable[rfmTable.clusters == 1]

c3 = rfmTable[rfmTable.clusters == 2]

c4 = rfmTable[rfmTable.clusters == 3]

plt.scatter(c1.recency, c1.frequency, c = 'blue', label = 'Cluster 1')

plt.scatter(c2.recency, c2.frequency, c = 'yellow', label = 'Cluster 2')

plt.scatter(c3.recency, c3.frequency, c = 'green', label = 'Cluster 3')

plt.scatter(c4.recency, c4.frequency, c = 'red', label = 'Cluster 4')

plt.title('Clusters of clients')

plt.xlabel('Recency')

plt.ylabel('Frequency')

plt.legend()

c1 = rfmTable[rfmTable.clusters == 0]

c2 = rfmTable[rfmTable.clusters == 1]

c3 = rfmTable[rfmTable.clusters == 2]

c4 = rfmTable[rfmTable.clusters == 3]

plt.scatter(c1.frequency, c1.monetary, c = 'blue', label = 'Cluster 1')

plt.scatter(c2.frequency, c2.monetary, c = 'yellow', label = 'Cluster 2')

plt.scatter(c3.frequency, c3.monetary, c = 'green', label = 'Cluster 3')

plt.scatter(c4.frequency, c4.monetary, c = 'red', label = 'Cluster 4')

plt.title('Clusters of clients')

plt.xlabel('Frequency')

plt.ylabel('Monetary')

plt.legend()

c1 = rfmTable[rfmTable.clusters == 0]

c2 = rfmTable[rfmTable.clusters == 1]

c3 = rfmTable[rfmTable.clusters == 2]

c4 = rfmTable[rfmTable.clusters == 3]

plt.scatter(c1.recency, c1.monetary, c = 'blue', label = 'Cluster 1')

plt.scatter(c2.recency, c2.monetary, c = 'yellow', label = 'Cluster 2')

plt.scatter(c3.recency, c3.monetary, c = 'green', label = 'Cluster 3')

plt.scatter(c4.recency, c4.monetary, c = 'red', label = 'Cluster 4')

plt.title('Clusters of clients')

plt.xlabel('Recency')

plt.ylabel('Monetary')

plt.legend()

标签: #kmeans算法的rfm