使用ML.NET實現基於RFM模型的客戶價值分析


RFM模型


在眾多的客戶價值分析模型中,RFM模型是被廣泛應用的,尤其在零售和企業服務領域堪稱經典的分類手段。它的核心定義從基本的交易數據中來,借助恰當的聚類算法,反映出對客戶較為直觀的分類指示,對於沒有數據分析和機器學習技術支撐的初創企業,它是簡單易上手的客戶分析途徑之一。

RFM模型主要有三項指標:

Recency:最近消費時間間隔

Frequency:消費頻率

Monetary:消費金額

我們為客戶在這三項指標上進行打分,那么總共會有27種組合的可能,使用K-Means算法,能夠縮減到指定的有限數量的分箱(一般會為5類),計算出每個客戶在分箱的位置即客戶的價值。

當然RFM模型還有更多衍生版本,可以參考WiKi:RFM (customer value)

ML.NET和K-Means


ML.NET自v0.2版本就提供了K-Means++ clustering的實現,也是非監督學習最常見的訓練,正好適用於為RFM模型的分類執行機器學習。

動手實踐


基本要求

  • Visual Studio 2017 或者 Visual Studio Code
  • DotNet Core 2.0+
  • ML.NET v0.3

數據來源

本案例數據來自UCI:Online Retail,這是一個跨國數據集,其中包含2010年12月1日至2011年12月9日期間在英國注冊的非商店在線零售業務中發生的所有交易。該公司主要銷售獨特的全場禮品。該公司的許多客戶都是批發商。

屬性信息:

InvoiceNo:發票編號。標稱值,為每個事務唯一分配的6位整數。如果此代碼以字母'c'開頭,則表示取消。

StockCode:產品(項目)代碼。標稱值,為每個不同的產品唯一分配的5位整數。

Description:產品(項目)名稱。標稱。

Quantity:每筆交易的每件產品(項目)的數量。數字。

InvoiceDate:發票日期和時間。數字,生成每個事務的日期和時間。

UnitPrice:單價。數字,英鎊單位產品價格。

CustomerID:客戶編號。標稱值,為每個客戶唯一分配的5位整數。

Country:國家名稱。每個客戶所在國家/地區的名稱。

數據處理

  1. 使用Excel,對原始數據增加4個字段,分別是Amount(金額,單價與數量相乘的結果)、Date(InvoiceDate的整數值)、Today(當天日期的整數值)、DateDiff(當天與Date的差值)。

  1. 建立透視圖,獲取每個客戶在Amount上的總和,DateDiff的最大和最小值,並且通過計算公式Amount/(DateDiff最大值-DateDiff最小值+1)算出頻率值。

  1. 按照以下規則計算RFM的評分
    • R:(DateDiff最大值- DateDiff最小值-2000)的差值,小於480計3分,480-570之間計2分,570-750之間計1分,大於750計0分。
    • F:頻率值,大於1000計5分,500-1000之間計4分,100-500之間計3分,50-100之間計2分,0-50之間計1分,小於0計0分。
    • M:Amount總和值,大於10000計5分,5000-10000之間計4分,2000-5000之間計3分,1000-2000之間計2分,0-1000之間計1分,小於0計0分。

有小伙伴可能存在疑問,為什么要這么划分,其實這就是對數據分布合理分段的一種思想,為了減小數據源的不平衡性對機器學習的影響,我們盡量使得數據的分布是自然的。

編碼部分

還是熟悉的味道,創建DotNet Core控制台應用程序,通過Nuget添加對ML.NET的引用。

  • 創建用於學習的數據結構
public class ClusteringPrediction
{
    [ColumnName("PredictedLabel")]
    public uint SelectedClusterId;
    [ColumnName("Score")]
    public float[] Distance;
}

public class ClusteringData
{
    [Column(ordinal: "0")]
    public string CustomId;

    [Column(ordinal: "1")]
    public float Amount;

    [Column(ordinal: "2")]
    public float MinDataDiff;

    [Column(ordinal: "3")]
    public float MaxDataDiff;

    [Column(ordinal: "4")]
    public float MeanAmount;

    [Column(ordinal: "5")]
    public float M;

    [Column(ordinal: "6")]
    public float F;

    [Column(ordinal: "7")]
    public float RelativaDataDiff;

    [Column(ordinal: "8")]
    public float R;
}
  • 訓練部分
static PredictionModel<ClusteringData, ClusteringPrediction> Train()
{
    int n = 1000;
    int k = 5;

    var textLoader = new Microsoft.ML.Data.TextLoader(DataPath).CreateFrom<ClusteringData>(useHeader: true, separator: ',', trimWhitespace: false);
    var pipeline = new LearningPipeline();
    pipeline.Add(textLoader);
    pipeline.Add(new ColumnConcatenator("Features",
                                        "R",
                                        "M",
                                        "F"));
    pipeline.Add(new KMeansPlusPlusClusterer() { K = k });
    var model = pipeline.Train<ClusteringData, ClusteringPrediction>();

    return model;
}
  • 評估部分
static void Evaluate(PredictionModel<ClusteringData, ClusteringPrediction> model)
{
    var textLoader = new Microsoft.ML.Data.TextLoader(DataPath).CreateFrom<ClusteringData>(useHeader: true, separator: ',', trimWhitespace: false);
    var evaluator = new ClusterEvaluator();
    var metrics = evaluator.Evaluate(model, textLoader);
    Console.WriteLine("AvgMinScore:{0}", metrics.AvgMinScore);
    Console.WriteLine("Dbi:{0}", metrics.Dbi);
    Console.WriteLine("Nmi:{0}", metrics.Nmi);
}
  • 預測部分
static void Predict(PredictionModel<ClusteringData, ClusteringPrediction> model)
{
    var predictedData = new ClusteringData()
    {
        R = 3F,
        M = 3F,
        F = 1F
    };
    var predictedResult = model.Predict(predictedData);
    Console.WriteLine("the predicted cluster id is: {0}", predictedResult.SelectedClusterId);
}
  • 調用部分
static void Main(string[] args)
{
    var model = Train();
    Evaluate(model);
    Predict(model);
}
  • 運行結果

可以看到,我用於測試的客戶,被分到了第2類上面。

盡管完成了聚類的工作,對於學習出來的這5個類別,仍然需要按原始數據集全部遍歷預測出對應的分類,根據客戶的RFM評分與分類的對應關系,才能夠對每個類別的意義進行有效地解釋。

結尾


這個簡單的案例為大家展示了使用ML.NET完成聚類的機器學習。對於想要上手針對自己公司的業務,進行一些門檻較低的客戶分析,使用ML.NET將是一個不錯的選擇。當然ML.NET還在不斷迭代中,希望大家持續關注新的特性功能發布。

完整代碼如下:

using Microsoft.ML;
using Microsoft.ML.Models;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Trainers;
using Microsoft.ML.Transforms;
using System;

namespace RMFClusters
{
    class Program
    {
        const string DataPath = @".\Data\Online Retail.csv";

        public class ClusteringPrediction
        {
            [ColumnName("PredictedLabel")]
            public uint SelectedClusterId;
            [ColumnName("Score")]
            public float[] Distance;
        }

        public class ClusteringData
        {
            [Column(ordinal: "0")]
            public string CustomId;

            [Column(ordinal: "1")]
            public float Amount;

            [Column(ordinal: "2")]
            public float MinDataDiff;

            [Column(ordinal: "3")]
            public float MaxDataDiff;

            [Column(ordinal: "4")]
            public float MeanAmount;

            [Column(ordinal: "5")]
            public float M;

            [Column(ordinal: "6")]
            public float F;

            [Column(ordinal: "7")]
            public float RelativaDataDiff;

            [Column(ordinal: "8")]
            public float R;
        }

        static PredictionModel<ClusteringData, ClusteringPrediction> Train()
        {
            int n = 1000;
            int k = 5;

            var textLoader = new Microsoft.ML.Data.TextLoader(DataPath).CreateFrom<ClusteringData>(useHeader: true, separator: ',', trimWhitespace: false);
            var pipeline = new LearningPipeline();
            pipeline.Add(textLoader);
            pipeline.Add(new ColumnConcatenator("Features",
                                               "R",
                                               "M",
                                               "F"));
            pipeline.Add(new KMeansPlusPlusClusterer() { K = k });
            var model = pipeline.Train<ClusteringData, ClusteringPrediction>();

            return model;
        }

        static void Evaluate(PredictionModel<ClusteringData, ClusteringPrediction> model)
        {
            var textLoader = new Microsoft.ML.Data.TextLoader(DataPath).CreateFrom<ClusteringData>(useHeader: true, separator: ',', trimWhitespace: false);
            var evaluator = new ClusterEvaluator();
            var metrics = evaluator.Evaluate(model, textLoader);
            Console.WriteLine("AvgMinScore:{0}", metrics.AvgMinScore);
            Console.WriteLine("Dbi:{0}", metrics.Dbi);
            Console.WriteLine("Nmi:{0}", metrics.Nmi);
        }

        static void Predict(PredictionModel<ClusteringData, ClusteringPrediction> model)
        {
            var predictedData = new ClusteringData()
            {
                R = 3F,
                M = 5F,
                F = 1F
            };
            var predictedResult = model.Predict(predictedData);
            Console.WriteLine("the predicted cluster id is: {0}", predictedResult.SelectedClusterId);
        }

        static void Main(string[] args)
        {
            var model = Train();
            Evaluate(model);
            Predict(model);
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM