AI時代的網站與手機App建置與開發Part18 - 使用ML.NET執行客戶分群

 

·       摘要

將無標示(Unlabeled)的資料進行分群是一種實用的機器學習演算法, 例如利用客戶歷史交易資料, 購物喜好, 年齡層, 性別, 國籍, 或居住地將客戶分群, 以進行精準行銷與客戶經營就是分群(Clustering)演算法的典型應用場合. 透過客戶分群的幫助, 企業能夠有效地為目標客群配置行銷資源, 鞏固某種客群, 或是將特定的廣告傳送給特定的客群, 以利於業務推行.

: 依據身高和體重將人分類的示意圖

·       認識分群演算法

區分客戶族群會依據客戶的特質將客戶區分成不同的族群, 例如:

ü  喜愛高收益, 但是低風險承受的族群

ü  傾向購買某種類型商品的族群

ü  傾向訂閱某種商品的族群

ü  非營利組織的的族群

ü  分析商店的人流, 支援開店選址

ü  等等

區分客戶族群能夠得到兩種層面的效益:

1       對客戶的效益

ü  客戶認為廠商在乎他們的需求

ü  客戶認為廠商記得他們的喜好

2     對企業的效益

ü  最佳化行銷預算配置

ü  提升客戶生涯貢獻

ü  提升客戶服務和客戶體驗

ü  為不同的客戶打造最佳行銷管道

ü  改良商品功能

ü  發掘最佳貢獻客戶

·       使用K-means演算法實作客戶分群

在我們的範例中, 我們將使用K-means演算法執行客戶群的工作. 使用K-means演算法對資料進行分群的優點與缺點如下:

優點:

ü  容易實作

ü  適合處理大量資料

ü  保證收歛

缺點:

ü  必須人工設定k(Hyperparameter)

ü  使用不同的初始核心結果會不相同

ü  不適用大小和密度會變動的群組

ü  易受異常資料影響

ü  易受大量的資料與特徵數量影響

ü  不適合非圓形的群組(例如橢圓形或半月形的群組)

首先請到以下的網址下載欲分析的客戶資料:

ü  Mall Customer Segmentation Data(下載網址: https://www.kaggle.com/datasets/shwetabh123/mall-customers

下載得到的客戶資料如圖1所示

1: 欲分群的客戶資料

其中的欄位說明如下:

1.        CustomerID欄位 : 客戶編號

2.        Gender欄位 :  客戶性別. 1代表男性, 2代表女性

3.        Age欄位 : 客戶年齡

4.        AnnualIncome欄位 : 客戶年消費金額

5.        SpendingScore欄位 : 客戶年消費分數

·       使用k-means演算法對客戶資料進行分群

因為我們將使用OxyPlot程式庫繪出使用K-means演算法分組客戶的結果, 所以我們將會使用Visual Studio 2022建立[WPF應用程式]型態的專案, 方便顯示使用OxyPlot程式庫繪製的統計圖.

建立妥WPF應用程式專案後請定義描述欲分析的客戶資料的MallCustomerData類別:

public class MallCustomerData

{

    [LoadColumn(0)]

    public uint CustomerID { get; set; }

    //[LoadColumn(1)]

    //public string GenderText { get; set; }

    [LoadColumn(2)]

    public float Age { get; set; }

    [LoadColumn(3)]

    public float AnnualIncomeInK { get; set; }

    [LoadColumn(4)]

    public float SpendingScore { get; set; }

    [LoadColumn(5)]

    public float Gender { get; set; }

}

定義描述分群結果的MallCustomerData類別:

public class MallCustomerPrediction

{

    [KeyType(5)]        // 5 is the number of clusters

    [ColumnName("PredictedLabel")]

    public uint PredictedClusterId;

    [ColumnName("Score")]

    public float[] Distances;

    // Copy columns from source data (automatically bound to source data)

    public uint CustomerID { get; set; }

    public float Gender { get; set; }

    public float Age { get; set; }

    public float AnnualIncomeInK { get; set; }

    public float SpendingScore { get; set; }

}

使用K-means演算法分群客戶的資料://欲分群的客戶資料

string dataPath = "mall_customers.csv";

//建立MLContext

var mlContext = new MLContext();

Trace.WriteLine("Loading data for the clustering...");

// 載入欲分析的資料

IDataView dataset = mlContext.Data.LoadFromTextFile<MallCustomerData>(dataPath, hasHeader: true, separatorChar: ',');

Trace.WriteLine("Splitting data into clusters...");

//設定k-means演算法的參數

var kmo = new KMeansTrainer.Options

{

    NumberOfClusters = 3,             //建立利用Elbow演算法取得

    FeatureColumnName = "Features",

    InitializationAlgorithm = KMeansTrainer.InitializationAlgorithm.KMeansPlusPlus,

    MaximumNumberOfIterations = 1000,

    AccelerationMemoryBudgetMb = 4096,

    NumberOfThreads = null,

    OptimizationTolerance = (float)Math.Pow(10, -7),

    ExampleWeightColumnName = null

};

//建立k-means演算法模型

var trainer = mlContext.Clustering.Trainers.KMeans(kmo);

//建立訓練管線

var pipeline = mlContext.Transforms.Concatenate(

    "Features", "Gender", "Age", "AnnualIncomeInK", "SpendingScore")

    Append(trainer);

//執行資料轉換與訓練

IDataView transformedDataView = pipeline.Fit(dataset).Transform(dataset);

//依據K-means分群演算法的輸出結果進行GroupBy運算

var enumerable = mlContext.Data

.CreateEnumerable<MallCustomerPrediction>(transformedDataView,

reuseRowObject: false).ToList();

var clusters = enumerable.GroupBy(r => r.PredictedClusterId);

//顯示客戶分群結果

foreach (var cluster in clusters)

{

    Trace.WriteLine($"CustomerID,Gender,Age,Annual Income (K), Spending Score-${cluster.Key}");

foreach (var row in cluster)

{

     Trace.WriteLine($"{row.CustomerID},{row.Gender},{row.Age},                                                                                      {row.AnnualIncomeInK},{row.SpendingScore}");

  }

}

//利用OxyPlot程式庫繪製K-means演算法分群的客戶結果

var originalData = mlContext.Data.CreateEnumerable<MallCustomerData>(

dataset, reuseRowObject: false).ToList();

var plotModel = new PlotModel { Title = "K-Means Clustering" };

// 使用三種顏色顯示不同的客戶族群

var clusterColors = new[] { OxyColors.Red, OxyColors.Green, OxyColors.Blue };

for (int i = 0; i < clusterColors.Length; i++)

{

  var clusterId = (uint)(i + 1); // Cluster IDs start at 1

  var scatterSeries = new ScatterSeries {  MarkerType = MarkerType.Circle, MarkerFill =                                                                                                clusterColors[i] };

  foreach (var (dataPoint, prediction) in originalData.Zip(enumerable, (dp, cp) => (dp, cp)))

  {

    if (prediction.PredictedClusterId == clusterId)

    {

       //依據客戶年消費金額和年消費分數檢視客戶的族群

scatterSeries.Points.Add(new ScatterPoint(                                                                                                            dataPoint.SpendingScore, dataPoint.AnnualIncomeInK));

     }

   }

   plotModel.Series.Add(scatterSeries);

}

// 將繪製的統計圖顯示到WPF應用程式

var plotView = new PlotView { Model = plotModel };

Content = plotView;

執行上述的程式, 您將會看到以下的客戶分群結果


2: 依據客戶年消費金額和年消費分數檢視客戶的族群

除了圖2的統計圖以外, 您也可以在Visual Studio的輸出視窗看到隷屬於各個群組的客戶清單, 如圖3所示:


3: 隷屬於各個群組的客戶清單

範例下載網址:

https://github.com/CraigIII/ClusterCustomers

留言

這個網誌中的熱門文章

AI時代的網站與手機App建置與開發Part27 - ML.NET與物件偵測

AI時代的網站與手機App建置與開發Part24 - ML.NET與圖片異常偵測

AI時代的網站與手機App建置與開發Part28 - 使用YOLO模型進行物件偵測