大數據【企業級360°全方位用戶畫像】之RFM模型和KMeans聚類算法

寫在前面: 博主是一名軟件工程系大數據應用開發專業大二的學生,暱稱來源於《愛麗絲夢遊仙境》中的Alice和自己的暱稱。作爲一名互聯網小白,寫博客一方面是爲了記錄自己的學習歷程,一方面是希望能夠幫助到很多和自己一樣處於起步階段的萌新。由於水平有限,博客中難免會有一些錯誤,有紕漏之處懇請各位大佬不吝賜教!個人小站:http://alices.ibilibili.xyz/ , 博客主頁:https://alice.blog.csdn.net/
儘管當前水平可能不及各位大佬,但我還是希望自己能夠做得更好,因爲一天的生活就是一生的縮影。我希望在最美的年華,做最好的自己

        在上一篇博客《一文帶你硬核踏入機器學習的大門》中,已經爲大家介紹了很多關於機器學習的基礎內容。本篇博客,我們將結合當前階段正在做的用戶畫像項目,爲大家介紹RFM模型KMeans聚類算法

        先贊後看,養成習慣!
在這裏插入圖片描述


一、RFM模型引入

        比如電商網站要做一次營銷活動,需要針對不同價值的客戶羣體進行分羣,對於高價值的用戶推薦手錶,珠寶等高端商品,對於低價值用戶推薦打折促銷的廉價商品,當然還有以下這些問題都是需要考慮的:

        1.誰是我的最佳客戶?

        2.誰即將要成爲流失客戶?

        3.誰將有潛力成爲有價值的客戶

        4.哪些客戶能夠留存?

        5.哪些客戶會對你目前對活動有所反應?

        那麼最終的問題是如何對客戶進行分羣,即如何建立客戶的價值模型呢?

        在傳統企業和電商衆多的客戶細分模型中,RFM模型是被廣泛提到和使用的。
        RFM模型是衡量當前用戶價值和客戶潛在價值的重要工具和手段。

        RFM是Rencency(最近一次消費),Frequency(消費頻率)、Monetary(消費金額),三個指標首字母組合,如圖所示:
在這裏插入圖片描述
        一般情況下RFM模型可以說明下列幾個事實:

        1.最近購買的時間越近,用戶對產品促銷互動越大

        2.客戶購買的頻率越高,客戶就品牌的滿意度就越大

        3.貨幣價值將高消費客戶和低消費客戶區分開來


        如圖所示,根據RFM模型,就可以統計在某一段時間內,用戶最近的消費間隔,消費次數和消費金額,再根據使用 k-means 算法對用戶進行聚類分羣

        注意一點,不僅僅可以侷限於這三個數據字段,還可以根據業務需求,加入其他字段,進行調整模型。
在這裏插入圖片描述
        我們可以根據RFM模型計算出所有用戶的RFM值形成一個二維表:

userid R值 F值 M值
1 2019-11-01 5 10000
2 2019-10-01 4 800

        對於以上數據的量綱不一致(單位不統一),所以要對數據進行歸一化

        如何歸一化? 我們可以自定義歸一化的規則!即建立一個評分標準。

        那如何建立評分標準?我們可以根據運營/產品的經驗,做一個標準,就像這樣:

R: 1-3天=5分,4-6天=4分,7-9天=3分,10-15天=2分,大於16天=1分
F: ≥200=5分,150-199=4分,100-149=3分,50-99=2分,1-49=1分
M: ≥20w=5分,10-19w=4分,5-9w=3分,1-4w=2分,<1w=1分

        根據上面的打分規則就可以對數據進行自定義的歸一化,得到如下類似結果:

userid R值 F值 M值
1 5 1 2
2 1 1 1

        那麼現在數據已經歸一化了,如何對數據進行分類?

        肯定不能簡單的將數據直接丟到三維座標系,因爲座標系的原點不好確定,且三維座標系只能分爲8類。所以應該使用算法進行分類(聚類)。讓算法自動學習用戶之間的相似度,然後相似度高的用戶,自動聚成一類,最後完成聚類的劃分

計算流程

1、首先對所有用戶的最近一次消費時間/總共消費次數/總共消費金額進行統計
2、再進行歸一化(運營/產品提供的打分規則)
3、再使用算法進行聚類(K-Means)
4、根據聚類結果給用戶打Tag(標籤)

1、RFM詳解

1.1 R值:最近一次消費(Recency)

        消費指的是客戶在店鋪消費最近一次和上一次的時間間隔,理論上R值越小的客戶是價值越高的客戶,即對店鋪的回購幾次最有可能產生迴應。目前網購便利,顧客已經有了更多的購買選擇和更低的購買成本,去除地域的限制因素,客戶非常容易流失,因此CRM操盤手想要提高回購率和留存率,需要時刻警惕R值。

        如下圖,某零食網店用戶最近一次消費R值分佈圖:
在這裏插入圖片描述
        1、客戶R值呈規律性的“波浪形”分佈,時間越長,波浪越小;

        2、最近一年內用戶佔比50%(真的很巧);

        數據分析:這個數據根據向行業內專業人員請教,已經是比較理想了的。說明每引入2個客戶,就有一位用戶在持續購買。說明店鋪復購做的比較好。

1.2 F值:消費頻率(Frequency)

        消費頻率是客戶在固定時間內的購買次數(一般是1年)。但是如果實操中實際店鋪由於受品類寬度的原因,比如賣3C產品,耐用品等即使是忠實粉絲用戶也很難在1年內購買多次。所以,有些店鋪在運營RFM模型時,會把F值的時間範圍去掉,替換成累計購買次數。

        如下圖,某零食網店用戶購買頻次圖(如1個客戶在1天內購買多筆訂單,則自動合併爲1筆訂單):
在這裏插入圖片描述
        1、購買1次(新客戶)佔比爲65.5%,產生重複購買(老客戶)的佔比爲34.4%;

        2、購買3次及以上(成熟客戶)的佔比爲17%,購買5次及以上(忠實客戶)的佔比爲6%;

        數據分析:影響復購的核心因素是商品,因此復購不適合做跨類目比較。比如食品類目和美妝類目:食品是屬於“半標品”,產品的標品化程度越高,客戶背叛的難度就越小,越難形成忠實用戶;但是相對美妝,食品又屬於易耗品,消耗週期短,購買頻率高,相對容易產生重複購買,因此跨類目復購併不具有可比性。

1.3 M值:消費金額(Monetary)

        M值是RFM模型中相對於R值和F值最難使用,但最具有價值的指標。大家熟知的“二八定律”(又名“帕雷託法則”)曾作出過這樣的解釋:公司80%的收入來自於20%的用戶。

        這個數據我在自己所從事的公司總都得到過驗證!可能有些店鋪不會那麼精確,一般也會在30%客戶貢獻70%收入,或者40%貢獻60%收入。

        理論上M值和F值是一樣的,都帶有時間範圍,指的是一段時間(通常是1年)內的消費金額,在工作中我認爲對於一般店鋪的類目而言,產品的價格帶都是比較單一的,比如:同一品牌美妝類,價格浮動範圍基本在某個特定消費羣的可接受範圍內,加上單一品類購買頻次不高,所以對於一般店鋪而言,M值對客戶細分的作用相對較弱。

        所以我認爲用店鋪的累計購買金額和平均客單價替代傳統的M值能更好的體現客戶消費金額的差異。

        教大家一個特別簡單的累積金額劃分方法:將1/2的客單價作爲累積消費金額的分段,比如客單價是300元,則按照150元進行累計消費金額分段,得出十個分段。

        現以國內某知名化妝品店鋪舉例,店鋪平均客單爲160元,因此以80元作爲間隔將累積消費金額分段,從表中可以很明顯發現,累計消費160元以下用戶佔比爲65.5%(近2/3),貢獻的店鋪收入比例只佔31.6%(近1/3),具體如下:
在這裏插入圖片描述

2、 基於RFM模型的實踐應用

        主要有兩種方法來分析RFM模型的結果:用基於RFM模型的劃分標準來進行客戶細分,用基於RFM模型的客戶評分來進行客戶細分。

2.1 基於RFM模型進行客戶細分

        CRM實操時可以選擇RFM模型中的1-3個指標進行客戶細分,如下表所示。切記細分指標需要在自己可操控的合理範圍內,並非越多越好,一旦用戶細分羣組過多,一來會給自己的營銷方案執行帶來較大的難度,而來可能會遺漏用戶羣或者對同個用戶造成多次打擾。

        最終選擇多少個指標有兩個參考標準:店鋪的客戶基數,店鋪的商品和客戶結構。
在這裏插入圖片描述
        店鋪的客戶基數:在店鋪客戶一定的情況下選擇的維度越多,細分出來每一組的用戶越少。對於店鋪基數不大(5萬以下客戶數)的店鋪而言,選擇1-2個維度進行細分即可。對於客戶超過50萬的大賣家而言可以選擇2-3個指標。

        店鋪的商品和客戶結構:如果在店鋪的商品層次比較單一,客單價差異幅度不大的情況下,購買頻次(F值)和消費金額(M值)高度相關的情況下,可以只選擇比較容易操作的購買頻次(F值)代替消費金額(M值)。對於剛剛開店還沒形成客戶粘性的店鋪,則可以放棄購買頻次(F值),直接用最後一次消費(R值)或者消費金額(M值)。

2.2 通過RFM模型評分後輸出目標用戶

        除了直接用RFM模型對用戶進行分組之外,還有一種常見的方法是利用RFM模型的三個屬性對客戶進行打分,通過打分確定每個用戶的質量,最終篩選出自己的目標用戶。

        RFM模型評分主要有三個部分:

1、確定RFM三個指標的分段和每個分段的分值;
2、計算每個客戶RFM三個指標的得分;
3、計算每個客戶的總得分,並且根據總得分篩選出優質的客戶

        比如,實操的過程中一般每個指標分爲3-5段,其中R值可以根據開店以來的時間和產品的回購週期來判定,F值根據現有店鋪的平均購買頻次,M值可參考上文客單價的分段指標。

        舉個例子:
在這裏插入圖片描述
        確認RFM的分段和對應分段的分值之後,就可以按照用戶情況對應進行打分。

        這個時候可能有人會對此產生質疑,我如何驗證這個給予的分值就是合理的呢?一般使用經驗值或用算法模型進行驗證。

        這裏提供一個段子,可謂是很形象了。

在這裏插入圖片描述

二、KMeans聚類算法

1、算法原理

        在正式開始之前,我們可以先通過幾個網址來感受一下KMeans的魅力。

        首先是 http://shabal.in/visuals/kmeans/3.html,我們可以通過刷新頁面多次,來觀察不同的KMeans聚類過程。下圖是我把四次不同的結果合併在一起的一個結果。
在這裏插入圖片描述
        通過觀察,我們可以得到初步結論:

  • 中心點數量4, 起始位置不相同。
  • 中心點可以移動
  • 中心點最後不移動

        第二個網址是 https://www.naftaliharris.com/blog/visualizing-k-means-clustering/

        這個網站更牛的一點是,可以自定義可視化K均值聚類。也就是,我們可以自定義K的數量,和初始位置,來查看不同的結果。

在這裏插入圖片描述
在這裏插入圖片描述
        初始情況下,大家應該看到的是下面這種情況
在這裏插入圖片描述
        接下來,我分別在圖中的四個位置設置質心的位置
在這裏插入圖片描述
        然後不斷的點擊Go

在這裏插入圖片描述
        最後可能會看到類似如下的結果:
在這裏插入圖片描述        再讓我們來看下其他的解釋
在這裏插入圖片描述
        最後將不同種類的數據分到了不同的區域。有點類似班級位置的一個分佈😂
在這裏插入圖片描述
        爲了節約碼字的時間,下面藉助一些PPT來爲大家說明
在這裏插入圖片描述
在這裏插入圖片描述
        我們可以得出,KMeans的計算步驟

1、選擇 K 個點作爲初始聚類中心
2、計算其他的點到中心點的距離, 進行聚類, 使用歐式距離
3、重新計算每個聚類的中心點, 再次聚類
4、直到中心點不再變化, 或者達到迭代次數

在這裏插入圖片描述
在這裏插入圖片描述

2、快速體驗

        接下來讓我們來感受一下KMeans的魅力。

2.1 數據集

        IRIS數據集由Fisher在1936年整理的一個經典數據集,在統計學習和機器學習領域都經常被用作示例。

        數據集內包含 3 類共 150 條記錄,每類各 50 個數據,每條數據包含4個特徵,都是浮點數,單位爲釐米。

Sepal.Length(花萼長度)
Sepal.Width(花萼寬度)
Petal.Length(花瓣長度)
Petal.Width(花瓣寬度))

        目標值爲鳶尾花的分類:

Iris Setosa(山鳶尾)
Iris Versicolour(雜色鳶尾)
Iris Virginica(維吉尼亞鳶尾)

        其中的數據分佈如下:
在這裏插入圖片描述
        
在這裏插入圖片描述

2.2 代碼演示

import org.apache.spark.ml.clustering.{KMeans, KMeansModel}
import org.apache.spark.ml.feature.{MinMaxScaler, MinMaxScalerModel}
import org.apache.spark.sql.{DataFrame, SparkSession}

/*
用於實現  使用 kmeans 爲鳶尾花數據分類
 */
object Iris {

  def main(args: Array[String]): Unit = {

    //1、創建sparlsession對象
    val spark: SparkSession = SparkSession.builder().appName("Iris").master("local[*]").getOrCreate()

    spark.sparkContext.setLogLevel("WARN")
     
    //2、讀取libsvm 數據
    val irisLibSvmDF: DataFrame = spark.read.format("libsvm")
      .load("file:///E:\\數據集\\iris_kmeans.txt")
    irisLibSvmDF.show(false)
  
    /*
 +-----+-------------------------------+
|label|features                       |
+-----+-------------------------------+
|1.0  |(4,[0,1,2,3],[5.1,3.5,1.4,0.2])|
|1.0  |(4,[0,1,2,3],[4.9,3.0,1.4,0.2])|
|1.0  |(4,[0,1,2,3],[4.7,3.2,1.3,0.2])|
|1.0  |(4,[0,1,2,3],[4.6,3.1,1.5,0.2])|
|1.0  |(4,[0,1,2,3],[5.0,3.6,1.4,0.2])|
     */

    //3、數據歸一化(將數據歸一到0-1之間,計算速度快)
    //數據歸一化
    //把數據映射到0~1範圍之內處理,更加便捷快速
    //MinMaxScaler  把有量綱表達式變成無量綱表達式,便於不同單位或量級的指標能夠進行比較和加權。
    //x' = (x - X_min) / (X_max - X_min)

    val scalerDatas: MinMaxScalerModel = new MinMaxScaler()
      .setInputCol("features") //設置需要歸一化的列
      .setOutputCol("featuresOut") //歸一化後的數據的列名字
      .fit(irisLibSvmDF) //設置數據


    val scalerDF: DataFrame = scalerDatas.transform(irisLibSvmDF)
    scalerDF.show(false)
/*
+-----+-------------------------------+---------------------------------------------------------------------------------+
|label|features                       |featuresOut                                                                      |
+-----+-------------------------------+---------------------------------------------------------------------------------+
|1.0  |(4,[0,1,2,3],[5.1,3.5,1.4,0.2])|[0.22222222222222213,0.6249999999999999,0.06779661016949151,0.04166666666666667] |
|1.0  |(4,[0,1,2,3],[4.9,3.0,1.4,0.2])|[0.1666666666666668,0.41666666666666663,0.06779661016949151,0.04166666666666667] |
|1.0  |(4,[0,1,2,3],[4.7,3.2,1.3,0.2])|[0.11111111111111119,0.5,0.05084745762711865,0.04166666666666667]                |
|1.0  |(4,[0,1,2,3],[4.6,3.1,1.5,0.2])|[0.08333333333333327,0.4583333333333333,0.0847457627118644,0.04166666666666667]  |
|1.0  |(4,[0,1,2,3],[5.0,3.6,1.4,0.2])|[0.19444444444444448,0.6666666666666666,0.06779661016949151,0.04166666666666667] |

 */

    //4、使用kmeans進行計算
    val prediction: KMeansModel = new KMeans()
      .setK(3) //設置需要劃分類別的數量/個數
      .setMaxIter(10) //設置最大計算次數
      .setFeaturesCol("featuresOut") //設置特徵的列    歸一化後的列
      .setPredictionCol("predictionValue") //設置最終預測後的結果列名
      .setSeed(10) //設置隨機種子
      .fit(scalerDF)
    

    val predictionDF: DataFrame = prediction.transform(scalerDF)
    predictionDF.show(false)
    
    /*
+-----+-------------------------------+---------------------------------------------------------------------------------+---------------+
|label|features                       |featuresOut                                                                      |predictionValue|
+-----+-------------------------------+---------------------------------------------------------------------------------+---------------+
|1.0  |(4,[0,1,2,3],[5.1,3.5,1.4,0.2])|[0.22222222222222213,0.6249999999999999,0.06779661016949151,0.04166666666666667] |0              |
|1.0  |(4,[0,1,2,3],[4.9,3.0,1.4,0.2])|[0.1666666666666668,0.41666666666666663,0.06779661016949151,0.04166666666666667] |0              |
|1.0  |(4,[0,1,2,3],[4.7,3.2,1.3,0.2])|[0.11111111111111119,0.5,0.05084745762711865,0.04166666666666667]                |0              |
|1.0  |(4,[0,1,2,3],[4.6,3.1,1.5,0.2])|[0.08333333333333327,0.4583333333333333,0.0847457627118644,0.04166666666666667]  |0              |
|1.0  |(4,[0,1,2,3],[5.0,3.6,1.4,0.2])|[0.19444444444444448,0.6666666666666666,0.06779661016949151,0.04166666666666667] |0              |
|1.0  |(4,[0,1,2,3],[5.4,3.9,1.7,0.4])|[0.30555555555555564,0.7916666666666665,0.11864406779661016,0.12500000000000003] |0              |
     */


    //簡單驗證
    predictionDF.groupBy("label","predictionValue").count().show()
  /*
+-----+---------------+-----+
|label|predictionValue|count|
+-----+---------------+-----+
|  2.0|              1|   47|
|  1.0|              0|   50|
|  2.0|              2|    3|
|  3.0|              1|   14|
|  3.0|              2|   36|
+-----+---------------+-----+

*/

  }
}

結語

        本篇博客,主要爲大家簡單介紹了RFM模型和KMeans聚類算法,後續會將其與用戶畫像的項目結合起來,爲大家講解挖掘型標籤開發的過程,敬請期待😎

        如果以上過程中出現了任何的紕漏錯誤,煩請大佬們指正😅

        受益的朋友或對大數據技術感興趣的夥伴記得點贊關注支持一波🙏

        希望我們都能在學習的道路上越走越遠😉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章