【火爐煉AI】機器學習027-專案案例:用聚類演算法建立客戶細分模型

煉丹老頑童發表於2018-09-07

【火爐煉AI】機器學習027-專案案例:用聚類演算法建立客戶細分模型

(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

客戶細分是市場營銷成功的前提,我們從市場中獲取的資料一般都沒有標記,要想對這些市場資料進行客戶細分,將客戶劃分簇群,這也是一種典型的無監督學習問題。

本專案擬用各種不同的聚類演算法來建立客戶細分模型,並比較這些聚類演算法在這一問題上的優虐。


1. 準備資料集

本專案案例所使用到的原始資料集來源於: UCI大學資料集,這個資料集來源於一個批發商,一共包含有440個樣本資料,每個樣本資料包含有8列,但是其中的6列作為features,此處由於是無監督學習,不需要標記,故而只需要其中的六列資料,這些資料的說明如下表所示。

【火爐煉AI】機器學習027-專案案例:用聚類演算法建立客戶細分模型

對於這6個features,資料集已經告訴我們這6列的min,max mean等資訊,我把它們整理成一個表格,如下所示:

【火爐煉AI】機器學習027-專案案例:用聚類演算法建立客戶細分模型

資料集的載入可以採用pd.read_csv函式來完成,程式碼可以參考我的github,下面我們隨便選擇兩個feature,將其繪製到二維平面圖上,看看這些資料點的分佈情況,比如下圖:

(X=fresh y=milk)的資料分佈圖

(X=grocery, y=delicassen)的資料分佈圖


2. 構建均值漂移聚類模型

本專案用均值漂移演算法來構建模型,模型的構建和訓練過程和我以前的文章【火爐煉AI】機器學習022-使用均值漂移聚類演算法構建模型一樣,如下程式碼,只不過該程式碼還列印出聚類後簇群的數量,並把每一種簇群的質心點位置列印出來。

# 構建均值漂移聚類模型
from sklearn.cluster import MeanShift, estimate_bandwidth
bandwidth=estimate_bandwidth(dataset,quantile=0.8,
                             n_samples=len(dataset))
meanshift=MeanShift(bandwidth=bandwidth,bin_seeding=True)
meanshift.fit(dataset) # 使用評估的頻寬構建均值漂移模型,並進行訓練
labels=meanshift.labels_
cluster_num=len(np.unique(labels))
centroids=meanshift.cluster_centers_
# 下面列印出簇群種類,和質心位置資訊
print('Number of Clusters: {}'.format(cluster_num))
print('\t'.join([col_name[:5] for col_name in col_names]))
for centroid in centroids:
    print('\t'.join(str(int(x)) for x in centroid))
複製程式碼

------------------------輸---------出--------------------------------

Number of Clusters: 8
Fresh Milk Groce Froze Deter Delic
9632 4671 6593 2570 2296 1248
40204 46314 57584 5518 25436 4241
16117 46197 92780 1026 40827 2944
22925 73498 32114 987 20070 903
112151 29627 18148 16745 4948 8550
36847 43950 20170 36534 239 47943
32717 16784 13626 60869 1272 5609
8565 4980 67298 131 38102 1215

-------------------------------完-------------------------------------

由此可見,均值漂移演算法自動將本專案的資料集劃分為8個不同類別,那麼怎麼檢視聚類演算法的效果圖了?我先自定義了一個顯示函式,用於展示各種不同聚類演算法在不同資料集上的聚類效果,這個函式有一定的通用性,不僅可以可以用於均值漂移演算法,還可以用於其他的各種聚類演算法。如下為程式碼和執行結果。

def visual_cluster_effect(cluster,dataset,title,col_id):
    assert isinstance(col_id,list) and len(col_id)==2,'col_id must be list type and length must be 2'
    
    labels=cluster.labels_ # 每一個樣本對應的簇群號碼
#     print(labels.shape) # (440,) 440個樣本
    markers=['.',',','o','v','^','<','>','1','2','3','4','8'
                 ,'s','p','*','h','H','+','x','D','d','|']
    colors=['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 
            'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan']
    
    # 將資料集繪製到圖表中
    plt.figure()
    for class_id in set(labels):
        one_class=dataset[class_id==labels]
        print('label: {}, smaple_num: {}'.format(class_id,len(one_class)))
        plt.scatter(one_class[:,0],one_class[:,1],marker=markers[class_id%len(markers)],
                    c=colors[class_id%len(colors)],label='class_'+str(class_id))
    plt.legend()
        
    # 將中心點繪製到圖中
    centroids=meanshift.cluster_centers_
#     print(centroids.shape)# eg (8, 6) 8個簇群,6個features
    plt.scatter(centroids[:,col_id[0]],centroids[:,col_id[1]],marker='o',
                s=100,linewidths=2,color='k',zorder=5,facecolors='b')
    plt.title(title) 
    plt.xlabel('feature_0')
    plt.ylabel('feature_1')
    plt.show()
複製程式碼

使用這個函式,我們可以看到本聚類演算法在資料集上的表現,如下程式碼中,我們主要檢視Fresh vs milk這一類產品的聚類效果。

visual_cluster_effect(meanshift,dataset,'MeanShift-X=fresh,y=milk',[0,1]) # X=fresh, y=milk 
複製程式碼

-------------------------輸---------出--------------------------------

label: 0, smaple_num: 428
label: 1, smaple_num: 3
label: 2, smaple_num: 1
label: 3, smaple_num: 1
label: 4, smaple_num: 3
label: 5, smaple_num: 1 label: 6, smaple_num: 1
label: 7, smaple_num: 2

-------------------------------完-------------------------------------

均值漂移演算法在資料集(X=fresh,y=milk)的表現

visual_cluster_effect(meanshift,dataset,'MeanShift-X=grocery,y=delica',[2,5]) # X=grocery, y=delicassen
複製程式碼

均值漂移演算法在資料集(X=grocery,y=delica)的表現

從上面的圖中我們很難看出模型到底是好還是壞,那我們就用指標來判斷吧,前面我們學習過輪廓係數,可以用來評估模型的優虐,如下是評價程式碼。

# 使用輪廓係數評估模型的優虐
from sklearn.metrics import silhouette_score
si_score=silhouette_score(dataset,meanshift.labels_,
                          metric='euclidean',sample_size=len(dataset))
print('si_score: {:.4f}'.format(si_score))
複製程式碼

----------------輸---------出--------------------------------

si_score: 0.6548

---------------------完-------------------------------------

########################小**********結###############################

1,本文的資料集基本上都是已經處理過的,我們只需要載入後即可使用。

2,構建均值漂移演算法的模型和訓練該模型非常簡單,但是裡面額quantile引數可能需要進行優化才能得到最佳值。

3,為了檢視本聚類演算法在資料集上的表現優虐,我們先通過資料視覺化,將聚類之後的簇群以及簇群質心繪製到圖示中,這是一個多features資料集,故而資料的視覺化只能一次取其中的兩列來檢視。

4,另外,我們還用輪廓係數來評估模型的好壞,此處模型的輪廓係數為0.6548,貌似不是太差,但也不是太好,看來還有優化空間,或者,我們可以採用其他演算法來構建模型,比如前面我們學習到的K-means,DBSCAN,凝聚層次聚類等,看看其輪廓係數。

#################################################################


注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章