免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
python聚類分析實現(xiàn)電商用戶細(xì)分(基于RFM用戶價值分析模型)

背景

聚類分析在機器學(xué)習(xí)領(lǐng)域?qū)儆跓o監(jiān)督學(xué)習(xí)的一種,能夠根據(jù)一些特征對樣本數(shù)據(jù)進(jìn)行分類。使用聚類分析分完的類具有“類中相似,類間區(qū)別”的特點。RFM模型是非常常見的分析用戶價值的方法,其核心思想是根據(jù)用戶的最近購買時間、購買頻次、花費金額3個特征來對用戶進(jìn)行分群,針對每個群體采取不同的營銷手段。k-means是常用的聚類分析算法之一,基于歐氏距離對樣本進(jìn)行分類。k-means算法運行速度快,能夠處理的數(shù)據(jù)量大,且易于理解。但缺點也很明顯,就是算法性能有限,在高維上可能不是最佳選項。在當(dāng)前動輒上億的數(shù)據(jù)量來看,k-means算法是比較好的選擇了。還有需要提醒的一點是,一定要結(jié)合業(yè)務(wù)使用算法,任何特征都可能拿來聚類,但是聚類的結(jié)果呢,能不能很好的解釋和指導(dǎo)業(yè)務(wù)?如果不能,那么這個算法就沒有什么意義。本次使用的數(shù)據(jù)來源于數(shù)據(jù)不吹牛公眾號,這里也是小打一波廣告。
本案例將從一個簡單的k-means機器學(xué)習(xí)模型入手,在介紹聚類算法的同時也簡單介紹機器學(xué)習(xí)的常規(guī)步驟。

1、數(shù)據(jù)概覽

首先,我們導(dǎo)入數(shù)據(jù),并查看前5行。

import pandas as pd import numpy as np df = pd.read_excel(r'F:\數(shù)據(jù)分析項目\電商數(shù)據(jù)的RFM模型\RFM\PYTHON-RFM實戰(zhàn)數(shù)據(jù).xlsx') df.head(5)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4


總覽數(shù)據(jù):

df.info()
  • 1
  • 1


數(shù)據(jù)共有28833行,9列,而且數(shù)據(jù)非常干凈,沒有空值,省去了我們處理空值的過程。
根據(jù)RFM模型的要求,我們需要的是買家昵稱、購買日期、實付金額三個變量。其中購買日期和實付金額用于幫助我們訓(xùn)練模型,買家昵稱則讓我們確定每個用戶所屬的類別。

選取交易成功的用戶:

df['訂單狀態(tài)'].value_counts() df = df[df['訂單狀態(tài)'] == '交易成功']
  • 1
  • 2
  • 1
  • 2


選擇我們需要的字段:

data = df[['買家昵稱', '付款日期',  '實付金額']]
data.head(5)
  • 1
  • 2
  • 1
  • 2

有個細(xì)節(jié)需要注意,訂單每一行代表著單個用戶的單次購買行為,什么意思呢?如果一個用戶在一天內(nèi)購買了4次,訂單表對應(yīng)記錄著4行,而在實際的業(yè)務(wù)場景中,一個用戶在一天內(nèi)的多次消費行為,應(yīng)該從整體上看作一次。 ----- 數(shù)據(jù)不吹牛 小Z

2、特征構(gòu)建

根據(jù)我們的RFM模型,我們需要構(gòu)建3列數(shù)據(jù),這個原始表中是沒有直接提供的,需要我們根據(jù)原始表的數(shù)據(jù)來提取。
所以這里需要先提取付款日期數(shù)據(jù):

data['paytime'] = pd.to_datetime(data['付款日期'].apply(lambda x:x.date())) data.head()
  • 1
  • 2
  • 1
  • 2


根據(jù)paytime計算最后一次付款時間距當(dāng)前的天數(shù)(數(shù)據(jù)引用的背景當(dāng)前時間是2019-07-01):

# 提取每個用戶最近(最大)的購買日期
data_r = data.groupby('買家昵稱')['paytime'].max().reset_index()
# 與當(dāng)前日期相減,取得最近一次購買距當(dāng)前的天數(shù)。
data_r['recency'] = data_r['paytime'].apply(lambda x:(pd.to_datetime('2019-07-01')-x).days)
# 兩個日期相減,得到的數(shù)據(jù)類型是timedelta類型,要進(jìn)行數(shù)值計算,需要提取出天數(shù)數(shù)字。
data_r.drop('paytime',axis = 1,inplace = True)
data_r.head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


提取購買次數(shù)數(shù)據(jù):

# 分組聚合,得到每個用戶發(fā)生于不同日期的購買次數(shù) data_f = data.groupby(['買家昵稱','paytime'])['付款日期'].count().reset_index() data_f = data_f.groupby('買家昵稱')['paytime'].count().reset_index() # 修改列名 data_f.rename({'paytime':'frequence'},axis = 1,inplace = True) data_f.head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


提取購買金額數(shù)據(jù),這里的金額我們使用每個用戶的金額/次:

data_m = data.groupby('買家昵稱')['實付金額'].sum().reset_index()
data_m['money'] = data_m['實付金額']/data_f['frequence']
data_m.drop('實付金額',axis = 1,inplace = True)
data_m.head()
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4


所以現(xiàn)在我們已經(jīng)有了包含recency、frequence、money的3個DataFrame表了,下面合并三個表:

data_rf = pd.merge(data_r,data_f,on = '買家昵稱',how = 'inner') data_rfm = pd.merge(data_rf,data_m, on = '買家昵稱',how = 'inner') data_rfm.head()
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

3、查看數(shù)據(jù)分布特征

數(shù)據(jù)的分布特征會影響算法結(jié)果,所以有必要先了解數(shù)據(jù)的大致分布。

import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize = (6,4))
sns.set(style = 'darkgrid')
sns.countplot(data_rfm['frequence'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

sns.distplot(data_rfm['recency']) plt.title('recency的分布直方圖',fontsize = 15)
  • 1
  • 2
  • 1
  • 2

sns.distplot(data_rfm['money'],color = 'g')
plt.title('money的分布直方圖',fontsize = 15)
  • 1
  • 2
  • 1
  • 2

4、數(shù)據(jù)處理及模型構(gòu)造

首先,對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理,這是為了消除量綱的影響。

from sklearn import preprocessing from sklearn.cluster import KMeans from sklearn import metrics data_rfm_s = data_rfm.copy() min_max_scaler = preprocessing.MinMaxScaler() data_rfm_s = min_max_scaler.fit_transform(data_rfm[['recency','frequence','money']])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

K-Means方法有個經(jīng)常被人詬病的地方,如何選擇K值?也就是要把樣本分成多少類呢?如果貿(mào)然定一個,會太主觀,所以還是要用數(shù)據(jù)說話。一般采用三個指標(biāo):

  • Calinski-Harabaz Index。通過計算類中各點與類中心的距離平方和來度量類內(nèi)的緊密度,通過計算各類中心點與數(shù)據(jù)集中心點距離平方和來度量數(shù)據(jù)集的分離度,CH指標(biāo)由分離度與緊密度的比值得到。從而,CH越大代表著類自身越緊密,類與類之間越分散,即更優(yōu)的聚類結(jié)果。
  • 輪廓系數(shù)。輪廓系數(shù)(Silhouette Coefficient),值是介于 [-1,1] ,越趨近于1代表內(nèi)聚度和分離度都相對較優(yōu)。也就是盡量選擇更大的輪廓系數(shù)。
  • inertia值。kmeans自帶的評價方法,越小說明聚類效果越好。
inertia = []
ch_score = []
ss_score = []
for k in range(2,9):
    model = KMeans(n_clusters = k, init = 'k-means++',max_iter = 500)
    model.fit(data_rfm_s)
    pre = model.predict(data_rfm_s)
    ch = metrics.calinski_harabaz_score(data_rfm_s,pre) 
    ss = metrics.silhouette_score(data_rfm_s,pre)
    inertia.append(model.inertia_)
    ch_score.append(ch)
    ss_score.append(ss)
print(ch_score,ss_score,inertia)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

畫圖可以更加直觀看出三個指標(biāo)的變化:

score = pd.Series([ch_score,ss_score,inertia],index = ['ch_score','ss_score','inertia']) aa = score.index.tolist() plt.figure(figsize = (15,6)) j = 1 for i in aa: plt.subplot(1,3,j) plt.plot(list(range(2,9)),score[i]) plt.xlabel('k的數(shù)目',fontsize = 13) plt.ylabel(f'{i}值',fontsize = 13) plt.title(f'{i}值變化趨勢',fontsize = 15) j+=1 plt.subplots_adjust(wspace = 0.3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12


根據(jù)上圖中3個指標(biāo)綜合判斷,選擇k=4時,各指標(biāo)變化出現(xiàn)明顯的拐點,聚類效果相對較優(yōu),所以分成四類比較好。

model = KMeans(n_clusters = 4, init = 'k-means++',max_iter = 500)
model.fit(data_rfm_s)
ppre = model.predict(data_rfm_s)
ppre = pd.DataFrame(ppre)
data = pd.concat([data_rfm,ppre],axis = 1)
data.rename({0:u'cluster'},axis = 1,inplace = True)
data.head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


可以看出,每個用戶都有了對應(yīng)的類別,并且可以查看每個類別的中心:

labels = model.labels_ # 取得各樣本的類別數(shù)據(jù) labels = pd.DataFrame(labels,columns = ['類別']) result = pd.concat([pd.DataFrame(model.cluster_centers_),labels['類別'].value_counts().sort_index()],axis = 1) result.columns = ['recency','frequence','money','cluster'] result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5


cluster=0時的分布狀態(tài):

cluster=1時的分布狀態(tài):

cluster=2時的分布狀態(tài):

cluster=3時的分布狀態(tài):

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
航空公司客戶價值分析模型LRFCM模型
手把手教你如何利用K均值聚類實現(xiàn)異常值的識別
Python實現(xiàn)基于機器學(xué)習(xí)的RFM模型
用TSNE進(jìn)行數(shù)據(jù)降維并展示聚類結(jié)果
數(shù)據(jù)挖掘——聚類分析總結(jié)(建議收藏)
python分類預(yù)測模型的特點
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服